Merge "Add backup functionality to Openstack client for undercloud and overcloud."

This commit is contained in:
Zuul 2020-07-18 01:40:10 +00:00 committed by Gerrit Code Review
commit e1b8bda709
6 changed files with 415 additions and 27 deletions

View File

@ -101,6 +101,7 @@ openstack.tripleoclient.v2 =
overcloud_external-update_run = tripleoclient.v1.overcloud_external_update:ExternalUpdateRun
overcloud_external-upgrade_run = tripleoclient.v1.overcloud_external_upgrade:ExternalUpgradeRun
overcloud_generate_fencing = tripleoclient.v1.overcloud_parameters:GenerateFencingParameters
overcloud_backup = tripleoclient.v1.overcloud_backup:BackupOvercloud
tripleo_container_image_build = tripleoclient.v2.tripleo_container_image:Build
tripleo_container_image_hotfix = tripleoclient.v2.tripleo_container_image:HotFix
tripleo_container_image_delete = tripleoclient.v1.container_image:TripleOContainerImageDelete
@ -113,7 +114,7 @@ openstack.tripleoclient.v2 =
undercloud_upgrade = tripleoclient.v1.undercloud:UpgradeUndercloud
undercloud_minion_install = tripleoclient.v1.undercloud_minion:InstallUndercloudMinion
undercloud_minion_upgrade = tripleoclient.v1.undercloud_minion:UpgradeUndercloudMinion
undercloud_backup = tripleoclient.v2.undercloud_backup:BackupUndercloud
undercloud_backup = tripleoclient.v1.undercloud_backup:BackupUndercloud
tripleo_validator_group_info = tripleoclient.v1.tripleo_validator:TripleOValidatorGroupInfo
tripleo_validator_list = tripleoclient.v1.tripleo_validator:TripleOValidatorList
tripleo_validator_run = tripleoclient.v1.tripleo_validator:TripleOValidatorRun

View File

@ -0,0 +1,147 @@
# Copyright 2018 Red Hat, 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.
#
import mock
from osc_lib.tests import utils
from tripleoclient import constants
from tripleoclient.tests import fakes
from tripleoclient.v1 import overcloud_backup
class TestOvercloudBackup(utils.TestCommand):
def setUp(self):
super(TestOvercloudBackup, self).setUp()
# Get the command object to test
app_args = mock.Mock()
app_args.verbose_level = 1
self.app.options = fakes.FakeOptions()
self.cmd = overcloud_backup.BackupOvercloud(self.app, app_args)
self.app.client_manager.workflow_engine = mock.Mock()
self.workflow = self.app.client_manager.workflow_engine
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True)
def test_overcloud_backup_noargs(self, mock_playbook):
arglist = []
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
mock_playbook.assert_called_once_with(
workdir=mock.ANY,
playbook='cli-overcloud-backup.yaml',
inventory=parsed_args.inventory,
skip_tags=None,
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
verbosity=3,
extra_vars=None
)
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True)
def test_overcloud_backup_init(self, mock_playbook):
arglist = [
'--init'
]
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
mock_playbook.assert_called_once_with(
workdir=mock.ANY,
playbook='prepare-overcloud-backup.yaml',
inventory=parsed_args.inventory,
skip_tags='bar_create_recover_image, bar_setup_nfs_server',
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
verbosity=3,
extra_vars=None
)
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True)
def test_overcloud_backup_storage_ip(self, mock_playbook):
arglist = [
'--init',
'--storage-ip',
'192.168.0.100'
]
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
extra_vars = {
"tripleo_backup_and_restore_nfs_server": parsed_args.storage_ip
}
self.cmd.take_action(parsed_args)
mock_playbook.assert_called_once_with(
workdir=mock.ANY,
playbook='prepare-overcloud-backup.yaml',
inventory=parsed_args.inventory,
skip_tags='bar_create_recover_image, bar_setup_nfs_server',
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
verbosity=3,
extra_vars=extra_vars
)
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True)
def test_overcloud_backup_init_with_inventory(self, mock_playbook):
arglist = [
'--init',
'--inventory',
'/tmp/test_inventory.yaml'
]
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
mock_playbook.assert_called_once_with(
workdir=mock.ANY,
playbook='prepare-overcloud-backup.yaml',
inventory=parsed_args.inventory,
skip_tags='bar_create_recover_image, bar_setup_nfs_server',
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
verbosity=3,
extra_vars=None
)
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True)
def test_overcloud_backup_inventory(self, mock_playbook):
arglist = [
'--inventory',
'/tmp/test_inventory.yaml'
]
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
mock_playbook.assert_called_once_with(
workdir=mock.ANY,
playbook='cli-overcloud-backup.yaml',
inventory=parsed_args.inventory,
skip_tags=None,
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
verbosity=3,
extra_vars=None
)

