IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 40932


Ignore:
Timestamp:
Oct 9, 2019, 2:15:34 PM (7 years ago)
Author:
fairlamb
Message:

Added local rsync to subprocess and how to handle it in backups (functionally the same as cp)

Location:
branches/ipp-259_genericise_backups/tools/backups
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • branches/ipp-259_genericise_backups/tools/backups/backup.py

    r40931 r40932  
    181181
    182182    def _run_rsync(self):
    183         raise Exception("Not implemented")
     183        if self.run_rsync is None or False:
     184            return 0
     185
     186        backup_paths = self.default_dict['backup_paths']
     187        for bp in backup_paths:
     188            if not path.exists(bp):
     189                raise errs.ValidationError(f"ValidationError: target path does not exist: {bp}")
     190
     191            for s in self.rsync_dict['sources']:
     192                if not path.exists(s):
     193                    raise errs.ValidationError(f"ValidationError: target path does not exist: {s}")
     194                try:
     195                    args = [s, bp]
     196                    if 'additional_args' in self.rsync_dict.keys():
     197                        print("hiya")
     198                        args = args + self.rsync_dict['additional_args']
     199                        print(args)
     200                    sub_utils.local_rsync_wrapper(args)
     201                except errs.SubprocessError as e:
     202                    raise errs.SubprocessError( f"Error: rsync\n"
     203                                                f"    from: {s}\n"
     204                                                f"    to: {bp}\n"
     205                                              ) from e
     206        return 0
    184207
    185208    def _run_mysqldump(self):
    186209
    187         # cfg_help.ConfigSchemaLine('user', True, str)
    188         # cfg_help.ConfigSchemaLine('password', True, str)
    189         # cfg_help.ConfigSchemaLine('db_name', True, str)
    190         # cfg_help.ConfigSchemaLine('additional_args', False, list, cfg_help.SpecialSchemaProcessing.space_separated)
    191         # cfg_help.ConfigSchemaLine('target_filename', True, str)
    192         # cfg_help.ConfigSchemaLine('prefix_date', True, bool)
    193 
    194210        backup_paths = self.default_dict['backup_paths']
    195211
    196         # Setup the commands:
    197212        mysqldump_args = [ 'mysqldump'
    198213                         , '-u', self.mysqldump_dict['user']
  • branches/ipp-259_genericise_backups/tools/backups/backup_test.py

    r40931 r40932  
    186186        assert os.path.exists(expected2file)
    187187
    188     def copy_fails_if_source_file_does_not_exist(self, tmpdir):
     188    def test_copy_fails_if_source_file_does_not_exist(self, tmpdir):
    189189        config = make_default_config(tmpdir, ['bck1', 'bck2'])
    190190        source = os.path.join(tmpdir, "and_specific_file.jpeg")
     
    196196        assert not os.path.exists(source)
    197197        backy = Backup(config)
    198         with pytest.raises(errs.SubprocessError):
     198        with pytest.raises(errs.ValidationError):
    199199            backy._run_copy()
    200200
    201     def copy_fails_if_destination_does_not_exist(self, tmpdir):
     201    def test_copy_fails_if_destination_does_not_exist(self, tmpdir):
    202202        config = ConfigParser()
    203203
     
    214214        assert not os.path.exists(backup_does_not_exist)
    215215        backy = Backup(config)
    216         with pytest.raises(errs.SubprocessError):
     216        with pytest.raises(errs.ValidationError):
    217217            backy._run_copy()
    218218
     
    298298
    299299
    300 # class TestRunningRsync():
    301 
    302 #     def test_simply_rsync(self):
    303 #         assert True is False
    304 
    305 #     def test_rsync_with_additional_args(self):
    306 #         assert True is False
     300class TestRunningRsync():
     301
     302    def test_simple_rsync(self, tmpdir):
     303        config = make_default_config(tmpdir, ['bck1', 'bck2'])
     304        source = os.path.join(tmpdir, "and_specific_file.jpeg")
     305        config['RSYNC'] = {'sources' : f"{source}"}
     306
     307        # make file to be copied
     308        Path(source).touch()
     309
     310        backy = Backup(config)
     311
     312        expected1file = os.path.join(tmpdir, 'bck1', 'and_specific_file.jpeg')
     313        expected2file = os.path.join(tmpdir, 'bck2', 'and_specific_file.jpeg')
     314        assert not os.path.exists(expected1file)
     315        assert not os.path.exists(expected2file)
     316        backy._run_rsync()
     317        assert os.path.exists(expected1file)
     318        assert os.path.exists(expected2file)
     319
     320    def test_rsync_with_additional_args(self, tmpdir):
     321        config = make_default_config(tmpdir, ['bck1', 'bck2'])
     322        source1 = os.path.join(tmpdir, "some_dir")
     323        source2 = os.path.join(tmpdir, "and_specific_file.jpeg")
     324        config['RSYNC'] = \
     325        { 'sources' : f"{source1}, {source2}"
     326        , 'additional_args' : "-v -z -r --progress"
     327        }
     328
     329        os.makedirs(source1)
     330        Path(source2).touch()
     331
     332        backy = Backup(config)
     333
     334        expected1dir  = os.path.join(tmpdir, 'bck1', 'some_dir')
     335        expected1file = os.path.join(tmpdir, 'bck1', 'and_specific_file.jpeg')
     336        expected2dir  = os.path.join(tmpdir, 'bck2', 'some_dir')
     337        expected2file = os.path.join(tmpdir, 'bck2', 'and_specific_file.jpeg')
     338        assert not os.path.exists(expected1dir)
     339        assert not os.path.exists(expected1file)
     340        assert not os.path.exists(expected2dir)
     341        assert not os.path.exists(expected2file)
     342        backy._run_rsync()
     343        assert os.path.exists(expected1dir)
     344        assert os.path.exists(expected1file)
     345        assert os.path.exists(expected2dir)
     346        assert os.path.exists(expected2file)
     347
     348    def test_rsync_fails_if_source_file_does_not_exist(self, tmpdir):
     349        config = make_default_config(tmpdir, ['bck1', 'bck2'])
     350        source = os.path.join(tmpdir, "and_specific_file.jpeg")
     351        config['RSYNC'] = \
     352        { 'sources' : f"{source}"
     353        , 'additional_args' : '-r'
     354        }
     355
     356        assert not os.path.exists(source)
     357        backy = Backup(config)
     358        with pytest.raises(errs.ValidationError):
     359            backy._run_rsync()
     360
     361    def test_rsync_fails_if_destination_does_not_exist(self, tmpdir):
     362        config = ConfigParser()
     363
     364        backup_does_not_exist = os.path.join(tmpdir, 'does_not_exist')
     365
     366        config['DEFAULT'] = \
     367        { 'backup_paths' : backup_does_not_exist
     368        , 'source_machine': socket.gethostname()
     369        }
     370        source = os.path.join(tmpdir, "and_specific_file.jpeg")
     371        Path(source).touch()
     372        config['RSYNC'] = {'sources' : f"{source}"}
     373
     374        assert not os.path.exists(backup_does_not_exist)
     375        backy = Backup(config)
     376        with pytest.raises(errs.ValidationError):
     377            backy._run_rsync()
     378
     379    def test_rsync_requires_dash_r_arg_for_copying_dirs(self, tmpdir):
     380        config = make_default_config(tmpdir, ['bck1', 'bck2'])
     381        source = os.path.join(tmpdir, "some_dir")
     382        config['RSYNC'] = \
     383        { 'sources' : f"{source}"
     384        }
     385        os.makedirs(source)
     386
     387        backy = Backup(config)
     388        expected1dir  = os.path.join(tmpdir, 'bck1', 'some_dir')
     389        expected2dir  = os.path.join(tmpdir, 'bck2', 'some_dir')
     390        assert not os.path.exists(expected1dir)
     391        assert not os.path.exists(expected2dir)
     392        backy._run_rsync()
     393        assert not os.path.exists(expected1dir)
     394        assert not os.path.exists(expected2dir)
     395
     396        config['RSYNC'] = \
     397        { 'sources' : f"{source}"
     398        , 'additional_args' : '-r'
     399        }
     400
     401        backy = Backup(config)
     402        expected1dir  = os.path.join(tmpdir, 'bck1', 'some_dir')
     403        expected2dir  = os.path.join(tmpdir, 'bck2', 'some_dir')
     404        assert not os.path.exists(expected1dir)
     405        assert not os.path.exists(expected2dir)
     406        backy._run_rsync()
     407        assert os.path.exists(expected1dir)
     408        assert os.path.exists(expected2dir)
    307409
    308410
  • branches/ipp-259_genericise_backups/tools/backups/utils/subprocess_utils.py

    r40913 r40932  
    3434
    3535
     36def local_rsync_wrapper(args: [str]):
     37    if args is None:
     38        raise ValidationError(f"Error:no arguments provided to {local_rsync_wrapper.__name__}")
     39    command_and_args = ["rsync"] + args
     40    return simple_unix_wrapper(command_and_args)
     41
     42
    3643def simple_unix_wrapper(command_and_args: [str]):
    3744    """ This should provide the program name and all arguments in a list.
  • branches/ipp-259_genericise_backups/tools/backups/utils/subprocess_utils_test.py

    r40898 r40932  
    164164        assert bool(new_stats.st_mode & stat.S_IWOTH) is True
    165165        assert bool(new_stats.st_mode & stat.S_IXOTH) is True
     166
     167
     168class TestLocalRsyncWrapper(object):
     169    """This is essentially a copy of the 'copy' tests above.
     170    """
     171
     172    def test_rsync_raises_validation_error_with_no_args(self):
     173        with pytest.raises(ValidationError):
     174            utils.local_rsync_wrapper(None)
     175
     176    def test_rsync_fails_with_invalid_args(self, tmpdir):
     177        with pytest.raises(SubprocessError):
     178            utils.local_rsync_wrapper(["not a real file", "not a valid rsync_location"])
     179
     180    def test_rsync_fails_if_source_does_not_exist(self, tmpdir):
     181        with pytest.raises(SubprocessError):
     182            utils.local_rsync_wrapper(["not a real file", tmpdir])
     183
     184    def test_simple_rsync(self, tmpdir):
     185        real_file = make_a_real_file(tmpdir, "real_file.txt")
     186        expected_filepath = os.path.join(tmpdir, "copied_file.txt")
     187        assert not os.path.isfile(expected_filepath)
     188
     189        result = utils.local_rsync_wrapper(["-v", real_file, expected_filepath])
     190        assert os.path.isfile(expected_filepath)
     191        assert result == 0
     192
     193    def test_simple_rsync_to_directory(self, tmpdir):
     194
     195        # Setup source file and target dir
     196        filename = "real_file.txt"
     197        real_file = make_a_real_file(tmpdir, filename)
     198
     199        destination_dir = os.path.join(tmpdir, "destination")
     200        os.makedirs(destination_dir)
     201        assert os.path.exists(destination_dir)
     202
     203        expected_filepath = os.path.join(destination_dir, filename)
     204        assert not os.path.exists(expected_filepath)
     205
     206        # run rsync function and confirm rsync exists (and original)
     207        result = utils.local_rsync_wrapper([real_file, destination_dir])
     208        assert result == 0
     209        assert os.path.isfile(real_file)
     210        assert os.path.exists(expected_filepath)
     211
     212    def test_rsyncing_directories_and_subdirectories(self, tmpdir):
     213
     214        subdir = os.path.join(tmpdir, "subdir")
     215        subsubdir = os.path.join(subdir, "subsubdir")
     216        os.makedirs(subsubdir)
     217        filename_a = "file_in_subdir.txt"
     218        filename_b = "file_in_subsubdir.txt"
     219        make_a_real_file(subdir, filename_a)
     220        make_a_real_file(subsubdir, filename_b)
     221
     222        destination_dir = os.path.join(tmpdir, "destination")
     223        os.makedirs(destination_dir)
     224        expected_filepath_a = os.path.join(destination_dir, "subdir", filename_a)
     225        expected_filepath_b = os.path.join(destination_dir, "subdir", "subsubdir", filename_b)
     226        assert not os.path.exists(expected_filepath_a)
     227        assert not os.path.exists(expected_filepath_b)
     228
     229        # silently passes without -r, just skips over directories
     230        assert not os.path.exists(expected_filepath_a)
     231        assert not os.path.exists(expected_filepath_b)
     232
     233        utils.local_rsync_wrapper([subdir, destination_dir])
     234        assert not os.path.exists(expected_filepath_a)
     235        assert not os.path.exists(expected_filepath_b)
     236
     237        # requires -r to copy directories (and contents)
     238        utils.local_rsync_wrapper(["-r", subdir, destination_dir])
     239        assert os.path.exists(expected_filepath_a)
     240        assert os.path.exists(expected_filepath_b)
Note: See TracChangeset for help on using the changeset viewer.