| # Copyright 2018 Mirantis, Inc. |
| # |
| # 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 tcp_tests import logger |
| from tcp_tests.managers.execute_commands import ExecuteCommandsMixin |
| |
| |
| LOG = logger.logger |
| |
| |
| class BackupRestoreManager(ExecuteCommandsMixin): |
| """Helper manager for execution backup restore""" |
| |
| def __init__(self, config, underlay, salt_api): |
| self.__config = config |
| self.underlay = underlay |
| self.__salt_api = salt_api |
| super(BackupRestoreManager, self).__init__(config, underlay) |
| |
| @property |
| def salt_api(self): |
| return self.__salt_api |
| |
| def get_node_name(self, tgt): |
| res = [node_name for node_name in |
| self.underlay.node_names() if tgt in node_name] |
| assert len(res) > 0, 'Can not find node name by tgt {}'.format(tgt) |
| return res[0] |
| |
| def create_backup(self, tgt, backup_cmd=None): |
| if not backup_cmd: |
| backup_cmd = 'backupninja -n --run /etc/backup.d/200.backup.rsync' |
| step = {'cmd': backup_cmd, 'node_name': self.get_node_name(tgt)} |
| self.execute_command(step, 'Running backup command') |
| |
| def check_file_exists(self, tgt, file_path=None): |
| if not file_path: |
| file_path = '/etc/backup.d/200.backup.rsync' |
| cmd = 'test -f {}'.format(file_path) |
| step = {'cmd': cmd, 'node_name': self.get_node_name(tgt)} |
| self.execute_command(step, 'Check file {} exists'.format(file_path)) |
| |
| def delete_dirs_files(self, tgt, file_path='/etc/pki/ca/salt_master_ca/'): |
| cmd = 'rm -rf {}'.format(file_path) |
| step = {'cmd': cmd, 'node_name': self.get_node_name(tgt)} |
| self.execute_command(step, 'Delete {}'.format(file_path)) |
| |
| def restore_salt(self, tgt): |
| cmd = 'salt-call state.sls salt.master.restore,salt.minion.restore' |
| step = {'cmd': cmd, 'node_name': self.get_node_name(tgt)} |
| self.execute_command(step, 'Restore salt master') |
| |
| def ping_minions(self, tgt): |
| cmd = 'salt "*" test.ping' |
| step = {'cmd': cmd, 'node_name': self.get_node_name(tgt)} |
| self.execute_command(step, 'Ping minions') |
| |
| def verify_salt_master_restored(self, tgt): |
| cmd = "salt -t2 '*' saltutil.refresh_pillar" |
| step = {'cmd': cmd, 'node_name': self.get_node_name(tgt)} |
| self.execute_command(step, |
| 'Verify that the Salt Master node is restored') |
| step = {'cmd': 'ls -la /etc/pki/ca/salt_master_ca/', |
| 'node_name': self.get_node_name(tgt)} |
| self.execute_command(step, |
| 'Check pki files exists') |
| |
| def create_mysql_backup_backupninja(self, tgt, ): |
| rets = [] |
| res = self.salt_api.enforce_state( |
| tgt, 'cmd.run', |
| 'backupninja -n --run /etc/backup.d/101.mysql') |
| rets.append(res) |
| res_rsync = self.salt_api.enforce_state(tgt, 'cmd.run') |
| rets.append(res_rsync) |
| return rets |
| |
| def restore_mysql_backupninja(self, tgt): |
| # Running this state restores the databases and creates a file |
| # for every restored database in /root/mysql/flags. |
| return self.salt_api.local(tgt, 'mysql.client') |
| |
| def create_mysql_xtrabackup(self, tgt, backup_cmd=None): |
| # Should be run on mysql master node |
| return self.salt_api.enforce_state( |
| tgt, 'cmd.run', '/usr/local/bin/innobackupex-runner.sh') |
| |
| def check_mysql_xtrabackup_rsynced(self, tgt='I@xtrabackup:server'): |
| return self.salt_api.enforce_state( |
| tgt, 'cmd.run', 'ls /var/backups/mysql/xtrabackup/full') |
| |
| def stop_mysql_slave(self, tgt='I@galera:slave'): |
| return self.salt_api.enforce_state(tgt, 'service.stop mysql') |
| |
| def remove_mysql_logs(self, tgt='I@galera:slave'): |
| return self.salt_api.enforce_state( |
| tgt, 'cmd.run', 'rm /var/lib/mysql/ib_logfile*') |
| |
| def stop_mysql_master(self, tgt='I@galera:master'): |
| return self.salt_api.enforce_state(tgt, 'service.stop mysql') |
| |
| def disconnect_wresp_master(self, tgt='I@galera:master'): |
| # TODO finds the way updated wresp |
| return self.salt_api.enforce_state( |
| tgt, 'cmd.run', 'wsrep_cluster_address=gcomm://') |
| |
| def move_dbs_files_to_new_location(self, tgt='I@galera:master'): |
| cmds = ['mkdir -p /root/mysql/mysql.bak/', |
| 'mv /var/lib/mysql/* /root/mysql/mysql.bak', |
| 'rm /var/lib/mysql/.galera_bootstrap'] |
| rest = [] |
| for cmd in cmds: |
| res = self.salt_api.enforce_state(tgt, 'cmd.run', cmd) |
| rest.append(res) |
| return rest |
| |
| def check_dbs_files_removed(self, tgt='I@galera:master'): |
| cmds = ['ls /var/lib/mysql/', |
| 'ls -ld /var/lib/mysql/.?*'] |
| rest = [] |
| for cmd in cmds: |
| res = self.salt_api.enforce_state(tgt, 'cmd.run', cmd) |
| rest.append(res) |
| return rest |
| |
| # run xtrabackup state on node where bacakup |
| def run_xtrabackup(self, tgt): |
| return self.salt_api.local(tgt, 'xtrabackup') |
| |
| def start_mysql(self): |
| tgts = ['I@galera:master', 'I@galera:slave'] |
| ret = [] |
| for tgt in tgts: |
| res = self.salt_api.enforce_state(tgt, 'service.start mysql') |
| ret.append(res) |
| return ret |
| |
| def check_galera_cluster(self, tgt='I@galera:master'): |
| return self.salt_api.enforce_state( |
| tgt, 'mysql.status | grep -A1 wsrep_cluster_size') |
| |
| # #################Backup_Restore_Glance################### |
| |
| def copy_glance_images_to_backup(self, path_to_backup, |
| tgt="I@glance:server and *01*"): |
| cmd = 'cp -a /var/lib/glance/images/. {}'.format(path_to_backup) |
| return self.salt_api.enforce_state( |
| tgt, 'cmd.run', cmd) |
| |
| def copy_glance_images_from_backup(self, path_to_backup, |
| tgt="I@glance:server and *01*"): |
| cmd = 'cp -a {}/. /var/lib/glance/images/'.format(path_to_backup) |
| return self.salt_api.enforce_state( |
| tgt, 'cmd.run', cmd) |
| |
| def check_images_after_backup(self, tgt="I@keystone:client"): |
| # TODO If the context of the Glance |
| # images files is lost, run the following commands: |
| # salt -C 'I@glance:server' cmd.run |
| # "chown glance:glance <IMAGE_FILE_NAME>" |
| # salt -C 'I@glance:server' cmd.run "chmod 640 <IMAGE_FILE_NAME>" |
| cmd = '. /root/keystonercv3; openstack image list' |
| return self.salt_api.enforce_state(tgt, 'cmd.run', cmd) |
| |
| # #################Backup_Restore_cinder_volumes_and_snapshots### |
| # TODO Verify that a complete backup was created on |
| # the MySQL Galera Database Master node |
| # ls /var/backups/mysql/xtrabackup/full |
| # TODO(tleontovich): add method to check needed configs |
| # TODO (tleontovich): check pillars |
| # TODO (tleontovich): check backup is created, and |
| # restore restores |