Merge "Change service candidates list for MariaDB"

This commit is contained in:
Jenkins 2016-07-30 03:21:55 +00:00 committed by Gerrit Code Review
commit 67940e90a6
9 changed files with 143 additions and 26 deletions

View File

@ -1292,7 +1292,7 @@ mariadb_opts = [
help='List of UDP ports and/or port ranges to open '
'in the security group (only applicable '
'if trove_security_groups_support is True).'),
cfg.StrOpt('backup_strategy', default='InnoBackupEx',
cfg.StrOpt('backup_strategy', default='MariaDBInnoBackupEx',
help='Default strategy to perform backups.',
deprecated_name='backup_strategy',
deprecated_group='DEFAULT'),
@ -1314,12 +1314,14 @@ mariadb_opts = [
help='Maximum time (in seconds) to wait for a Guest to become '
'active.'),
cfg.StrOpt('backup_namespace',
default='trove.guestagent.strategies.backup.mysql_impl',
default='trove.guestagent.strategies.backup.experimental'
'.mariadb_impl',
help='Namespace to load backup strategies from.',
deprecated_name='backup_namespace',
deprecated_group='DEFAULT'),
cfg.StrOpt('restore_namespace',
default='trove.guestagent.strategies.restore.mysql_impl',
default='trove.guestagent.strategies.restore.experimental'
'.mariadb_impl',
help='Namespace to load restore strategies from.',
deprecated_name='restore_namespace',
deprecated_group='DEFAULT'),
@ -1328,7 +1330,8 @@ mariadb_opts = [
cfg.StrOpt('device_path', default='/dev/vdb',
help='Device path for volume if volume support is enabled.'),
cfg.DictOpt('backup_incremental_strategy',
default={'InnoBackupEx': 'InnoBackupExIncremental'},
default={'MariaDBInnoBackupEx':
'MariaDBInnoBackupExIncremental'},
help='Incremental Backup Runner based on the default '
'strategy. For strategies that do not implement an '
'incremental backup, the runner will use the default full '

View File

@ -16,6 +16,7 @@
from oslo_log import log as logging
from trove.guestagent.common import operating_system
from trove.guestagent.datastore.galera_common import service as galera_service
from trove.guestagent.datastore.mysql_common import service as mysql_service
@ -24,11 +25,22 @@ LOG = logging.getLogger(__name__)
class MariaDBApp(galera_service.GaleraApp):
OS = operating_system.get_os()
def __init__(self, status):
super(MariaDBApp, self).__init__(
status, mysql_service.BaseLocalSqlClient,
mysql_service.BaseKeepAliveConnection)
@property
def service_candidates(self):
service_candidates = super(MariaDBApp, self).service_candidates
return {
operating_system.DEBIAN: service_candidates,
operating_system.REDHAT: ["mariadb"],
operating_system.SUSE: service_candidates
}[self.OS]
@property
def mysql_service(self):
result = super(MariaDBApp, self).mysql_service

View File

@ -591,10 +591,14 @@ class BaseMySqlApp(object):
def keep_alive_connection_cls(self):
return self._keep_alive_connection_cls
@property
def service_candidates(self):
return ["mysql", "mysqld", "mysql-server"]
@property
def mysql_service(self):
MYSQL_SERVICE_CANDIDATES = ["mysql", "mysqld", "mysql-server"]
return operating_system.service_discovery(MYSQL_SERVICE_CANDIDATES)
service_candidates = self.service_candidates
return operating_system.service_discovery(service_candidates)
configuration_manager = ConfigurationManager(
MYSQL_CONFIG, MYSQL_OWNER, MYSQL_OWNER, CFG_CODEC, requires_root=True,

View File

@ -0,0 +1,28 @@
# Copyright 2016 Tesora Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from trove.guestagent.datastore.experimental.mariadb.service import MariaDBApp
from trove.guestagent.datastore.mysql.service import MySqlAppStatus
from trove.guestagent.strategies.backup import mysql_impl
class MariaDBInnoBackupEx(mysql_impl.InnoBackupEx):
def _build_app(self):
return MariaDBApp(MySqlAppStatus.get())
class MariaDBInnoBackupExIncremental(MariaDBInnoBackupEx):
pass

View File

@ -62,3 +62,18 @@ class Replication(Strategy):
@abc.abstractmethod
def demote_master(self, service):
"""Turn off replication on a master site."""
@property
def repl_backup_runner(self):
"""Backup runner to be used to snapshot for replication"""
return None
@property
def repl_incr_backup_runner(self):
"""Incremental backup runner to be used to snapshot for replication"""
return None
@property
def repl_backup_extra_opts(self):
"""Extra options to be passed to the backup agent"""
return None

View File

@ -18,17 +18,35 @@ from oslo_log import log as logging
from trove.common import cfg
from trove.guestagent.backup.backupagent import BackupAgent
from trove.guestagent.strategies import backup
from trove.guestagent.strategies.replication import mysql_base
AGENT = BackupAgent()
CONF = cfg.CONF
REPL_BACKUP_NAMESPACE = 'trove.guestagent.strategies.backup' \
'.experimental.mariadb_impl'
LOG = logging.getLogger(__name__)
class MariaDBGTIDReplication(mysql_base.MysqlReplicationBase):
"""MariaDB Replication coordinated by GTIDs."""
@property
def repl_backup_runner(self):
return backup.get_backup_strategy('MariaDBInnoBackupEx',
REPL_BACKUP_NAMESPACE)
@property
def repl_incr_backup_runner(self):
return backup.get_backup_strategy('MariaDBInnoBackupExIncremental',
REPL_BACKUP_NAMESPACE)
@property
def repl_backup_extra_opts(self):
return CONF.backup_runner_options.get('MariaDBInnoBackupEx', '')
def connect_to_master(self, service, snapshot):
logging_config = snapshot['log_position']
LOG.debug("connect_to_master %s" % logging_config['replication_user'])

View File

@ -33,13 +33,6 @@ AGENT = BackupAgent()
CONF = cfg.CONF
REPL_BACKUP_NAMESPACE = 'trove.guestagent.strategies.backup.mysql_impl'
REPL_BACKUP_STRATEGY = 'InnoBackupEx'
REPL_BACKUP_INCREMENTAL_STRATEGY = 'InnoBackupExIncremental'
REPL_BACKUP_RUNNER = backup.get_backup_strategy(
REPL_BACKUP_STRATEGY, REPL_BACKUP_NAMESPACE)
REPL_BACKUP_INCREMENTAL_RUNNER = backup.get_backup_strategy(
REPL_BACKUP_INCREMENTAL_STRATEGY, REPL_BACKUP_NAMESPACE)
REPL_EXTRA_OPTS = CONF.backup_runner_options.get(REPL_BACKUP_STRATEGY, '')
LOG = logging.getLogger(__name__)
@ -47,6 +40,20 @@ LOG = logging.getLogger(__name__)
class MysqlReplicationBase(base.Replication):
"""Base class for MySql Replication strategies."""
@property
def repl_backup_runner(self):
return backup.get_backup_strategy('InnoBackupEx',
REPL_BACKUP_NAMESPACE)
@property
def repl_incr_backup_runner(self):
return backup.get_backup_strategy('InnoBackupExIncremental',
REPL_BACKUP_NAMESPACE)
@property
def repl_backup_extra_opts(self):
return CONF.backup_runner_options.get('InnoBackupEx', '')
def get_master_ref(self, service, snapshot_info):
master_ref = {
'host': netutils.get_my_ipv4(),
@ -81,13 +88,6 @@ class MysqlReplicationBase(base.Replication):
return replication_user
def backup_runner_for_replication(self):
return {
'runner': REPL_BACKUP_RUNNER,
'extra_opts': REPL_EXTRA_OPTS,
'incremental_runner': REPL_BACKUP_INCREMENTAL_RUNNER
}
def snapshot_for_replication(self, context, service,
location, snapshot_info):
snapshot_id = snapshot_info['id']
@ -97,8 +97,9 @@ class MysqlReplicationBase(base.Replication):
# Only create a backup if it's the first replica
if replica_number == 1:
AGENT.execute_backup(
context, snapshot_info,
**self.backup_runner_for_replication())
context, snapshot_info, runner=self.repl_backup_runner,
extra_opts=self.repl_backup_extra_opts,
incremental_runner=self.repl_incr_backup_runner)
else:
LOG.debug("Using existing backup created for previous replica.")
LOG.debug("Replication snapshot %s used for replica number %d."

View File

@ -0,0 +1,28 @@
# Copyright 2016 Tesora Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from trove.guestagent.datastore.experimental.mariadb.service import MariaDBApp
from trove.guestagent.datastore.mysql.service import MySqlAppStatus
from trove.guestagent.strategies.restore import mysql_impl
class MariaDBInnoBackupEx(mysql_impl.InnoBackupEx):
def _build_app(self):
return MariaDBApp(MySqlAppStatus.get())
class MariaDBInnoBackupExIncremental(MariaDBInnoBackupEx):
pass

View File

@ -205,13 +205,22 @@ class InnoBackupEx(base.RestoreRunner, MySQLRestoreMixin):
' 2>/tmp/innoprepare.log')
def __init__(self, *args, **kwargs):
self._app = None
super(InnoBackupEx, self).__init__(*args, **kwargs)
self.prepare_cmd = self.base_prepare_cmd % kwargs
self.prep_retcode = None
@property
def app(self):
if self._app is None:
self._app = self._build_app()
return self._app
def _build_app(self):
return dbaas.MySqlApp(dbaas.MySqlAppStatus.get())
def pre_restore(self):
app = dbaas.MySqlApp(dbaas.MySqlAppStatus.get())
app.stop_db()
self.app.stop_db()
LOG.info(_("Cleaning out restore location: %s."),
self.restore_location)
operating_system.chmod(self.restore_location, FileMode.SET_FULL,
@ -229,8 +238,7 @@ class InnoBackupEx(base.RestoreRunner, MySQLRestoreMixin):
force=True, as_root=True)
self._delete_old_binlogs()
self.reset_root_password()
app = dbaas.MySqlApp(dbaas.MySqlAppStatus.get())
app.start_mysql()
self.app.start_mysql()
def _delete_old_binlogs(self):
files = glob.glob(os.path.join(self.restore_location, "ib_logfile*"))