Index: /branches/ipp-259_genericise_backups/tools/backups/backup.py
===================================================================
--- /branches/ipp-259_genericise_backups/tools/backups/backup.py	(revision 40922)
+++ /branches/ipp-259_genericise_backups/tools/backups/backup.py	(revision 40923)
@@ -4,5 +4,6 @@
 
 import backups.utils.config_parse_helper as cfg_help
-from backups.utils.errors import ConfigError
+import backups.utils.errors as errs
+import backups.utils.subprocess_utils as sub_utils
 from configparser import ConfigParser
 
@@ -24,5 +25,5 @@
         config = ConfigParser()
         if config_class_or_filepath is None:
-            raise ConfigError(config_class_or_filepath, "Neither config settings or filepath of config given")
+            raise errs.ConfigError(config_class_or_filepath, "Neither config settings or filepath of config given")
         elif isinstance(config_class_or_filepath, configparser.ConfigParser):
             config = config_class_or_filepath
@@ -119,2 +120,47 @@
         actual_hostname = socket.gethostname()
         return actual_hostname == self.default_dict['source_machine']
+
+    def run_backup(self):
+            self._run_copy()
+            self._run_tar()
+            self._run_rsync()
+            self._run_mysqldump()
+
+    def _run_copy(self):
+        if self.run_copy is None or False:
+            return 0
+
+        for bp in self.default_dict['backup_paths']:
+            if not path.exists(bp):
+                    raise errs.ValidationError(f"ValidationError: target path does not exist: {bp}")
+
+            for s in self.copy_dict['sources']:
+                if not path.exists(s):
+                    raise errs.ValidationError(f"ValidationError: target path does not exist: {s}")
+                try:
+                    args = [s, bp]
+                    if 'additional_args' in self.copy_dict.keys():
+                        print("hiya")
+                        args = args + self.copy_dict['additional_args']
+                    sub_utils.cp_wrapper(args)
+                except errs.SubprocessError as e:
+                    raise errs.SubprocessError( f"Error: copying\n"
+                                                f"    from: {s}\n"
+                                                f"    to: {bp}\n"
+                                              ) from e
+        return 0
+
+    def _run_tar(self):
+        if self.run_tar is None or False:
+            return False
+        return True
+
+    def _run_rsync(self):
+        if self.run_rsync is None or False:
+            return False
+        return True
+
+    def _run_mysqldump(self):
+        if self.run_mysqldump is None or False:
+            return False
+        return True
Index: /branches/ipp-259_genericise_backups/tools/backups/backup_test.py
===================================================================
--- /branches/ipp-259_genericise_backups/tools/backups/backup_test.py	(revision 40922)
+++ /branches/ipp-259_genericise_backups/tools/backups/backup_test.py	(revision 40923)
@@ -3,7 +3,8 @@
 import socket
 from configparser import ConfigParser
-
+from pathlib import Path
+
+import backups.utils.errors as errs
 from backups.backup import Backup
-from backups.utils.errors import ConfigError
 
 
@@ -17,7 +18,11 @@
     config = ConfigParser()
 
+    # make the paths:
+    for b in backup_targs:
+        os.makedirs(os.path.join(tmpdir, b))
+
+    # Get the correct formats for the config
     backup_paths = ','.join([os.path.join(tmpdir, b) for b in backup_targs])
     source_machine = socket.gethostname()
