IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 40931


Ignore:
Timestamp:
Oct 9, 2019, 11:25:06 AM (7 years ago)
Author:
fairlamb
Message:

added mysqldump to the backup class + tests; tests are skipped as they require some mysql setup

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

Legend:

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

    r40924 r40931  
    33import os.path as path
    44import socket
     5import subprocess
    56
    67import backups.utils.config_parse_helper as cfg_help
     
    156157            return 0
    157158
    158         dests = self.default_dict['backup_paths']
     159        backup_paths = self.default_dict['backup_paths']
    159160
    160161        filename = self.tar_dict['target_filename']
    161162        if 'prefix_date' in self.tar_dict.keys() and self.tar_dict['prefix_date']:
    162163            filename = f"{get_date()}_{filename}"
    163         filename = path.join(dests[0], filename)  # may need some tar suffix magic
     164        filename = path.join(backup_paths[0], filename)  # may need some tar suffix magic
    164165
    165166        add_args = [] if 'additional_args' not in self.tar_dict.keys() else self.tar_dict['additional_args']
     
    171172            sub_utils.chmod_wrapper(['774', filename])
    172173            # copy to backups
    173             if len(dests) == 1:
     174            if len(backup_paths) == 1:
    174175                return 0
    175             for d in range(1, len(dests)):
    176                 sub_utils.cp_wrapper([ filename, dests[d]])
     176            for d in range(1, len(backup_paths)):
     177                sub_utils.cp_wrapper([ filename, backup_paths[d]])
    177178        except errs.SubprocessError as e:
    178179            raise errs.SubprocessError() from e
     
    183184
    184185    def _run_mysqldump(self):
    185         raise Exception("Not implemented")
     186
     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
     194        backup_paths = self.default_dict['backup_paths']
     195
     196        # Setup the commands:
     197        mysqldump_args = [ 'mysqldump'
     198                         , '-u', self.mysqldump_dict['user']
     199                         , f"-p{self.mysqldump_dict['password']}"
     200                         , '--databases', self.mysqldump_dict['db_name']
     201                         ]
     202        if 'additional_args' in self.mysqldump_dict.keys():
     203            mysqldump_args = mysqldump_args + self.mysqldump_dict['additional_args']
     204
     205        dump_filename = self.mysqldump_dict['target_filename']
     206        if 'prefix_date' in self.mysqldump_dict.keys() and self.mysqldump_dict['prefix_date']:
     207            dump_filename = f"{get_date()}_{dump_filename}"
     208        dump_filename = path.join(backup_paths[0], dump_filename)
     209
     210        if path.exists(dump_filename):
     211            raise errs.ValidationError(f"ValidationError: mysqldump already exists {dump_filename}")
     212
     213        with open(dump_filename, "w+") as df:
     214            mysqldump_process = subprocess.Popen(mysqldump_args, stdout=df, stderr=subprocess.PIPE)
     215            dump_result = mysqldump_process.communicate()
     216
     217        # Get the piped std err. See if it contains the word error
     218        stdo, stde = dump_result
     219        if stde is not None:
     220            decoded_stderr = stde.decode()
     221            if decoded_stderr.casefold().find('error'.casefold()) > -1:
     222                raise errs.SubprocessError(f"SubprocessError: Errors detected in mysqldump:\n{decoded_stderr}")
     223
     224        # copy the dump to other locations
     225        for d in range(1, len(backup_paths)):
     226            sub_utils.cp_wrapper([dump_filename, backup_paths[d]])
    186227
    187228
  • branches/ipp-259_genericise_backups/tools/backups/backup_test.py

    r40924 r40931  
    294294        assert not os.path.exists(expected_tar2)
    295295        backy._run_tar()
    296         print(expected_tar1)
    297         print(expected_tar2)
    298296        assert os.path.exists(expected_tar1)
    299297        assert os.path.exists(expected_tar2)
     
    309307
    310308
    311 # class TestRunningMysqldump():
    312 
    313 #     def test_simply_mysqldump(self):
    314 #         assert True is False
    315 
    316 #     def test_mysqldump_with_additional_args(self):
    317 #         assert True is False
     309@pytest.mark.skip(reason="Requires a fake database to be setup")
     310class TestMysqlBackup(object):
     311    """ The mySQL dump tests require the machine on which they are
     312running to have a mysql database running with a user called
     313'dumper' and a password set to 'not_a_real_password'.
     314
     315In production, a proper password should be set on the server and in the config
     316file. DO NOT USE THE ABOVE IN PRODUCTION
     317
     318To change the password:
     319UPDATE mysql.user SET authentication_string = PASSWORD('NEW_USER_PASSWORD')WHERE User = 'user-name' AND Host = 'localhost';FLUSH PRIVILEGES;
     320"""
     321
     322    dumper_password = "not_a_real_password"
     323
     324    def test_mysql_dump_is_ok(self, tmpdir):
     325        config = make_default_config(tmpdir, ['bck1', 'bck2'])
     326        config['MYSQLDUMP'] = \
     327        { 'user' : 'dumper'
     328        , 'password' : 'not_a_real_password'
     329        , 'db_name' : 'jiradb'
     330        , 'target_filename' : "cool_dump.sql"
     331        , 'prefix_date' : True
     332        }
     333
     334        backy = Backup(config)
     335
     336        date = bckup.get_date()
     337
     338        expected_dump1 = os.path.join(tmpdir, 'bck1', f'{date}_cool_dump.sql')
     339        expected_dump2 = os.path.join(tmpdir, 'bck2', f'{date}_cool_dump.sql')
     340        assert not os.path.exists(expected_dump1)
     341        assert not os.path.exists(expected_dump2)
     342        backy._run_mysqldump()
     343        assert os.path.exists(expected_dump1)
     344        assert os.path.exists(expected_dump2)
     345
     346    def test_mysql_dump_fails_with_incorrect_password(self, tmpdir):
     347        config = make_default_config(tmpdir, ['bck1', 'bck2'])
     348        config['MYSQLDUMP'] = \
     349        { 'user' : 'dumper'
     350        , 'password' : 'incorrect_password'
     351        , 'db_name' : 'jiradb'
     352        , 'target_filename' : "cool_dump.sql"
     353        , 'prefix_date' : True
     354        }
     355
     356        backy = Backup(config)
     357        with pytest.raises(errs.SubprocessError):
     358            backy._run_mysqldump()
Note: See TracChangeset for help on using the changeset viewer.