diff --git a/backup/drivers/mariabackup.py b/backup/drivers/mariabackup.py index 0da4b847ba..9e0a5a4e7c 100644 --- a/backup/drivers/mariabackup.py +++ b/backup/drivers/mariabackup.py @@ -25,17 +25,19 @@ CONF = cfg.CONF class MariaBackup(mysql_base.MySQLBaseRunner): """Implementation of Backup and Restore using mariabackup.""" + backup_binary = 'mariabackup' restore_cmd = ('mbstream -x -C %(restore_location)s') - prepare_cmd = 'mariabackup --prepare --target-dir=%(restore_location)s' + prepare_cmd = \ + f'{backup_binary} --prepare --target-dir=%(restore_location)s' def __init__(self, *args, **kwargs): super(MariaBackup, self).__init__(*args, **kwargs) - self.backup_log = '/tmp/mariabackup.log' + self.backup_log = f'/tmp/{self.backup_binary}.log' self._gzip = True @property def cmd(self): - cmd = ('mariabackup --backup --stream=xbstream ' + + cmd = (f'{self.backup_binary} --backup --stream=xbstream ' + self.user_and_pass) return cmd @@ -64,9 +66,15 @@ class MariaBackup(mysql_base.MySQLBaseRunner): raise Exception(msg) +class MariaDBBackup(MariaBackup): + """Implementation of Backup and Restore using mariadb-backup.""" + backup_binary = 'mariadb-backup' + + class MariaBackupIncremental(MariaBackup): """Incremental backup and restore using mariabackup.""" - incremental_prep = ('mariabackup --prepare ' + incremental_prep_binary = MariaBackup.backup_binary + incremental_prep = (f'{incremental_prep_binary} --prepare ' '--target-dir=%(restore_location)s ' '%(incremental_args)s') @@ -81,7 +89,7 @@ class MariaBackupIncremental(MariaBackup): @property def cmd(self): cmd = ( - 'mariabackup --backup --stream=xbstream' + f'{self.incremental_prep_binary} --backup --stream=xbstream' ' --incremental-lsn=%(lsn)s ' + self.user_and_pass ) @@ -102,3 +110,8 @@ class MariaBackupIncremental(MariaBackup): LOG.info('Running incremental restore') self.incremental_restore(self.location, self.checksum) return self.restore_content_length + + +class MariaDBBackupIncremental(MariaBackupIncremental): + """Incremental backup and restore using mariadb-backup.""" + incremental_prep_binary = MariaDBBackup.backup_binary diff --git a/backup/main.py b/backup/main.py index 64fa47bae9..fa9dd02163 100644 --- a/backup/main.py +++ b/backup/main.py @@ -19,6 +19,7 @@ import sys from oslo_config import cfg from oslo_log import log as logging from oslo_utils import importutils +from semantic_version import Version topdir = os.path.normpath( os.path.join(os.path.abspath(sys.argv[0]), os.pardir, os.pardir)) @@ -37,7 +38,13 @@ cli_opts = [ cfg.StrOpt( 'driver', default='innobackupex', - choices=['innobackupex', 'mariabackup', 'pg_basebackup', 'xtrabackup'] + choices=[ + 'innobackupex', + 'mariabackup', + 'mariadb_backup', + 'pg_basebackup', + 'xtrabackup' + ] ), cfg.BoolOpt('backup'), cfg.StrOpt( @@ -72,7 +79,10 @@ driver_mapping = { 'innobackupex': 'backup.drivers.innobackupex.InnoBackupEx', 'innobackupex_inc': 'backup.drivers.innobackupex.InnoBackupExIncremental', 'mariabackup': 'backup.drivers.mariabackup.MariaBackup', + 'mariadb_backup': 'backup.drivers.mariabackup.MariaDBBackup', 'mariabackup_inc': 'backup.drivers.mariabackup.MariaBackupIncremental', + 'mariadb_backup_inc': + 'backup.drivers.mariabackup.MariaDBBackupIncremental', 'pg_basebackup': 'backup.drivers.postgres.PgBasebackup', 'pg_basebackup_inc': 'backup.drivers.postgres.PgBasebackupIncremental', 'xtrabackup': 'backup.drivers.xtrabackup.XtraBackup', @@ -148,13 +158,19 @@ def main(): CONF(sys.argv[1:], project='trove-backup') logging.setup(CONF, 'trove-backup') - runner_cls = importutils.import_class(driver_mapping[CONF.driver]) + driver = CONF.driver + if driver == "mariabackup": + ds_version = CONF.swift_extra_metadata.get('datastore_version', '0.0') + if Version.coerce(ds_version) >= Version.coerce("10.4"): + driver = "mariadb_backup" + + runner_cls = importutils.import_class(driver_mapping[driver]) storage = importutils.import_class(storage_mapping[CONF.storage_driver])() if CONF.backup: if CONF.incremental: runner_cls = importutils.import_class( - driver_mapping['%s_inc' % CONF.driver]) + driver_mapping['%s_inc' % driver]) LOG.info('Starting backup database to %s, backup ID %s', CONF.storage_driver, CONF.backup_id) @@ -163,7 +179,7 @@ def main(): if storage.is_incremental_backup(CONF.restore_from): LOG.debug('Restore from incremental backup') runner_cls = importutils.import_class( - driver_mapping['%s_inc' % CONF.driver]) + driver_mapping['%s_inc' % driver]) LOG.info('Starting restore database from %s, location: %s', CONF.storage_driver, CONF.restore_from) diff --git a/backup/tests/unittests/drivers/test_mariadb.py b/backup/tests/unittests/drivers/test_mariadb.py index 0ec70d3077..b9f9a82b5c 100644 --- a/backup/tests/unittests/drivers/test_mariadb.py +++ b/backup/tests/unittests/drivers/test_mariadb.py @@ -31,7 +31,10 @@ driver_mapping = { 'innobackupex': 'backup.drivers.innobackupex.InnoBackupEx', 'innobackupex_inc': 'backup.drivers.innobackupex.InnoBackupExIncremental', 'mariabackup': 'backup.drivers.mariabackup.MariaBackup', + 'mariadb_backup': 'backup.drivers.mariabackup.MariaDBBackup', 'mariabackup_inc': 'backup.drivers.mariabackup.MariaBackupIncremental', + 'mariadb_backup_inc': + 'backup.drivers.mariabackup.MariaDBBackupIncremental', 'pg_basebackup': 'backup.drivers.postgres.PgBasebackup', 'pg_basebackup_inc': 'backup.drivers.postgres.PgBasebackupIncremental', 'xtrabackup': 'backup.drivers.xtrabackup.XtraBackup', @@ -80,6 +83,47 @@ class TestMariaBackup(unittest.TestCase): self.assertEqual(runner.check_restore_process(), True) +class TestMariaDBBackup(unittest.TestCase): + def setUp(self): + self.runner_cls = importutils.import_class( + driver_mapping['mariadb_backup']) + self.params = {} + + # assertions + self.assertIsNotNone(self.runner_cls) + + def tearDown(self): + pass + + def test_instance(self): + '''Check instance''' + # call the method + runner = self.runner_cls(**self.params) + + # assertions + self.assertIsNotNone(runner) + + def test_cmd(self): + '''Check cmd property''' + # call the method + runner = self.runner_cls(**self.params) + + # assertions + cmd = ("mariadb-backup --backup --stream=xbstream {}".format( + runner.user_and_pass)) + self.assertEqual(runner.cmd, cmd) + + def test_check_restore_process(self): + '''Check manifest''' + runner = self.runner_cls(**self.params) + runner.process = MagicMock() + returncode = PropertyMock(return_value=0) + type(runner.process).returncode = returncode + + # call the method + self.assertEqual(runner.check_restore_process(), True) + + class TestMariaBackupIncremental(unittest.TestCase): def setUp(self): self.runner_cls = importutils.import_class( @@ -131,5 +175,56 @@ class TestMariaBackupIncremental(unittest.TestCase): self.assertEqual(ret, length) +class TestMariaDBBackupIncremental(unittest.TestCase): + def setUp(self): + self.runner_cls = importutils.import_class( + driver_mapping['mariadb_backup_inc']) + self.params = { + 'lsn': '1234567890', + 'incremental_dir': './' + } + self.metadata = {} + + def tearDown(self): + pass + + def test_cmd(self): + '''Check cmd property''' + # call the method + runner = self.runner_cls(**self.params) + + # assertions + cmd = ( + 'mariadb-backup --backup --stream=xbstream' + ' --incremental-lsn=%(lsn)s ' + + runner.user_and_pass + ) + self.assertEqual(runner.cmd, cmd) + + def test_get_metadata(self): + # prepare the test + runner = self.runner_cls(**self.params) + runner.get_metadata = MagicMock(return_value=self.metadata) + + # call the method + ret = runner.get_metadata() + + # assertions + self.assertEqual(ret, self.metadata) + + def test_run_restore(self): + # prepare the test + runner = self.runner_cls(**self.params) + length = 10 + runner.incremental_restore = MagicMock(return_value=length) + runner.restore_content_length = length + + # call the method + ret = runner.run_restore() + + # assertions + self.assertEqual(ret, length) + + if __name__ == '__main__': unittest.main() diff --git a/releasenotes/notes/mariadb-backup-b93c334f06498ff4.yaml b/releasenotes/notes/mariadb-backup-b93c334f06498ff4.yaml new file mode 100644 index 0000000000..95374ab6e2 --- /dev/null +++ b/releasenotes/notes/mariadb-backup-b93c334f06498ff4.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + For MariaDB datastore of versions equal or higher then 10.4, + `mariadb-backup` binary will be executed instead of `mariabackup` + when performing backup or restore process.