Introduce mariadb_backup backup_strategy
With mariabackup being renamed to mariadb-backup binary, to keep some backwards compatability instead of renaming the binary to call, this patch introduces the whole new strategy designed to pretty much override only used binary name for modern MariaDB versions. This new strategy is selected whenever requested datastore version is equal or higher 10.4. This patch is alternative to [1] [1] https://review.opendev.org/c/openstack/trove/+/948643 Change-Id: I5336c8f98d9f1f33810113b9d7a84f1bef3deb66
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
6
releasenotes/notes/mariadb-backup-b93c334f06498ff4.yaml
Normal file
6
releasenotes/notes/mariadb-backup-b93c334f06498ff4.yaml
Normal file
@@ -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.
|
||||
Reference in New Issue
Block a user