View File

@ -19,7 +19,7 @@ from osc_lib.tests import utils
from tripleoclient import constants
from tripleoclient.tests import fakes
from tripleoclient.v2 import undercloud_backup
from tripleoclient.v1 import undercloud_backup
class TestUndercloudBackup(utils.TestCommand):
@ -37,27 +37,7 @@ class TestUndercloudBackup(utils.TestCommand):
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True)
def test_undercloud_backup_noargs(self, mock_playbook):
arglist = []
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
mock_playbook.assert_called_once_with(
workdir=mock.ANY,
playbook='cli-undercloud-backup.yaml',
inventory='localhost,',
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
verbosity=3,
extra_vars={
'sources_path': '/home/stack/'
}
)
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True)
def test_undercloud_backup_withargs(self, mock_playbook):
def test_undercloud_backup_legacy_withargs(self, mock_playbook):
arglist = [
'--add-path',
'/tmp/foo.yaml',
@ -73,6 +53,7 @@ class TestUndercloudBackup(utils.TestCommand):
workdir=mock.ANY,
playbook=mock.ANY,
inventory=mock.ANY,
skip_tags=None,
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
verbosity=3,
extra_vars={'sources_path':
@ -100,6 +81,7 @@ class TestUndercloudBackup(utils.TestCommand):
workdir=mock.ANY,
playbook=mock.ANY,
inventory=mock.ANY,
skip_tags=None,
verbosity=3,
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
extra_vars={'sources_path':
@ -127,6 +109,7 @@ class TestUndercloudBackup(utils.TestCommand):
workdir=mock.ANY,
playbook=mock.ANY,
inventory=mock.ANY,
skip_tags=None,
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
verbosity=3,
extra_vars={'sources_path':
@ -150,7 +133,93 @@ class TestUndercloudBackup(utils.TestCommand):
workdir=mock.ANY,
playbook=mock.ANY,
inventory=mock.ANY,
skip_tags=None,
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
verbosity=3,
extra_vars={'sources_path':
'/home/stack/,/tmp/foo.yaml'})
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True)
def test_undercloud_backup_noargs(self, mock_playbook):
arglist = []
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
mock_playbook.assert_called_once_with(
workdir=mock.ANY,
playbook='cli-undercloud-backup.yaml',
inventory=parsed_args.inventory,
skip_tags=None,
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
verbosity=3,
extra_vars=None
)
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True)
def test_undercloud_backup_init(self, mock_playbook):
arglist = [
'--init'
]
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
mock_playbook.assert_called_once_with(
workdir=mock.ANY,
playbook='prepare-undercloud-backup.yaml',
inventory=parsed_args.inventory,
skip_tags='bar_create_recover_image',
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
verbosity=3,
extra_vars=None
)
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True)
def test_undercloud_backup_init_with_inventory(self, mock_playbook):
arglist = [
'--init',
'--inventory',
'/tmp/test_inventory.yaml'
]
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
mock_playbook.assert_called_once_with(
workdir=mock.ANY,
playbook='prepare-undercloud-backup.yaml',
inventory=parsed_args.inventory,
skip_tags='bar_create_recover_image',
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
verbosity=3,
extra_vars=None
)
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True)
def test_undercloud_backup_inventory(self, mock_playbook):
arglist = [
'--inventory',
'/tmp/test_inventory.yaml'
]
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
mock_playbook.assert_called_once_with(
workdir=mock.ANY,
playbook='cli-undercloud-backup.yaml',
inventory=parsed_args.inventory,
skip_tags=None,
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
verbosity=3,
extra_vars=None
)

View File