-
     config['DEFAULT'] = \
     {
@@ -98,11 +103,11 @@
     def test_failure_if_no_defaults_provided(self):
         config = ConfigParser()
-        with pytest.raises(ConfigError):
+        with pytest.raises(errs.ConfigError):
             Backup(config_file=config)
 
-        with pytest.raises(ConfigError):
+        with pytest.raises(errs.ConfigError):
             Backup(config_file=None)
 
-        with pytest.raises(ConfigError):
+        with pytest.raises(errs.ConfigError):
             Backup(config_file="/not/a/real/file.config")
 
@@ -130,2 +135,135 @@
         backy.default_dict['source_machine'] = actual_hostname
         assert backy.hostname_is_valid() is True
+
+
+class TestRunningCopy():
+
+    def test_simple_copy(self, tmpdir):
+        config = make_default_config(tmpdir, ['bck1', 'bck2'])
+        source = os.path.join(tmpdir, "and_specific_file.jpeg")
+        config['COPY'] = {'sources' : f"{source}"}
+
+        # make file to be copied
+        Path(source).touch()
+
+        backy = Backup(config)
+
+        expected1file = os.path.join(tmpdir, 'bck1', 'and_specific_file.jpeg')
+        expected2file = os.path.join(tmpdir, 'bck2', 'and_specific_file.jpeg')
+        assert not os.path.exists(expected1file)
+        assert not os.path.exists(expected2file)
+        backy._run_copy()
+        assert os.path.exists(expected1file)
+        assert os.path.exists(expected2file)
+
+    def test_copy_with_additional_args(self, tmpdir):
+        config = make_default_config(tmpdir, ['bck1', 'bck2'])
+        source1 = os.path.join(tmpdir, "some_dir")
+        source2 = os.path.join(tmpdir, "and_specific_file.jpeg")
+        config['COPY'] = \
+        { 'sources' : f"{source1}, {source2}"
+        , 'additional_args' : "-v --preserve -r"
+        }
+
+        os.makedirs(source1)
+        Path(source2).touch()
+
+        backy = Backup(config)
+
+        expected1dir  = os.path.join(tmpdir, 'bck1', 'some_dir')
+        expected1file = os.path.join(tmpdir, 'bck1', 'and_specific_file.jpeg')
+        expected2dir  = os.path.join(tmpdir, 'bck2', 'some_dir')
+        expected2file = os.path.join(tmpdir, 'bck2', 'and_specific_file.jpeg')
+        assert not os.path.exists(expected1dir)
+        assert not os.path.exists(expected1file)
+        assert not os.path.exists(expected2dir)
+        assert not os.path.exists(expected2file)
+        backy._run_copy()
+        assert os.path.exists(expected1dir)
+        assert os.path.exists(expected1file)
+        assert os.path.exists(expected2dir)
+        assert os.path.exists(expected2file)
+
+    def copy_fails_if_source_file_does_not_exist(self, tmpdir):
+        config = make_default_config(tmpdir, ['bck1', 'bck2'])
+        source = os.path.join(tmpdir, "and_specific_file.jpeg")
+        config['COPY'] = \
+        { 'sources' : f"{source}"
+        , 'additional_args' : '-r'
+        }
+
+        assert not os.path.exists(source)
+        backy = Backup(config)
+        with pytest.raises(errs.SubprocessError):
+            backy._run_copy()
+
+    def copy_fails_if_destination_does_not_exist(self, tmpdir):
+        config = ConfigParser()
+
+        backup_does_not_exist = os.path.join(tmpdir, 'does_not_exist')
+
+        config['DEFAULT'] = \
+        { 'backup_paths' : backup_does_not_exist
+        , 'source_machine': socket.gethostname()
+        }
+        source = os.path.join(tmpdir, "and_specific_file.jpeg")
+        Path(source).touch()
+        config['COPY'] = {'sources' : f"{source}"}
+
+        assert not os.path.exists(backup_does_not_exist)
+        backy = Backup(config)
+        with pytest.raises(errs.SubprocessError):
+            backy._run_copy()
+
+    def test_copy_requires_dash_r_arg_for_copying_dirs(self, tmpdir):
+        config = make_default_config(tmpdir, ['bck1', 'bck2'])
+        source = os.path.join(tmpdir, "some_dir")
+        config['COPY'] = \
+        { 'sources' : f"{source}"
+        }
+        os.makedirs(source)
+
+        with pytest.raises(errs.SubprocessError):
+            backy = Backup(config)
+            backy._run_copy()
+
+        config['COPY'] = \
+        { 'sources' : f"{source}"
+        , 'additional_args' : '-r'
+        }
+        backy = Backup(config)
+
+        expected1dir  = os.path.join(tmpdir, 'bck1', 'some_dir')
+        expected2dir  = os.path.join(tmpdir, 'bck2', 'some_dir')
+        assert not os.path.exists(expected1dir)
+        assert not os.path.exists(expected2dir)
+        backy._run_copy()
+        assert os.path.exists(expected1dir)
+        assert os.path.exists(expected2dir)
+
+
+# class TestRunningTar():
+
+#     def test_simply_tar(self):
+#         assert True is False
+
+#     def test_tar_with_additional_args(self):
+#         assert True is False
+
+
+# class TestRunningRsync():
+
+#     def test_simply_rsync(self):
+#         assert True is False
+
+#     def test_rsync_with_additional_args(self):
+#         assert True is False
+
+
+# class TestRunningMysqldump():
+
+#     def test_simply_mysqldump(self):
+#         assert True is False
+
+#     def test_mysqldump_with_additional_args(self):
+#         assert True is False
