When using ephemeral Heat, the update run can no
longer rely on the Heat stack being present. Since
we create the stack and update the playbooks during
update prepare. We can simply execute the
update_steps_playbook.yaml now.
With this change, we also change the converge to just
execute the deploy_steps_playbook.yaml without doing
the entire stack update. The stack update is no longer
necessary with Ephemeral Heat.
Related: https://review.opendev.org/c/openstack/tripleo-upgrade/+/806565
Change-Id: I57d788639b651945ad765f810b504529e41f0fbd
(cherry picked from commit 5020a8a69a)
197 lines
7.9 KiB
Python
197 lines
7.9 KiB
Python
# Copyright 2015 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.utils import ParserException
|
|
from tripleoclient import constants
|
|
from tripleoclient import exceptions
|
|
from tripleoclient.tests.v1.overcloud_update import fakes
|
|
from tripleoclient.v1 import overcloud_update
|
|
|
|
|
|
class TestOvercloudUpdatePrepare(fakes.TestOvercloudUpdatePrepare):
|
|
|
|
def setUp(self):
|
|
super(TestOvercloudUpdatePrepare, self).setUp()
|
|
|
|
# Get the command object to test
|
|
app_args = mock.Mock()
|
|
app_args.verbose_level = 1
|
|
self.cmd = overcloud_update.UpdatePrepare(self.app, app_args)
|
|
|
|
uuid4_patcher = mock.patch('uuid.uuid4', return_value="UUID4")
|
|
self.mock_uuid4 = uuid4_patcher.start()
|
|
self.addCleanup(self.mock_uuid4.stop)
|
|
|
|
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
|
|
'_get_ctlplane_attrs', autospec=True, return_value={})
|
|
@mock.patch('tripleoclient.utils.ensure_run_as_normal_user')
|
|
@mock.patch('tripleoclient.utils.prompt_user_for_confirmation',
|
|
return_value=True)
|
|
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
|
|
'_get_undercloud_host_entry', autospec=True,
|
|
return_value='192.168.0.1 uc.ctlplane.localhost uc.ctlplane')
|
|
@mock.patch('tripleoclient.v1.overcloud_update.UpdatePrepare.log',
|
|
autospec=True)
|
|
@mock.patch('os.path.abspath')
|
|
@mock.patch('yaml.safe_load')
|
|
@mock.patch('shutil.copytree', autospec=True)
|
|
@mock.patch('six.moves.builtins.open')
|
|
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
|
|
'take_action', autospec=True)
|
|
def test_update_out(self, mock_deploy, mock_open, mock_copy, mock_yaml,
|
|
mock_abspath, mock_logger,
|
|
mock_get_undercloud_host_entry,
|
|
mock_confirm, mock_usercheck,
|
|
mock_get_ctlplane_attrs):
|
|
mock_yaml.return_value = {'fake_container': 'fake_value'}
|
|
|
|
argslist = ['--stack', 'overcloud', '--templates']
|
|
|
|
verifylist = [
|
|
('stack', 'overcloud'),
|
|
('templates', constants.TRIPLEO_HEAT_TEMPLATES),
|
|
]
|
|
|
|
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
|
|
with mock.patch('os.path.exists') as mock_exists, \
|
|
mock.patch('os.path.isfile') as mock_isfile:
|
|
mock_exists.return_value = True
|
|
mock_isfile.return_value = True
|
|
self.cmd.take_action(parsed_args)
|
|
mock_usercheck.assert_called_once()
|
|
mock_deploy.assert_called_once()
|
|
|
|
@mock.patch('tripleoclient.utils.ensure_run_as_normal_user')
|
|
@mock.patch('tripleoclient.utils.prompt_user_for_confirmation',
|
|
return_value=True)
|
|
@mock.patch('six.moves.builtins.open')
|
|
@mock.patch('os.path.abspath')
|
|
@mock.patch('yaml.safe_load')
|
|
@mock.patch('shutil.copytree', autospec=True)
|
|
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
|
|
'take_action', autospec=True)
|
|
def test_update_failed(self, mock_deploy, mock_copy, mock_yaml,
|
|
mock_abspath, mock_open,
|
|
mock_confirm, mock_usercheck):
|
|
mock_deploy.side_effect = exceptions.DeploymentError()
|
|
mock_yaml.return_value = {'fake_container': 'fake_value'}
|
|
argslist = ['--stack', 'overcloud', '--templates', ]
|
|
verifylist = [
|
|
('stack', 'overcloud'),
|
|
('templates', constants.TRIPLEO_HEAT_TEMPLATES),
|
|
]
|
|
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
|
|
|
|
with mock.patch('os.path.exists') as mock_exists, \
|
|
mock.patch('os.path.isfile') as mock_isfile:
|
|
mock_exists.return_value = True
|
|
mock_isfile.return_value = True
|
|
self.assertRaises(exceptions.DeploymentError,
|
|
self.cmd.take_action, parsed_args)
|
|
mock_usercheck.assert_called_once()
|
|
|
|
|
|
class TestOvercloudUpdateRun(fakes.TestOvercloudUpdateRun):
|
|
|
|
def setUp(self):
|
|
super(TestOvercloudUpdateRun, self).setUp()
|
|
|
|
# Get the command object to test
|
|
app_args = mock.Mock()
|
|
app_args.verbose_level = 1
|
|
self.cmd = overcloud_update.UpdateRun(self.app, app_args)
|
|
|
|
uuid4_patcher = mock.patch('uuid.uuid4', return_value="UUID4")
|
|
self.mock_uuid4 = uuid4_patcher.start()
|
|
self.addCleanup(self.mock_uuid4.stop)
|
|
|
|
@mock.patch('tripleoclient.utils.prompt_user_for_confirmation',
|
|
return_value=True)
|
|
@mock.patch('tripleoclient.utils.run_ansible_playbook',
|
|
autospec=True)
|
|
@mock.patch('os.path.expanduser')
|
|
@mock.patch('oslo_concurrency.processutils.execute')
|
|
@mock.patch('six.moves.builtins.open')
|
|
def test_update_with_no_limit(
|
|
self, mock_open, mock_execute, mock_expanduser, update_ansible,
|
|
mock_confirm):
|
|
mock_expanduser.return_value = '/home/fake/'
|
|
argslist = []
|
|
verifylist = [
|
|
('static_inventory', None),
|
|
('playbook', 'all')
|
|
]
|
|
self.assertRaises(ParserException, lambda: self.check_parser(
|
|
self.cmd, argslist, verifylist))
|
|
|
|
|
|
class TestOvercloudUpdateConverge(fakes.TestOvercloudUpdateConverge):
|
|
def setUp(self):
|
|
super(TestOvercloudUpdateConverge, self).setUp()
|
|
# Get the command object to test
|
|
app_args = mock.Mock()
|
|
app_args.verbose_level = 1
|
|
self.cmd = overcloud_update.UpdateConverge(self.app, app_args)
|
|
|
|
@mock.patch('tripleoclient.utils.get_key')
|
|
@mock.patch('tripleoclient.utils.get_default_working_dir')
|
|
@mock.patch('tripleoclient.utils.ensure_run_as_normal_user')
|
|
@mock.patch('tripleoclient.utils.prompt_user_for_confirmation',
|
|
return_value=True)
|
|
@mock.patch(
|
|
'tripleoclient.utils.run_ansible_playbook')
|
|
def test_update_converge(self, deploy_action, mock_confirm,
|
|
mock_usercheck, mock_dir, mock_key):
|
|
argslist = ['--stack', 'cloud']
|
|
verifylist = [
|
|
('stack', 'cloud')
|
|
]
|
|
mock_dir.return_value = "/home/stack/overcloud-deploy"
|
|
ansible_dir = "{}/config-download/cloud".format(
|
|
mock_dir.return_value
|
|
)
|
|
inventory = "{}/tripleo-ansible-inventory.yaml".format(
|
|
ansible_dir
|
|
)
|
|
ansible_cfg = "{}/ansible.cfg".format(
|
|
ansible_dir
|
|
)
|
|
mock_key.return_value = '/home/stack/.ssh/id_rsa_tripleo'
|
|
|
|
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
|
|
with mock.patch('os.path.exists') as mock_exists, \
|
|
mock.patch('os.path.isfile') as mock_isfile:
|
|
mock_exists.return_value = True
|
|
mock_isfile.return_value = True
|
|
self.cmd.take_action(parsed_args)
|
|
mock_usercheck.assert_called_once()
|
|
deploy_action.assert_called_once_with(
|
|
playbook='deploy_steps_playbook.yaml',
|
|
inventory=inventory,
|
|
workdir=ansible_dir,
|
|
playbook_dir=ansible_dir,
|
|
ansible_cfg=ansible_cfg,
|
|
ssh_user='tripleo-admin',
|
|
reproduce_command=True,
|
|
forks=parsed_args.ansible_forks,
|
|
extra_env_variables={
|
|
"ANSIBLE_BECOME": True,
|
|
"ANSIBLE_PRIVATE_KEY_FILE":
|
|
"/home/stack/.ssh/id_rsa_tripleo"
|
|
}
|
|
)
|