@ -0,0 +1,107 @@
# Copyright 2020 Red Hat, 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.
#
import argparse
import logging
from osc_lib.command import command
from osc_lib.i18n import _
from tripleoclient import constants
from tripleoclient import utils
LOG = logging.getLogger(__name__ + ".BackupOvercloud")
class BackupOvercloud(command.Command):
"""Backup the Overcloud"""
def get_parser(self, prog_name):
parser = argparse.ArgumentParser(
description=self.get_description(),
prog=prog_name,
add_help=False
)
parser.add_argument(
'--init',
default=False,
action='store_true',
help=_("Initialize enviornment for backup,"
"which will check for package install"
"status and configured ReaR.")
)
parser.add_argument(
'--inventory',
default='/home/stack/tripleo-inventory.yaml',
help=_("Tripleo inventory file generated with"
"tripleo-ansible-inventory command.")
)
parser.add_argument(
'--storage-ip',
help=_("Storage IP is an optional parameter"
"which allows for an ip of a storage"
"server to be specified, overriding the"
"default undercloud.")
)
return parser
def _run_backup_Overcloud(self, parsed_args):
"""Backup defined overcloud nodes."""
if parsed_args.init is False:
playbook = 'cli-overcloud-backup.yaml'
skip_tags = None
elif parsed_args.init is True:
playbook = 'prepare-overcloud-backup.yaml'
skip_tags = 'bar_create_recover_image, bar_setup_nfs_server'
if parsed_args.storage_ip:
extra_vars = {
"tripleo_backup_and_restore_nfs_server": parsed_args.storage_ip
}
else:
extra_vars = None
LOG.debug(_('Starting Overcloud Backup'))
with utils.TempDirs() as tmp:
utils.run_ansible_playbook(
playbook=playbook,
inventory=parsed_args.inventory,
workdir=tmp,
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
skip_tags=skip_tags,
verbosity=utils.playbook_verbosity(self=self),
extra_vars=extra_vars
)
def take_action(self, parsed_args):
self._run_backup_Overcloud(parsed_args)
print(
'\n'
' #############################################################\n'
' # Disclaimer #\n'
' # Backup verification is the End Users responsibility #\n'
' # Please verify backup integrity before any possible #\n'
' # disruptive actions against the Overcloud. The resulting #\n'
' # backup file path will be shown on a successful execution. #\n'
' # #\n'
' # .-Stay safe and avoid future issues-. #\n'
' #############################################################\n'
)

View File

@ -1,4 +1,4 @@
# Copyright 2018 Red Hat, Inc.
# Copyright 2020 Red Hat, 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
@ -35,6 +35,24 @@ class BackupUndercloud(command.Command):
add_help=False
)
# New flags for tripleo-ansible backup and restore role.
parser.add_argument(
'--init',
default=False,
action='store_true',
help=_("Initialize enviornment for backup,"
"which will check for package install"
"status and configured ReaR.")
)
parser.add_argument(
'--inventory',
action='store',
default='/home/stack/tripleo-inventory.yaml',
help=_("Tripleo inventory file generated with"
"tripleo-ansible-inventory command.")
)
# Parameter to choose the files to backup
parser.add_argument(
'--add-path',
@ -65,10 +83,32 @@ class BackupUndercloud(command.Command):
"Swift itself is backed up if you call this multiple times "
"the backup size will grow exponentially")
)
return parser
def _run_backup_undercloud(self, parsed_args):
if parsed_args.init is False:
playbook = 'cli-undercloud-backup.yaml'
skip_tags = None
elif parsed_args.init is True:
playbook = 'prepare-undercloud-backup.yaml'
skip_tags = 'bar_create_recover_image'
self._run_ansible_playbook(
playbook=playbook,
inventory=parsed_args.inventory,
skip_tags=skip_tags,
extra_vars=None
)
def _legacy_backup_undercloud(self, parsed_args):
"""Legacy backup undercloud.
This will allow for easier removal once the functionality
is no longer needed.
"""
merge_paths = sorted(list(set(parsed_args.add_path)))
for exc in parsed_args.exclude_path:
if exc in merge_paths:
@ -84,19 +124,43 @@ class BackupUndercloud(command.Command):
extra_vars.update({"save_swift": True})
LOG.debug(_('Launch the Undercloud Backup'))
self._run_ansible_playbook(
playbook='cli-undercloud-backup-legacy.yaml',
inventory='localhost, ',
skip_tags=None,
extra_vars=extra_vars
)
def _run_ansible_playbook(self,
playbook,
inventory,
skip_tags,
extra_vars):
"""Run ansible playbook"""
with utils.TempDirs() as tmp:
utils.run_ansible_playbook(
playbook='cli-undercloud-backup.yaml',
inventory='localhost,',
playbook=playbook,
inventory=inventory,
workdir=tmp,
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
skip_tags=skip_tags,
verbosity=utils.playbook_verbosity(self=self),
extra_vars=extra_vars
)
def take_action(self, parsed_args):
self._run_backup_undercloud(parsed_args)
if len(parsed_args.add_path) > 1 or parsed_args.save_swift:
LOG.warning("The following flags will be deprecated:"
"[--add-path, --exclude-path, --save-swift]")
self._legacy_backup_undercloud(parsed_args)
else:
self._run_backup_undercloud(parsed_args)
print(
'\n'
' #############################################################\n'