Modifying Openstack client for undercloud and overcloud backup
- Adding v1/overcloud_backup.py and test/overcloud_backup/
to cover overcloud backup use case and following the structure
of stable/victoria.
- Moving back v2/undercloud_backup.py to v1/undercloud_backup.py
to follow same structure of stable/victoria.
- Moving back tests/v2/undercloud/test_backup.py to
tests/v1/undercloud/test_backup.py to follow same structure
of stable/victoria.
- Updating setup.cfg from undercloud_backup v2 to v1 and adding
overcloud_backup.
- '--init' flag was marked with WARNING indicating it will be
deprecated and replaced by '--setup-nfs' and '--setup-rear'.
Now it receives arguments: 'rear' and 'nfs'. Defaults to: rear,
so it doesn't break interface.
- '--setup-nfs' flag added which installs and configure NFS
on the 'BackupNode' host.
- '--setup-rear' flag added which installs and configure ReaR
on the 'Undercloud' or the 'Controller' nodes.
- '--extra-vars' was enabled to pass variables to the playbooks
by specifying JSON/YAML string or full path of the file.
- Now 'tags' parameter is used internally to specify which
tasks to run.
- '--storage-ip' flag on overcloud backup command was marked with
WARNING indicating it will be deprecated in favor of '--extra-vars'
which allows to pass this and more properties.
Thought, it has precedence over '--extra-vars'. If used it will replace
the '--extra-vars' property 'tripleo_backup_and_restore_nfs_server'.
Bugzilla: #1824806
Change-Id: I31f2a554b03677fe29bd1186dee5d278b6d0554b
(cherry picked from commit 945882fe72
)
This commit is contained in:
parent
5f803a1c44
commit
8c45380b7a
|
@ -51,6 +51,7 @@ openstack.tripleoclient.v2 =
|
|||
tripleo_launch_heat = tripleoclient.v1.tripleo_launch_heat:LaunchHeat
|
||||
tripleo_upgrade = tripleoclient.v1.tripleo_upgrade:Upgrade
|
||||
overcloud_admin_authorize = tripleoclient.v1.overcloud_admin:Authorize
|
||||
overcloud_backup = tripleoclient.v1.overcloud_backup:BackupOvercloud
|
||||
overcloud_netenv_validate = tripleoclient.v1.overcloud_netenv_validate:ValidateOvercloudNetenv
|
||||
overcloud_cell_export = tripleoclient.v1.overcloud_cell:ExportCell
|
||||
overcloud_config_download = tripleoclient.v1.overcloud_config:DownloadConfig
|
||||
|
@ -114,7 +115,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
|
||||
|
|
|
@ -0,0 +1,255 @@
|
|||
# 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
|
||||
from unittest.mock import call
|
||||
|
||||
|
||||
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,
|
||||
tags='bar_create_recover_image',
|
||||
skip_tags=None,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
verbosity=3,
|
||||
extra_vars={}
|
||||
)
|
||||
|
||||
@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,
|
||||
tags='bar_setup_rear',
|
||||
skip_tags=None,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
verbosity=3,
|
||||
extra_vars={}
|
||||
)
|
||||
|
||||
@mock.patch('tripleoclient.utils.run_ansible_playbook',
|
||||
autospec=True)
|
||||
def test_overcloud_backup_init_nfs(self, mock_playbook):
|
||||
arglist = [
|
||||
'--init',
|
||||
'nfs'
|
||||
]
|
||||
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-nfs-backup.yaml',
|
||||
inventory=parsed_args.inventory,
|
||||
tags='bar_setup_nfs_server',
|
||||
skip_tags=None,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
verbosity=3,
|
||||
extra_vars={}
|
||||
)
|
||||
|
||||
@mock.patch('tripleoclient.utils.run_ansible_playbook',
|
||||
autospec=True)
|
||||
def test_overcloud_backup_setup_nfs(self, mock_playbook):
|
||||
arglist = [
|
||||
'--setup-nfs'
|
||||
]
|
||||
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-nfs-backup.yaml',
|
||||
inventory=parsed_args.inventory,
|
||||
tags='bar_setup_nfs_server',
|
||||
skip_tags=None,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
verbosity=3,
|
||||
extra_vars={}
|
||||
)
|
||||
|
||||
@mock.patch('tripleoclient.utils.run_ansible_playbook',
|
||||
autospec=True)
|
||||
def test_overcloud_backup_setup_rear(self, mock_playbook):
|
||||
arglist = [
|
||||
'--setup-rear',
|
||||
]
|
||||
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,
|
||||
tags='bar_setup_rear',
|
||||
skip_tags=None,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
verbosity=3,
|
||||
extra_vars={}
|
||||
)
|
||||
|
||||
@mock.patch('tripleoclient.utils.run_ansible_playbook', autospec=True)
|
||||
def test_overcloud_backup_setup_nfs_rear_with_inventory(self,
|
||||
mock_playbook):
|
||||
arglist = [
|
||||
'--setup-nfs',
|
||||
'--setup-rear',
|
||||
'--inventory',
|
||||
'/tmp/test_inventory.yaml'
|
||||
]
|
||||
verifylist = []
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
self.cmd.take_action(parsed_args)
|
||||
|
||||
calls = [call(workdir=mock.ANY,
|
||||
playbook='prepare-nfs-backup.yaml',
|
||||
inventory=parsed_args.inventory,
|
||||
tags='bar_setup_nfs_server',
|
||||
skip_tags=None,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
verbosity=3,
|
||||
extra_vars={}),
|
||||
call(workdir=mock.ANY,
|
||||
playbook='prepare-overcloud-backup.yaml',
|
||||
inventory=parsed_args.inventory,
|
||||
tags='bar_setup_rear',
|
||||
skip_tags=None,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
verbosity=3,
|
||||
extra_vars={})]
|
||||
|
||||
mock_playbook.assert_has_calls(calls)
|
||||
|
||||
@mock.patch('tripleoclient.utils.run_ansible_playbook',
|
||||
autospec=True)
|
||||
def test_overcloud_backup_setup_rear_extra_vars_inline(self,
|
||||
mock_playbook):
|
||||
arglist = [
|
||||
'--setup-rear',
|
||||
'--extra-vars',
|
||||
'{"tripleo_backup_and_restore_nfs_server": "192.168.24.1"}'
|
||||
]
|
||||
verifylist = []
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
extra_vars_dict = {
|
||||
'tripleo_backup_and_restore_nfs_server': '192.168.24.1'
|
||||
}
|
||||
|
||||
self.cmd.take_action(parsed_args)
|
||||
mock_playbook.assert_called_once_with(
|
||||
workdir=mock.ANY,
|
||||
playbook='prepare-overcloud-backup.yaml',
|
||||
inventory=parsed_args.inventory,
|
||||
tags='bar_setup_rear',
|
||||
skip_tags=None,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
verbosity=3,
|
||||
extra_vars=extra_vars_dict
|
||||
)
|
||||
|
||||
@mock.patch('tripleoclient.utils.run_ansible_playbook',
|
||||
autospec=True)
|
||||
def test_overcloud_backup_setup_rear_with_extra_vars(self, mock_playbook):
|
||||
arglist = [
|
||||
'--setup-rear',
|
||||
'--extra-vars',
|
||||
'/tmp/test_vars.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,
|
||||
tags='bar_setup_rear',
|
||||
skip_tags=None,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
verbosity=3,
|
||||
extra_vars='/tmp/test_vars.yaml'
|
||||
)
|
||||
|
||||
@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,
|
||||
tags='bar_create_recover_image',
|
||||
skip_tags=None,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
verbosity=3,
|
||||
extra_vars={}
|
||||
)
|
|
@ -0,0 +1,363 @@
|
|||
# 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 undercloud_backup
|
||||
from unittest.mock import call
|
||||
|
||||
|
||||
class TestUndercloudBackup(utils.TestCommand):
|
||||
|
||||
def setUp(self):
|
||||
super(TestUndercloudBackup, self).setUp()
|
||||
|
||||
# Get the command object to test
|
||||
app_args = mock.Mock()
|
||||
app_args.verbose_level = 1
|
||||
self.app.options = fakes.FakeOptions()
|
||||
self.cmd = undercloud_backup.BackupUndercloud(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_undercloud_backup_withargs(self, mock_playbook):
|
||||
arglist = [
|
||||
'--add-path',
|
||||
'/tmp/foo.yaml',
|
||||
'--add-path',
|
||||
'/tmp/bar.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=mock.ANY,
|
||||
inventory=mock.ANY,
|
||||
tags=None,
|
||||
skip_tags=None,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
verbosity=3,
|
||||
extra_vars={'sources_path':
|
||||
'/home/stack/,/tmp/bar.yaml,/tmp/foo.yaml'})
|
||||
|
||||
@mock.patch('tripleoclient.utils.run_ansible_playbook',
|
||||
autospec=True)
|
||||
def test_undercloud_backup_withargs_remove(self, mock_playbook):
|
||||
arglist = [
|
||||
'--add-path',
|
||||
'/tmp/foo.yaml',
|
||||
'--exclude-path',
|
||||
'/tmp/bar.yaml',
|
||||
'--exclude-path',
|
||||
'/home/stack/',
|
||||
'--add-path',
|
||||
'/tmp/bar.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=mock.ANY,
|
||||
inventory=mock.ANY,
|
||||
tags=None,
|
||||
skip_tags=None,
|
||||
verbosity=3,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
extra_vars={'sources_path':
|
||||
'/tmp/foo.yaml'})
|
||||
|
||||
@mock.patch('tripleoclient.utils.run_ansible_playbook',
|
||||
autospec=True)
|
||||
def test_undercloud_backup_withargs_remove_double(self, mock_playbook):
|
||||
arglist = [
|
||||
'--add-path',
|
||||
'/tmp/foo.yaml',
|
||||
'--add-path',
|
||||
'/tmp/bar.yaml',
|
||||
'--exclude-path',
|
||||
'/tmp/foo.yaml',
|
||||
'--exclude-path',
|
||||
'/tmp/foo.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=mock.ANY,
|
||||
inventory=mock.ANY,
|
||||
tags=None,
|
||||
skip_tags=None,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
verbosity=3,
|
||||
extra_vars={'sources_path':
|
||||
'/home/stack/,/tmp/bar.yaml'})
|
||||
|
||||
@mock.patch('tripleoclient.utils.run_ansible_playbook',
|
||||
autospec=True)
|
||||
def test_undercloud_backup_withargs_remove_unex(self, mock_playbook):
|
||||
arglist = [
|
||||
'--add-path',
|
||||
'/tmp/foo.yaml',
|
||||
'--exclude-path',
|
||||
'/tmp/non-existing-path.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=mock.ANY,
|
||||
inventory=mock.ANY,
|
||||
tags=None,
|
||||
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=mock.ANY,
|
||||
tags='bar_create_recover_image',
|
||||
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=mock.ANY,
|
||||
tags='bar_setup_rear',
|
||||
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_nfs(self, mock_playbook):
|
||||
arglist = [
|
||||
'--init',
|
||||
'nfs'
|
||||
]
|
||||
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-nfs-backup.yaml',
|
||||
inventory=mock.ANY,
|
||||
tags='bar_setup_nfs_server',
|
||||
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_setup_nfs(self, mock_playbook):
|
||||
arglist = [
|
||||
'--setup-nfs'
|
||||
]
|
||||
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-nfs-backup.yaml',
|
||||
inventory=mock.ANY,
|
||||
tags='bar_setup_nfs_server',
|
||||
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_setup_rear(self, mock_playbook):
|
||||
arglist = [
|
||||
'--setup-rear'
|
||||
]
|
||||
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=mock.ANY,
|
||||
tags='bar_setup_rear',
|
||||
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_setup_rear_extra_vars_inline(self,
|
||||
mock_playbook):
|
||||
arglist = [
|
||||
'--setup-rear',
|
||||
'--extra-vars',
|
||||
'{"tripleo_backup_and_restore_nfs_server": "192.168.24.1"}'
|
||||
]
|
||||
verifylist = []
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
extra_vars_dict = {
|
||||
'tripleo_backup_and_restore_nfs_server': '192.168.24.1'
|
||||
}
|
||||
|
||||
self.cmd.take_action(parsed_args)
|
||||
mock_playbook.assert_called_once_with(
|
||||
workdir=mock.ANY,
|
||||
playbook='prepare-undercloud-backup.yaml',
|
||||
inventory=mock.ANY,
|
||||
tags='bar_setup_rear',
|
||||
skip_tags=None,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
verbosity=3,
|
||||
extra_vars=extra_vars_dict
|
||||
)
|
||||
|
||||
@mock.patch('tripleoclient.utils.run_ansible_playbook', autospec=True)
|
||||
def test_undercloud_backup_setup_nfs_rear_with_inventory(self,
|
||||
mock_playbook):
|
||||
arglist = [
|
||||
'--setup-nfs',
|
||||
'--setup-rear',
|
||||
'--inventory',
|
||||
'/tmp/test_inventory.yaml'
|
||||
]
|
||||
verifylist = []
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
self.cmd.take_action(parsed_args)
|
||||
|
||||
calls = [call(workdir=mock.ANY,
|
||||
playbook='prepare-nfs-backup.yaml',
|
||||
inventory=mock.ANY,
|
||||
tags='bar_setup_nfs_server',
|
||||
skip_tags=None,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
verbosity=3,
|
||||
extra_vars=None),
|
||||
call(workdir=mock.ANY,
|
||||
playbook='prepare-undercloud-backup.yaml',
|
||||
inventory=mock.ANY,
|
||||
tags='bar_setup_rear',
|
||||
skip_tags=None,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
verbosity=3,
|
||||
extra_vars=None)]
|
||||
|
||||
mock_playbook.assert_has_calls(calls)
|
||||
|
||||
@mock.patch('tripleoclient.utils.run_ansible_playbook',
|
||||
autospec=True)
|
||||
def test_undercloud_backup_setup_nfs_with_extra_vars(self, mock_playbook):
|
||||
arglist = [
|
||||
'--setup-nfs',
|
||||
'--extra-vars',
|
||||
'/tmp/test_vars.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-nfs-backup.yaml',
|
||||
inventory=mock.ANY,
|
||||
tags='bar_setup_nfs_server',
|
||||
skip_tags=None,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
verbosity=3,
|
||||
extra_vars='/tmp/test_vars.yaml'
|
||||
)
|
||||
|
||||
@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=mock.ANY,
|
||||
tags='bar_create_recover_image',
|
||||
skip_tags=None,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
verbosity=3,
|
||||
extra_vars=None
|
||||
)
|
|
@ -1,156 +0,0 @@
|
|||
# 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.v2 import undercloud_backup
|
||||
|
||||
|
||||
class TestUndercloudBackup(utils.TestCommand):
|
||||
|
||||
def setUp(self):
|
||||
super(TestUndercloudBackup, self).setUp()
|
||||
|
||||
# Get the command object to test
|
||||
app_args = mock.Mock()
|
||||
app_args.verbose_level = 1
|
||||
self.app.options = fakes.FakeOptions()
|
||||
self.cmd = undercloud_backup.BackupUndercloud(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_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):
|
||||
arglist = [
|
||||
'--add-path',
|
||||
'/tmp/foo.yaml',
|
||||
'--add-path',
|
||||
'/tmp/bar.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=mock.ANY,
|
||||
inventory=mock.ANY,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
verbosity=3,
|
||||
extra_vars={'sources_path':
|
||||
'/home/stack/,/tmp/bar.yaml,/tmp/foo.yaml'})
|
||||
|
||||
@mock.patch('tripleoclient.utils.run_ansible_playbook',
|
||||
autospec=True)
|
||||
def test_undercloud_backup_withargs_remove(self, mock_playbook):
|
||||
arglist = [
|
||||
'--add-path',
|
||||
'/tmp/foo.yaml',
|
||||
'--exclude-path',
|
||||
'/tmp/bar.yaml',
|
||||
'--exclude-path',
|
||||
'/home/stack/',
|
||||
'--add-path',
|
||||
'/tmp/bar.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=mock.ANY,
|
||||
inventory=mock.ANY,
|
||||
verbosity=3,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
extra_vars={'sources_path':
|
||||
'/tmp/foo.yaml'})
|
||||
|
||||
@mock.patch('tripleoclient.utils.run_ansible_playbook',
|
||||
autospec=True)
|
||||
def test_undercloud_backup_withargs_remove_double(self, mock_playbook):
|
||||
arglist = [
|
||||
'--add-path',
|
||||
'/tmp/foo.yaml',
|
||||
'--add-path',
|
||||
'/tmp/bar.yaml',
|
||||
'--exclude-path',
|
||||
'/tmp/foo.yaml',
|
||||
'--exclude-path',
|
||||
'/tmp/foo.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=mock.ANY,
|
||||
inventory=mock.ANY,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
verbosity=3,
|
||||
extra_vars={'sources_path':
|
||||
'/home/stack/,/tmp/bar.yaml'})
|
||||
|
||||
@mock.patch('tripleoclient.utils.run_ansible_playbook',
|
||||
autospec=True)
|
||||
def test_undercloud_backup_withargs_remove_unex(self, mock_playbook):
|
||||
arglist = [
|
||||
'--add-path',
|
||||
'/tmp/foo.yaml',
|
||||
'--exclude-path',
|
||||
'/tmp/non-existing-path.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=mock.ANY,
|
||||
inventory=mock.ANY,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
verbosity=3,
|
||||
extra_vars={'sources_path':
|
||||
'/home/stack/,/tmp/foo.yaml'})
|
|
@ -0,0 +1,214 @@
|
|||
# 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
|
||||
import os
|
||||
import yaml
|
||||
|
||||
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',
|
||||
const='rear',
|
||||
nargs='?',
|
||||
action='store',
|
||||
help=_("Initialize environment for backup,"
|
||||
"using 'rear' or 'nfs' as args "
|
||||
"which will check for package install "
|
||||
"and configured ReaR or NFS server. "
|
||||
"Defaults to: rear. "
|
||||
"i.e. --init rear. "
|
||||
"WARNING: This flag will be deprecated"
|
||||
"and replaced by '--setup-rear' and"
|
||||
"'--setup-nfs'.")
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--setup-nfs',
|
||||
default=False,
|
||||
action='store_true',
|
||||
help=_("Setup the NFS server on the backup node "
|
||||
"which will install required packages "
|
||||
"and configuration on the host 'BackupNode' "
|
||||
"in the ansible inventory.")
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--setup-rear',
|
||||
default=False,
|
||||
action='store_true',
|
||||
help=_("Setup ReaR on the overcloud 'Controller' hosts which will "
|
||||
"install and configure ReaR.")
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--inventory',
|
||||
default='/home/stack/tripleo-inventory.yaml',
|
||||
help=_("Tripleo inventory file generated with "
|
||||
"tripleo-ansible-inventory command. "
|
||||
"Defaults to: /home/stack/tripleo-inventory.yaml.")
|
||||
)
|
||||
|
||||
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. "
|
||||
"WARNING: This flag will be deprecated in "
|
||||
"favor of '--extra-vars' which will allow "
|
||||
"to pass this and other variables.")
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--extra-vars',
|
||||
default=None,
|
||||
action='store',
|
||||
help=_("Set additional variables as Dict or as "
|
||||
"an absolute path of a JSON or YAML file type. "
|
||||
"i.e. --extra-vars '{\"key\": \"val\", "
|
||||
" \"key2\": \"val2\"}' "
|
||||
"i.e. --extra-vars /path/to/my_vars.yaml "
|
||||
"i.e. --extra-vars /path/to/my_vars.json. "
|
||||
"For more information about the variables that "
|
||||
"can be passed, visit: https://opendev.org/openstack/"
|
||||
"tripleo-ansible/src/branch/master/tripleo_ansible/"
|
||||
"roles/backup_and_restore/defaults/main.yml.")
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
def _parse_extra_vars(self, raw_extra_vars):
|
||||
|
||||
if raw_extra_vars is None:
|
||||
return {}
|
||||
elif os.path.exists(raw_extra_vars):
|
||||
with open(raw_extra_vars, 'r') as fp:
|
||||
extra_vars = yaml.safe_load(fp.read())
|
||||
else:
|
||||
try:
|
||||
extra_vars = yaml.safe_load(raw_extra_vars)
|
||||
except yaml.YAMLError as exc:
|
||||
raise RuntimeError(
|
||||
_('--extra-vars is not an existing file and cannot be '
|
||||
'parsed as YAML / JSON: %s') % exc)
|
||||
|
||||
return extra_vars
|
||||
|
||||
def _run_backup_overcloud(self, parsed_args):
|
||||
"""Backup defined overcloud nodes."""
|
||||
|
||||
extra_vars = self._parse_extra_vars(parsed_args.extra_vars)
|
||||
|
||||
if parsed_args.storage_ip:
|
||||
storage_ip = parsed_args.storage_ip
|
||||
|
||||
extra_vars[
|
||||
'tripleo_backup_and_restore_nfs_server'
|
||||
] = storage_ip
|
||||
|
||||
if parsed_args.setup_nfs is True or parsed_args.init == 'nfs':
|
||||
|
||||
LOG.debug(_('Setting up NFS Backup node'))
|
||||
self._run_ansible_playbook(
|
||||
playbook='prepare-nfs-backup.yaml',
|
||||
inventory=parsed_args.inventory,
|
||||
tags='bar_setup_nfs_server',
|
||||
skip_tags=None,
|
||||
extra_vars=extra_vars
|
||||
)
|
||||
|
||||
if parsed_args.setup_rear is True or parsed_args.init == 'rear':
|
||||
|
||||
LOG.debug(_('Installing ReaR on controller nodes'))
|
||||
self._run_ansible_playbook(
|
||||
playbook='prepare-overcloud-backup.yaml',
|
||||
inventory=parsed_args.inventory,
|
||||
tags='bar_setup_rear',
|
||||
skip_tags=None,
|
||||
extra_vars=extra_vars
|
||||
)
|
||||
|
||||
if (parsed_args.setup_nfs is False and
|
||||
parsed_args.setup_rear is False and
|
||||
parsed_args.init is None):
|
||||
|
||||
LOG.debug(_('Starting Overcloud Backup'))
|
||||
self._run_ansible_playbook(
|
||||
playbook='cli-overcloud-backup.yaml',
|
||||
inventory=parsed_args.inventory,
|
||||
tags='bar_create_recover_image',
|
||||
skip_tags=None,
|
||||
extra_vars=extra_vars
|
||||
)
|
||||
|
||||
def _run_ansible_playbook(self,
|
||||
playbook,
|
||||
inventory,
|
||||
tags,
|
||||
skip_tags,
|
||||
extra_vars):
|
||||
"""Run ansible playbook"""
|
||||
|
||||
with utils.TempDirs() as tmp:
|
||||
utils.run_ansible_playbook(
|
||||
playbook=playbook,
|
||||
inventory=inventory,
|
||||
workdir=tmp,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
tags=tags,
|
||||
skip_tags=skip_tags,
|
||||
verbosity=utils.playbook_verbosity(self=self),
|
||||
extra_vars=extra_vars
|
||||
)
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
|
||||
if parsed_args.init:
|
||||
|
||||
LOG.warning("The following flags will be deprecated:"
|
||||
"[--init, --storage-ip]")
|
||||
|
||||
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'
|
||||
)
|
|
@ -0,0 +1,262 @@
|
|||
# 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 argparse
|
||||
import logging
|
||||
import os
|
||||
import yaml
|
||||
|
||||
from osc_lib.command import command
|
||||
from osc_lib.i18n import _
|
||||
|
||||
from tripleoclient import constants
|
||||
from tripleoclient import utils
|
||||
|
||||
LOG = logging.getLogger(__name__ + ".BackupUndercloud")
|
||||
|
||||
|
||||
class BackupUndercloud(command.Command):
|
||||
"""Backup the undercloud"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = argparse.ArgumentParser(
|
||||
description=self.get_description(),
|
||||
prog=prog_name,
|
||||
add_help=False
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--init',
|
||||
const='rear',
|
||||
nargs='?',
|
||||
action='store',
|
||||
help=_("Initialize environment for backup,"
|
||||
"using 'rear' or 'nfs' as args "
|
||||
"which will check for package install "
|
||||
"and configured ReaR or NFS server. "
|
||||
"Defaults to: rear. "
|
||||
"i.e. --init rear. "
|
||||
"WARNING: This flag will be deprecated"
|
||||
"and replaced by '--setup-rear' and"
|
||||
"'--setup-nfs'.")
|
||||
)
|
||||
|
||||
# New flags for tripleo-ansible backup and restore role.
|
||||
parser.add_argument(
|
||||
'--setup-nfs',
|
||||
default=False,
|
||||
action='store_true',
|
||||
help=_("Setup the NFS server on the backup node"
|
||||
"which will install required packages"
|
||||
"and configuration on the host 'BackupNode' "
|
||||
"in the ansible inventory.")
|
||||
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--setup-rear',
|
||||
default=False,
|
||||
action='store_true',
|
||||
help=_("Setup ReaR on the 'Undercloud' host which will"
|
||||
"install and configure ReaR.")
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--inventory',
|
||||
action='store',
|
||||
default='/home/stack/tripleo-inventory.yaml',
|
||||
help=_("Tripleo inventory file generated with"
|
||||
"tripleo-ansible-inventory command. "
|
||||
"Defaults to: /home/stack/tripleo-inventory.yaml.")
|
||||
)
|
||||
|
||||
# Parameter to choose the files to backup
|
||||
parser.add_argument(
|
||||
'--add-path',
|
||||
action='append',
|
||||
default=['/home/stack/'],
|
||||
help=_("Add additional files to backup. "
|
||||
"Defaults to: /home/stack/ "
|
||||
"i.e. --add-path /this/is/a/folder/ "
|
||||
" --add-path /this/is/a/texfile.txt.")
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--exclude-path",
|
||||
default=[],
|
||||
action="append",
|
||||
help=_("Exclude path when performing the Undercloud Backup, "
|
||||
"this option can be specified multiple times. "
|
||||
"Defaults to: none "
|
||||
"i.e. --exclude-path /this/is/a/folder/ "
|
||||
" --exclude-path /this/is/a/texfile.txt.")
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--save-swift',
|
||||
default=False,
|
||||
action='store_true',
|
||||
help=_("Save backup to swift. "
|
||||
"Defaults to: False "
|
||||
"Special attention should be taken that "
|
||||
"Swift itself is backed up if you call this multiple times "
|
||||
"the backup size will grow exponentially.")
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--extra-vars',
|
||||
default=None,
|
||||
action='store',
|
||||
help=_("Set additional variables as Dict or as "
|
||||
"an absolute path of a JSON or YAML file type. "
|
||||
"i.e. --extra-vars '{\"key\": \"val\", "
|
||||
"\"key2\": \"val2\"}' "
|
||||
"i.e. --extra-vars /path/to/my_vars.yaml "
|
||||
"i.e. --extra-vars /path/to/my_vars.json. "
|
||||
"For more information about the variables that "
|
||||
"can be passed, visit: https://opendev.org/openstack/"
|
||||
"tripleo-ansible/src/branch/master/tripleo_ansible/"
|
||||
"roles/backup_and_restore/defaults/main.yml.")
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
def _parse_extra_vars(self, raw_extra_vars):
|
||||
|
||||
if raw_extra_vars is None:
|
||||
return raw_extra_vars
|
||||
elif os.path.exists(raw_extra_vars):
|
||||
with open(raw_extra_vars, 'r') as fp:
|
||||
extra_vars = yaml.safe_load(fp.read())
|
||||
|
||||
else:
|
||||
try:
|
||||
extra_vars = yaml.safe_load(raw_extra_vars)
|
||||
except yaml.YAMLError as exc:
|
||||
raise RuntimeError(
|
||||
_('--extra-vars is not an existing file and cannot be '
|
||||
'parsed as YAML / JSON: %s') % exc)
|
||||
|
||||
return extra_vars
|
||||
|
||||
def _run_backup_undercloud(self, parsed_args):
|
||||
|
||||
extra_vars = self._parse_extra_vars(parsed_args.extra_vars)
|
||||
|
||||
if parsed_args.setup_nfs is True or parsed_args.init == 'nfs':
|
||||
|
||||
self._run_ansible_playbook(
|
||||
playbook='prepare-nfs-backup.yaml',
|
||||
inventory=parsed_args.inventory,
|
||||
tags='bar_setup_nfs_server',
|
||||
skip_tags=None,
|
||||
extra_vars=extra_vars
|
||||
)
|
||||
if parsed_args.setup_rear is True or parsed_args.init == 'rear':
|
||||
|
||||
self._run_ansible_playbook(
|
||||
playbook='prepare-undercloud-backup.yaml',
|
||||
inventory=parsed_args.inventory,
|
||||
tags='bar_setup_rear',
|
||||
skip_tags=None,
|
||||
extra_vars=extra_vars
|
||||
)
|
||||
|
||||
if (parsed_args.setup_nfs is False and
|
||||
parsed_args.setup_rear is False and
|
||||
parsed_args.init is None):
|
||||
|
||||
self._run_ansible_playbook(
|
||||
playbook='cli-undercloud-backup.yaml',
|
||||
inventory=parsed_args.inventory,
|
||||
tags='bar_create_recover_image',
|
||||
skip_tags=None,
|
||||
extra_vars=extra_vars
|
||||
)
|
||||
|
||||
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:
|
||||
merge_paths.remove(exc)
|
||||
|
||||
files_to_backup = ','.join(merge_paths)
|
||||
|
||||
# Define the backup sources_path (files to backup).
|
||||
# This is a comma separated string.
|
||||
# I.e. "/this/is/a/folder/,/this/is/a/texfile.txt"
|
||||
extra_vars = {"sources_path": files_to_backup}
|
||||
if parsed_args.save_swift:
|
||||
extra_vars.update({"save_swift": True})
|
||||
|
||||
LOG.debug(_('Launch the Undercloud Backup'))
|
||||
self._run_ansible_playbook(
|
||||
playbook='cli-undercloud-backup-legacy.yaml',
|
||||
inventory='localhost, ',
|
||||
tags=None,
|
||||
skip_tags=None,
|
||||
extra_vars=extra_vars
|
||||
)
|
||||
|
||||
def _run_ansible_playbook(self,
|
||||
playbook,
|
||||
inventory,
|
||||
tags,
|
||||
skip_tags,
|
||||
extra_vars):
|
||||
"""Run ansible playbook"""
|
||||
|
||||
with utils.TempDirs() as tmp:
|
||||
utils.run_ansible_playbook(
|
||||
playbook=playbook,
|
||||
inventory=inventory,
|
||||
workdir=tmp,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
tags=tags,
|
||||
skip_tags=skip_tags,
|
||||
verbosity=utils.playbook_verbosity(self=self),
|
||||
extra_vars=extra_vars
|
||||
)
|
||||
|
||||
def take_action(self, 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, --init, --save-swift]")
|
||||
|
||||
self._legacy_backup_undercloud(parsed_args)
|
||||
|
||||
else:
|
||||
self._run_backup_undercloud(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 Undercloud. The resulting #\n'
|
||||
' # backup file path will be shown on a successful execution. #\n'
|
||||
' # #\n'
|
||||
' # .-Stay safe and avoid future issues-. #\n'
|
||||
' #############################################################\n'
|
||||
)
|
|
@ -1,111 +0,0 @@
|
|||
# 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 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__ + ".BackupUndercloud")
|
||||
|
||||
|
||||
class BackupUndercloud(command.Command):
|
||||
"""Backup the undercloud"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = argparse.ArgumentParser(
|
||||
description=self.get_description(),
|
||||
prog=prog_name,
|
||||
add_help=False
|
||||
)
|
||||
|
||||
# Parameter to choose the files to backup
|
||||
parser.add_argument(
|
||||
'--add-path',
|
||||
action='append',
|
||||
default=['/home/stack/'],
|
||||
help=_("Add additional files to backup. "
|
||||
"Defaults to: /home/stack/ "
|
||||
"i.e. --add-path /this/is/a/folder/ "
|
||||
" --add-path /this/is/a/texfile.txt")
|
||||
)
|
||||
parser.add_argument(
|
||||
"--exclude-path",
|
||||
default=[],
|
||||
action="append",
|
||||
help=_("Exclude path when performing the Undercloud Backup, "
|
||||
"this option can be specified multiple times. "
|
||||
"Defaults to: none "
|
||||
"i.e. --exclude-path /this/is/a/folder/ "
|
||||
" --exclude-path /this/is/a/texfile.txt")
|
||||
)
|
||||
parser.add_argument(
|
||||
'--save-swift',
|
||||
default=False,
|
||||
action='store_true',
|
||||
help=_("Save backup to swift. "
|
||||
"Defaults to: False "
|
||||
"Special attention should be taken that "
|
||||
"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):
|
||||
|
||||
merge_paths = sorted(list(set(parsed_args.add_path)))
|
||||
for exc in parsed_args.exclude_path:
|
||||
if exc in merge_paths:
|
||||
merge_paths.remove(exc)
|
||||
|
||||
files_to_backup = ','.join(merge_paths)
|
||||
|
||||
# Define the backup sources_path (files to backup).
|
||||
# This is a comma separated string.
|
||||
# I.e. "/this/is/a/folder/,/this/is/a/texfile.txt"
|
||||
extra_vars = {"sources_path": files_to_backup}
|
||||
if parsed_args.save_swift:
|
||||
extra_vars.update({"save_swift": True})
|
||||
|
||||
LOG.debug(_('Launch the Undercloud Backup'))
|
||||
with utils.TempDirs() as tmp:
|
||||
utils.run_ansible_playbook(
|
||||
playbook='cli-undercloud-backup.yaml',
|
||||
inventory='localhost,',
|
||||
workdir=tmp,
|
||||
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||
verbosity=utils.playbook_verbosity(self=self),
|
||||
extra_vars=extra_vars
|
||||
)
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
|
||||
self._run_backup_undercloud(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 Undercloud. The resulting #\n'
|
||||
' # backup file path will be shown on a successful execution. #\n'
|
||||
' # #\n'
|
||||
' # .-Stay safe and avoid future issues-. #\n'
|
||||
' #############################################################\n'
|
||||
)
|
Loading…
Reference in New Issue