Remove mistral from the config_download deploy workflow

This change removes all of mistral from the config_download_deploy function
by calling the required functions directly.

- All of the inputs within this function have been cleaned up and documented.
- New log entires will be created when using this method giving the deployer
  a better overall user experience.
- To ensure we're able to support the ability to reproduce commands, the ssh
  args extravar has been moved to an environment variable.
- The methods get_config and get_key have been moved to the utils module.
  This was done to help avoid circular imports.

Update methods have been changed to execute without running within a mistral
workflow. This was changed because there's no need to support the multiple
code paths anymore given config_download is now running directly.

Test classes have been updated to reduce duplication.

With the new streamlined execution process we should see improved deployment
times and better visability into the deployment process.

Task: 38422
Story: 2007212

Depends-On: I006291a2465aa4c950abce76f9e5f9459b76e330
Change-Id: Ide1a4503dd2bdd2d5e494cd1eac483b842a21acf
Co-authored-by: Luke Short <ekultails@gmail.com>
Co-authored-by: Dougal Matthews <dougal@dougalmatthews.com>
Signed-off-by: Kevin Carter <kecarter@redhat.com>
This commit is contained in:
Kevin Carter 2020-02-04 12:19:55 -06:00 committed by Kevin Carter (cloudnull)
parent 712d8d7a61
commit dc9ae1ac5b
27 changed files with 732 additions and 854 deletions

View File

@ -18,6 +18,8 @@ import logging
from osc_lib.command import command from osc_lib.command import command
from osc_lib import exceptions as oscexc from osc_lib import exceptions as oscexc
from tripleo_common.utils import config
from tripleoclient import exceptions from tripleoclient import exceptions
from tripleoclient import utils from tripleoclient import utils
@ -36,6 +38,38 @@ class Command(command.Command):
self.log.exception("Exception occured while running the command") self.log.exception("Exception occured while running the command")
raise raise
@staticmethod
def get_ansible_key_and_dir(no_workflow, stack, orchestration):
"""Return the ansible directory and key path.
:param no_workflow: Enable or disable the mistral workflow code path.
:type no_workflow: Boolean
:oaram stack: Name of a given stack to run against.
:type stack: String
:param orchestration: Orchestration client object.
:type orchestration: Object
:returns: Tuple
"""
if no_workflow:
key = utils.get_key(stack=stack)
stack_config = config.Config(orchestration)
with utils.TempDirs(cleanup=False, chdir=False) as tmp:
stack_config.write_config(
stack_config.fetch_config(stack),
stack,
tmp
)
return key, tmp
else:
# Assumes execution will take place from within a mistral
# container.
key = '.ssh/tripleo-admin-rsa'
return key, None
class Lister(Command, command.Lister): class Lister(Command, command.Lister):
pass pass

View File

@ -16,6 +16,10 @@
import mock import mock
import sys import sys
from osc_lib.tests import utils
from tripleoclient import plugin
AUTH_TOKEN = "foobar" AUTH_TOKEN = "foobar"
AUTH_URL = "http://0.0.0.0" AUTH_URL = "http://0.0.0.0"
@ -36,6 +40,11 @@ class FakeApp(object):
class FakeStackObject(object): class FakeStackObject(object):
stack_name = 'undercloud' stack_name = 'undercloud'
outputs = []
@staticmethod
def get(*args, **kwargs):
pass
class FakeClientManager(object): class FakeClientManager(object):
@ -81,6 +90,8 @@ class FakeClientWrapper(object):
def __init__(self): def __init__(self):
self.ws = FakeWebSocket() self.ws = FakeWebSocket()
self.object_store = FakeObjectClient()
self._instance = mock.Mock()
def messaging_websocket(self): def messaging_websocket(self):
return self.ws return self.ws
@ -125,6 +136,60 @@ class FakeInstanceData(object):
_data = {'token': {}} _data = {'token': {}}
class FakeObjectClient(object):
def __init__(self):
self._instance = mock.Mock()
self.put_object = mock.Mock()
def get_object(self, *args):
return [None, "fake"]
def get_container(self, *args):
return [None, [{"name": "fake"}]]
class FakePlaybookExecution(utils.TestCommand):
def setUp(self, ansible_mock=True):
super(FakePlaybookExecution, self).setUp()
self.app.client_manager.auth_ref = mock.Mock(auth_token="TOKEN")
self.app.client_manager.baremetal = mock.Mock()
self.app.client_manager.compute = mock.Mock()
self.app.client_manager.identity = mock.Mock()
self.app.client_manager.image = mock.Mock()
self.app.client_manager.network = mock.Mock()
tc = self.app.client_manager.tripleoclient = FakeClientWrapper()
self.app.client_manager.workflow_engine = mock.Mock()
stack = self.app.client_manager.orchestration = mock.Mock()
stack.stacks.get.return_value = FakeStackObject
tc.create_mistral_context = plugin.ClientWrapper(
instance=FakeInstanceData
).create_mistral_context
# NOTE(cloudnull): When mistral is gone this should be removed.
workflow = execution = mock.Mock()
execution.id = "IDID"
workflow.executions.create.return_value = execution
self.app.client_manager.workflow_engine = workflow
if ansible_mock:
self.gcn = mock.patch(
'tripleo_common.utils.config.Config',
autospec=True
)
self.gcn.start()
self.addCleanup(self.gcn.stop)
self.mkdirs = mock.patch(
'os.makedirs',
autospec=True
)
self.mkdirs.start()
self.addCleanup(self.mkdirs.stop)
def fake_ansible_runner_run_return(rc=0): def fake_ansible_runner_run_return(rc=0):
return 'Test Status', rc return 'Test Status', rc

View File

@ -14,7 +14,6 @@
# #
import mock import mock
from osc_lib.tests import utils
from tripleoclient.tests import fakes from tripleoclient.tests import fakes
@ -105,43 +104,7 @@ def create_env(**kwargs):
return env return env
class FakeClientWrapper(object): class TestDeployOvercloud(fakes.FakePlaybookExecution):
def __init__(self):
self._instance = mock.Mock()
self.object_store = FakeObjectClient()
def messaging_websocket(self):
return fakes.FakeWebSocket()
class FakeObjectClient(object):
def __init__(self):
self._instance = mock.Mock()
self.put_object = mock.Mock()
def get_object(self, *args):
return [None, "fake"]
def get_container(self, *args):
return [None, [{"name": "fake"}]]
class TestDeployOvercloud(utils.TestCommand):
def setUp(self): def setUp(self):
super(TestDeployOvercloud, self).setUp() super(TestDeployOvercloud, self).setUp(ansible_mock=False)
self.app.client_manager.auth_ref = mock.Mock(auth_token="TOKEN")
self.app.client_manager.baremetal = mock.Mock()
self.app.client_manager.compute = mock.Mock()
self.app.client_manager.identity = mock.Mock()
self.app.client_manager.image = mock.Mock()
self.app.client_manager.network = mock.Mock()
self.app.client_manager.orchestration = mock.Mock()
workflow = execution = mock.Mock()
execution.id = "IDID"
workflow.executions.create.return_value = execution
self.app.client_manager.workflow_engine = workflow
self.app.client_manager.tripleoclient = FakeClientWrapper()

View File

@ -877,9 +877,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
parsed_args) parsed_args)
self.assertIn('/tmp/notthere', str(error)) self.assertIn('/tmp/notthere', str(error))
@mock.patch('tripleoclient.tests.v1.overcloud_deploy.fakes.' def test_validate_args_missing_environment_files(self):
'FakeObjectClient.get_object', autospec=True)
def test_validate_args_missing_environment_files(self, mock_obj):
arglist = ['--templates', arglist = ['--templates',
'-e', 'nonexistent.yaml'] '-e', 'nonexistent.yaml']
verifylist = [ verifylist = [
@ -887,8 +885,6 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
('environment_files', ['nonexistent.yaml']), ('environment_files', ['nonexistent.yaml']),
] ]
mock_obj.side_effect = ObjectClientException(mock.Mock(
'/fake/path not found'))
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(oscexc.CommandError, self.assertRaises(oscexc.CommandError,
@ -1482,8 +1478,6 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
self.cmd.take_action(parsed_args) self.cmd.take_action(parsed_args)
self.assertTrue(fixture.mock_get_hosts_and_enable_ssh_admin.called) self.assertTrue(fixture.mock_get_hosts_and_enable_ssh_admin.called)
self.assertTrue(fixture.mock_config_download.called) self.assertTrue(fixture.mock_config_download.called)
self.assertEqual('ansible.cfg',
fixture.mock_config_download.call_args[0][8])
mock_copy.assert_called_once() mock_copy.assert_called_once()
@mock.patch('tripleoclient.utils.copy_clouds_yaml') @mock.patch('tripleoclient.utils.copy_clouds_yaml')
@ -1514,7 +1508,6 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
self.cmd.take_action(parsed_args) self.cmd.take_action(parsed_args)
fixture.mock_config_download.assert_called() fixture.mock_config_download.assert_called()
self.assertEqual(240*60, fixture.mock_config_download.call_args[0][9])
mock_copy.assert_called_once() mock_copy.assert_called_once()
def test_download_missing_files_from_plan(self): def test_download_missing_files_from_plan(self):

View File

@ -13,38 +13,10 @@
# under the License. # under the License.
# #
import mock
from osc_lib.tests import utils
from tripleoclient.tests import fakes from tripleoclient.tests import fakes
class FakeClientWrapper(object): class TestOvercloudExternalUpdateRun(fakes.FakePlaybookExecution):
def __init__(self):
self._instance = mock.Mock()
self.object_store = FakeObjectClient()
def messaging_websocket(self):
return fakes.FakeWebSocket()
class FakeObjectClient(object):
def __init__(self):
self._instance = mock.Mock()
self.put_object = mock.Mock()
def get_object(self, *args):
return
class TestOvercloudExternalUpdateRun(utils.TestCommand):
def setUp(self): def setUp(self):
super(TestOvercloudExternalUpdateRun, self).setUp() super(TestOvercloudExternalUpdateRun, self).setUp()
self.app.client_manager.auth_ref = mock.Mock(auth_token="TOKEN")
self.app.client_manager.tripleoclient = FakeClientWrapper()
self.app.client_manager.workflow_engine = mock.Mock()
self.app.client_manager.orchestration = mock.Mock()

View File

@ -15,6 +15,7 @@
import mock import mock
from tripleoclient.tests import fakes as ooofakes
from tripleoclient.tests.v1.overcloud_external_update import fakes from tripleoclient.tests.v1.overcloud_external_update import fakes
from tripleoclient.v1 import overcloud_external_update from tripleoclient.v1 import overcloud_external_update
@ -34,13 +35,23 @@ class TestOvercloudExternalUpdateRun(fakes.TestOvercloudExternalUpdateRun):
self.mock_uuid4 = uuid4_patcher.start() self.mock_uuid4 = uuid4_patcher.start()
self.addCleanup(self.mock_uuid4.stop) self.addCleanup(self.mock_uuid4.stop)
@mock.patch('tripleoclient.workflows.package_update.update_ansible', @mock.patch(
'ansible_runner.runner_config.RunnerConfig',
autospec=True,
return_value=ooofakes.FakeRunnerConfig()
)
@mock.patch(
'ansible_runner.Runner.run',
return_value=ooofakes.fake_ansible_runner_run_return()
)
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True) autospec=True)
@mock.patch('os.path.expanduser') @mock.patch('os.path.expanduser')
@mock.patch('oslo_concurrency.processutils.execute') @mock.patch('oslo_concurrency.processutils.execute')
@mock.patch('six.moves.builtins.open') @mock.patch('six.moves.builtins.open')
def test_update_with_user_and_tags(self, mock_open, mock_execute, def test_update_with_user_and_tags(self, mock_open, mock_execute,
mock_expanduser, update_ansible): mock_expanduser, update_ansible,
mock_run, mock_run_prepare):
mock_expanduser.return_value = '/home/fake/' mock_expanduser.return_value = '/home/fake/'
argslist = ['--ssh-user', 'tripleo-admin', argslist = ['--ssh-user', 'tripleo-admin',
'--tags', 'ceph'] '--tags', 'ceph']
@ -54,25 +65,35 @@ class TestOvercloudExternalUpdateRun(fakes.TestOvercloudExternalUpdateRun):
mock_exists.return_value = True mock_exists.return_value = True
self.cmd.take_action(parsed_args) self.cmd.take_action(parsed_args)
update_ansible.assert_called_once_with( update_ansible.assert_called_once_with(
self.app.client_manager,
container='overcloud',
nodes='all',
inventory_file=mock_open().__enter__().read(),
playbook='external_update_steps_playbook.yaml', playbook='external_update_steps_playbook.yaml',
node_user='tripleo-admin', inventory=mock.ANY,
workdir=mock.ANY,
ssh_user='tripleo-admin',
key='/var/lib/mistral/overcloud/ssh_private_key',
module_path='/usr/share/ansible-modules',
limit_hosts='all',
tags='ceph', tags='ceph',
skip_tags='', skip_tags='',
verbosity=0, extra_vars={'ansible_become': True}
extra_vars={}
) )
@mock.patch('tripleoclient.workflows.package_update.update_ansible', @mock.patch(
'ansible_runner.runner_config.RunnerConfig',
autospec=True,
return_value=ooofakes.FakeRunnerConfig()
)
@mock.patch(
'ansible_runner.Runner.run',
return_value=ooofakes.fake_ansible_runner_run_return()
)
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True) autospec=True)
@mock.patch('os.path.expanduser') @mock.patch('os.path.expanduser')
@mock.patch('oslo_concurrency.processutils.execute') @mock.patch('oslo_concurrency.processutils.execute')
@mock.patch('six.moves.builtins.open') @mock.patch('six.moves.builtins.open')
def test_update_with_user_and_extra_vars(self, mock_open, mock_execute, def test_update_with_user_and_extra_vars(self, mock_open, mock_execute,
mock_expanduser, update_ansible): mock_expanduser, update_ansible,
mock_run, mock_run_prepare):
mock_expanduser.return_value = '/home/fake/' mock_expanduser.return_value = '/home/fake/'
argslist = ['--ssh-user', 'tripleo-admin', argslist = ['--ssh-user', 'tripleo-admin',
'--extra-vars', 'key1=val1', '--extra-vars', 'key1=val1',
@ -87,14 +108,18 @@ class TestOvercloudExternalUpdateRun(fakes.TestOvercloudExternalUpdateRun):
mock_exists.return_value = True mock_exists.return_value = True
self.cmd.take_action(parsed_args) self.cmd.take_action(parsed_args)
update_ansible.assert_called_once_with( update_ansible.assert_called_once_with(
self.app.client_manager,
container='overcloud',
nodes='all',
inventory_file=mock_open().__enter__().read(),
playbook='external_update_steps_playbook.yaml', playbook='external_update_steps_playbook.yaml',
node_user='tripleo-admin', inventory=mock.ANY,
workdir=mock.ANY,
ssh_user='tripleo-admin',
key='/var/lib/mistral/overcloud/ssh_private_key',
module_path='/usr/share/ansible-modules',
limit_hosts='all',
tags='', tags='',
skip_tags='', skip_tags='',
verbosity=0, extra_vars={
extra_vars={'key1': 'val1', 'key2': 'val2'} 'key1': 'val1',
'key2': 'val2',
'ansible_become': True
}
) )

View File

@ -13,38 +13,10 @@
# under the License. # under the License.
# #
import mock
from osc_lib.tests import utils
from tripleoclient.tests import fakes from tripleoclient.tests import fakes
class FakeClientWrapper(object): class TestOvercloudExternalUpgradeRun(fakes.FakePlaybookExecution):
def __init__(self):
self._instance = mock.Mock()
self.object_store = FakeObjectClient()
def messaging_websocket(self):
return fakes.FakeWebSocket()
class FakeObjectClient(object):
def __init__(self):
self._instance = mock.Mock()
self.put_object = mock.Mock()
def get_object(self, *args):
return
class TestOvercloudExternalUpgradeRun(utils.TestCommand):
def setUp(self): def setUp(self):
super(TestOvercloudExternalUpgradeRun, self).setUp() super(TestOvercloudExternalUpgradeRun, self).setUp()
self.app.client_manager.auth_ref = mock.Mock(auth_token="TOKEN")
self.app.client_manager.tripleoclient = FakeClientWrapper()
self.app.client_manager.workflow_engine = mock.Mock()
self.app.client_manager.orchestration = mock.Mock()

View File

@ -15,6 +15,7 @@
import mock import mock
from tripleoclient.tests import fakes as ooofakes
from tripleoclient.tests.v1.overcloud_external_upgrade import fakes from tripleoclient.tests.v1.overcloud_external_upgrade import fakes
from tripleoclient.v1 import overcloud_external_upgrade from tripleoclient.v1 import overcloud_external_upgrade
@ -34,13 +35,23 @@ class TestOvercloudExternalUpgradeRun(fakes.TestOvercloudExternalUpgradeRun):
self.mock_uuid4 = uuid4_patcher.start() self.mock_uuid4 = uuid4_patcher.start()
self.addCleanup(self.mock_uuid4.stop) self.addCleanup(self.mock_uuid4.stop)
@mock.patch('tripleoclient.workflows.package_update.update_ansible', @mock.patch(
'ansible_runner.runner_config.RunnerConfig',
autospec=True,
return_value=ooofakes.FakeRunnerConfig()
)
@mock.patch(
'ansible_runner.Runner.run',
return_value=ooofakes.fake_ansible_runner_run_return()
)
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True) autospec=True)
@mock.patch('os.path.expanduser') @mock.patch('os.path.expanduser')
@mock.patch('oslo_concurrency.processutils.execute') @mock.patch('oslo_concurrency.processutils.execute')
@mock.patch('six.moves.builtins.open') @mock.patch('six.moves.builtins.open')
def test_upgrade_with_user_and_tags(self, mock_open, mock_execute, def test_upgrade_with_user_and_tags(self, mock_open, mock_execute,
mock_expanduser, update_ansible): mock_expanduser, update_ansible,
mock_run, mock_run_prepare):
mock_expanduser.return_value = '/home/fake/' mock_expanduser.return_value = '/home/fake/'
argslist = ['--ssh-user', 'tripleo-admin', argslist = ['--ssh-user', 'tripleo-admin',
'--tags', 'ceph'] '--tags', 'ceph']
@ -54,25 +65,35 @@ class TestOvercloudExternalUpgradeRun(fakes.TestOvercloudExternalUpgradeRun):
mock_exists.return_value = True mock_exists.return_value = True
self.cmd.take_action(parsed_args) self.cmd.take_action(parsed_args)
update_ansible.assert_called_once_with( update_ansible.assert_called_once_with(
self.app.client_manager,
container='overcloud',
nodes='all',
inventory_file=mock_open().__enter__().read(),
playbook='external_upgrade_steps_playbook.yaml', playbook='external_upgrade_steps_playbook.yaml',
node_user='tripleo-admin', inventory=mock.ANY,
workdir=mock.ANY,
ssh_user='tripleo-admin',
key='/var/lib/mistral/overcloud/ssh_private_key',
module_path='/usr/share/ansible-modules',
limit_hosts='all',
tags='ceph', tags='ceph',
skip_tags='', skip_tags='',
verbosity=0, extra_vars={'ansible_become': True}
extra_vars={}
) )
@mock.patch('tripleoclient.workflows.package_update.update_ansible', @mock.patch(
'ansible_runner.runner_config.RunnerConfig',
autospec=True,
return_value=ooofakes.FakeRunnerConfig()
)
@mock.patch(
'ansible_runner.Runner.run',
return_value=ooofakes.fake_ansible_runner_run_return()
)
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True) autospec=True)
@mock.patch('os.path.expanduser') @mock.patch('os.path.expanduser')
@mock.patch('oslo_concurrency.processutils.execute') @mock.patch('oslo_concurrency.processutils.execute')
@mock.patch('six.moves.builtins.open') @mock.patch('six.moves.builtins.open')
def test_upgrade_with_user_and_extra_vars(self, mock_open, mock_execute, def test_upgrade_with_user_and_extra_vars(self, mock_open, mock_execute,
mock_expanduser, update_ansible): mock_expanduser, update_ansible,
mock_run, mock_run_prepare):
mock_expanduser.return_value = '/home/fake/' mock_expanduser.return_value = '/home/fake/'
argslist = ['--ssh-user', 'tripleo-admin', argslist = ['--ssh-user', 'tripleo-admin',
'--extra-vars', 'key1=val1', '--extra-vars', 'key1=val1',
@ -87,14 +108,18 @@ class TestOvercloudExternalUpgradeRun(fakes.TestOvercloudExternalUpgradeRun):
mock_exists.return_value = True mock_exists.return_value = True
self.cmd.take_action(parsed_args) self.cmd.take_action(parsed_args)
update_ansible.assert_called_once_with( update_ansible.assert_called_once_with(
self.app.client_manager,
container='overcloud',
nodes='all',
inventory_file=mock_open().__enter__().read(),
playbook='external_upgrade_steps_playbook.yaml', playbook='external_upgrade_steps_playbook.yaml',
node_user='tripleo-admin', inventory=mock.ANY,
workdir=mock.ANY,
ssh_user='tripleo-admin',
key='/var/lib/mistral/overcloud/ssh_private_key',
module_path='/usr/share/ansible-modules',
limit_hosts='all',
tags='', tags='',
skip_tags='', skip_tags='',
verbosity=0, extra_vars={
extra_vars={'key1': 'val1', 'key2': 'val2'} 'key1': 'val1',
'key2': 'val2',
'ansible_become': True
}
) )

View File

@ -13,78 +13,22 @@
# under the License. # under the License.
# #
import mock
from osc_lib.tests import utils
from tripleoclient import plugin
from tripleoclient.tests import fakes from tripleoclient.tests import fakes
class FakeClientWrapper(object): class TestFFWDUpgradePrepare(fakes.FakePlaybookExecution):
def __init__(self):
self._instance = mock.Mock()
self.object_store = FakeObjectClient()
def messaging_websocket(self, queue="tripleo"):
return fakes.FakeWebSocket()
class FakeObjectClient(object):
def __init__(self):
self._instance = mock.Mock()
self.put_object = mock.Mock()
def get_object(self, *args):
return
class TestFFWDUpgradePrepare(utils.TestCommand):
def setUp(self): def setUp(self):
super(TestFFWDUpgradePrepare, self).setUp() super(TestFFWDUpgradePrepare, self).setUp()
self.app.client_manager.auth_ref = mock.Mock(auth_token="TOKEN")
self.app.client_manager.baremetal = mock.Mock()
self.app.client_manager.orchestration = mock.Mock()
workflow = execution = mock.Mock()
execution.id = "IDID"
workflow.executions.create.return_value = execution
self.app.client_manager.workflow_engine = workflow
tc = self.app.client_manager.tripleoclient = FakeClientWrapper()
tc.create_mistral_context = plugin.ClientWrapper(
instance=fakes.FakeInstanceData
).create_mistral_context
class TestFFWDUpgradeRun(fakes.FakePlaybookExecution):
class TestFFWDUpgradeRun(utils.TestCommand):
def setUp(self): def setUp(self):
super(TestFFWDUpgradeRun, self).setUp() super(TestFFWDUpgradeRun, self).setUp()
self.app.client_manager.auth_ref = mock.Mock(auth_token="TOKEN")
self.app.client_manager.workflow_engine = mock.Mock()
self.app.client_manager.orchestration = mock.Mock()
tc = self.app.client_manager.tripleoclient = FakeClientWrapper()
tc.create_mistral_context = plugin.ClientWrapper(
instance=fakes.FakeInstanceData
).create_mistral_context
class TestFFWDUpgradeConverge(fakes.FakePlaybookExecution):
class TestFFWDUpgradeConverge(utils.TestCommand):
def setUp(self): def setUp(self):
super(TestFFWDUpgradeConverge, self).setUp() super(TestFFWDUpgradeConverge, self).setUp()
self.app.client_manager.auth_ref = mock.Mock(auth_token="TOKEN")
self.app.client_manager.baremetal = mock.Mock()
self.app.client_manager.orchestration = mock.Mock()
workflow = execution = mock.Mock()
execution.id = "IDID"
workflow.executions.create.return_value = execution
self.app.client_manager.workflow_engine = workflow
tc = self.app.client_manager.tripleoclient = FakeClientWrapper()
tc.create_mistral_context = plugin.ClientWrapper(
instance=fakes.FakeInstanceData
).create_mistral_context

View File

@ -155,7 +155,7 @@ class TestFFWDUpgradeRun(fakes.TestFFWDUpgradeRun):
self.mock_uuid4 = uuid4_patcher.start() self.mock_uuid4 = uuid4_patcher.start()
self.addCleanup(self.mock_uuid4.stop) self.addCleanup(self.mock_uuid4.stop)
@mock.patch('tripleoclient.workflows.package_update.update_ansible', @mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True) autospec=True)
@mock.patch('os.path.expanduser') @mock.patch('os.path.expanduser')
@mock.patch('oslo_concurrency.processutils.execute') @mock.patch('oslo_concurrency.processutils.execute')
@ -171,19 +171,19 @@ class TestFFWDUpgradeRun(fakes.TestFFWDUpgradeRun):
mock_exists.return_value = True mock_exists.return_value = True
self.cmd.take_action(parsed_args) self.cmd.take_action(parsed_args)
upgrade_ansible.assert_called_once_with( upgrade_ansible.assert_called_once_with(
self.app.client_manager, playbook='fast_forward_upgrade_playbook.yaml',
container='overcloud', inventory=mock.ANY,
inventory_file=mock_open().__enter__().read(), workdir=mock.ANY,
nodes='', ssh_user='heat-admin',
playbook=constants.FFWD_UPGRADE_PLAYBOOK, key='/var/lib/mistral/overcloud/ssh_private_key',
node_user='heat-admin', module_path='/usr/share/ansible-modules',
limit_hosts='',
tags='', tags='',
skip_tags='', skip_tags='',
verbosity=0, extra_vars={'ansible_become': True}
extra_vars=None
) )
@mock.patch('tripleoclient.workflows.package_update.update_ansible', @mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True) autospec=True)
@mock.patch('os.path.expanduser') @mock.patch('os.path.expanduser')
@mock.patch('oslo_concurrency.processutils.execute') @mock.patch('oslo_concurrency.processutils.execute')
@ -199,19 +199,19 @@ class TestFFWDUpgradeRun(fakes.TestFFWDUpgradeRun):
mock_exists.return_value = True mock_exists.return_value = True
self.cmd.take_action(parsed_args) self.cmd.take_action(parsed_args)
upgrade_ansible.assert_called_once_with( upgrade_ansible.assert_called_once_with(
self.app.client_manager, playbook='fast_forward_upgrade_playbook.yaml',
container='overcloud', inventory=mock.ANY,
inventory_file=mock_open().__enter__().read(), workdir=mock.ANY,
nodes='', ssh_user='my-user',
playbook=constants.FFWD_UPGRADE_PLAYBOOK, key='/var/lib/mistral/overcloud/ssh_private_key',
node_user='my-user', module_path='/usr/share/ansible-modules',
limit_hosts='',
tags='', tags='',
skip_tags='', skip_tags='',
verbosity=0, extra_vars={'ansible_become': True}
extra_vars=None
) )
@mock.patch('tripleoclient.workflows.package_update.update_ansible', @mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True) autospec=True)
@mock.patch('os.path.expanduser') @mock.patch('os.path.expanduser')
@mock.patch('oslo_concurrency.processutils.execute') @mock.patch('oslo_concurrency.processutils.execute')

View File

@ -51,10 +51,31 @@ class TestDeleteNode(fakes.TestDeleteNode):
tc.create_mistral_context = plugin.ClientWrapper( tc.create_mistral_context = plugin.ClientWrapper(
instance=ooofakes.FakeInstanceData instance=ooofakes.FakeInstanceData
).create_mistral_context ).create_mistral_context
self.gcn = mock.patch(
'tripleo_common.actions.config.DownloadConfigAction',
autospec=True
)
self.gcn.start()
self.addCleanup(self.gcn.stop)
self.ansible = mock.patch(
'tripleo_common.actions.ansible.AnsibleGenerateInventoryAction',
autospec=True
)
self.ansible.start()
self.addCleanup(self.ansible.stop)
config_mock = mock.patch(
'tripleo_common.actions.config.GetOvercloudConfig',
autospec=True
)
config_mock.start()
self.addCleanup(config_mock.stop)
self.workflow = self.app.client_manager.workflow_engine self.workflow = self.app.client_manager.workflow_engine
self.stack_name = self.app.client_manager.orchestration.stacks.get self.stack_name = self.app.client_manager.orchestration.stacks.get
self.stack_name.return_value = mock.Mock(stack_name="overcloud") stack = self.stack_name.return_value = mock.Mock(
stack_name="overcloud"
)
stack.output_show.return_value = {'output': {'output_value': []}}
execution = mock.Mock() execution = mock.Mock()
execution.id = "IDID" execution.id = "IDID"
self.workflow.executions.create.return_value = execution self.workflow.executions.create.return_value = execution
@ -67,11 +88,19 @@ class TestDeleteNode(fakes.TestDeleteNode):
delete_node.return_value = None delete_node.return_value = None
self.addCleanup(delete_node.stop) self.addCleanup(delete_node.stop)
wait_stack = mock.patch(
'tripleoclient.utils.wait_for_stack_ready',
autospec=True
)
wait_stack.start()
wait_stack.return_value = None
self.addCleanup(wait_stack.stop)
# TODO(someone): This test does not pass with autospec=True, it should # TODO(someone): This test does not pass with autospec=True, it should
# probably be fixed so that it can pass with that. # probably be fixed so that it can pass with that.
@mock.patch("heatclient.common.event_utils.poll_for_events") @mock.patch('tripleoclient.utils.run_ansible_playbook',
def test_node_delete(self, mock_poll): autospec=True)
mock_poll.return_value = ("CREATE_IN_PROGRESS", "MESSAGE") def test_node_delete(self, mock_playbook):
argslist = ['instance1', 'instance2', '--templates', argslist = ['instance1', 'instance2', '--templates',
'--stack', 'overcast', '--timeout', '90', '--yes'] '--stack', 'overcast', '--timeout', '90', '--yes']
verifylist = [ verifylist = [
@ -79,14 +108,6 @@ class TestDeleteNode(fakes.TestDeleteNode):
('nodes', ['instance1', 'instance2']) ('nodes', ['instance1', 'instance2'])
] ]
parsed_args = self.check_parser(self.cmd, argslist, verifylist) parsed_args = self.check_parser(self.cmd, argslist, verifylist)
self.websocket.wait_for_messages.return_value = iter([{
"execution_id": "IDID",
"status": "SUCCESS",
"message": "Success.",
}])
self.stack_name.return_value = mock.Mock(stack_name="overcast")
self.cmd.take_action(parsed_args) self.cmd.take_action(parsed_args)
@mock.patch('tripleoclient.utils.prompt_user_for_confirmation', @mock.patch('tripleoclient.utils.prompt_user_for_confirmation',
@ -122,9 +143,9 @@ class TestDeleteNode(fakes.TestDeleteNode):
# Verify # Verify
self.workflow.executions.create.assert_not_called() self.workflow.executions.create.assert_not_called()
@mock.patch("heatclient.common.event_utils.poll_for_events") @mock.patch('tripleoclient.utils.run_ansible_playbook',
def test_node_delete_without_stack(self, mock_poll): autospec=True)
mock_poll.return_value = ("CREATE_IN_PROGRESS", "MESSAGE") def test_node_delete_without_stack(self, mock_playbook):
arglist = ['instance1', '--yes'] arglist = ['instance1', '--yes']
verifylist = [ verifylist = [
@ -132,49 +153,17 @@ class TestDeleteNode(fakes.TestDeleteNode):
('nodes', ['instance1']), ('nodes', ['instance1']),
] ]
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.websocket.wait_for_messages.return_value = iter([{
"execution_id": "IDID",
"status": "SUCCESS",
"message": "Success.",
}])
self.cmd.take_action(parsed_args) self.cmd.take_action(parsed_args)
def test_node_delete_wrong_instance(self): @mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True)
argslist = ['wrong_instance', '--templates',
'--stack', 'overcloud', '--yes']
verifylist = [
('stack', 'overcloud'),
('nodes', ['wrong_instance']),
]
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
self.websocket.wait_for_messages.return_value = iter([{
"status": "FAILED",
"execution_id": "IDID",
"message": """Failed to run action ERROR: Couldn't find \
following instances in stack overcloud: wrong_instance"""
}])
# Verify
self.assertRaises(exceptions.DeploymentError,
self.cmd.take_action, parsed_args)
@mock.patch("heatclient.common.event_utils.poll_for_events")
@mock.patch('tripleoclient.workflows.baremetal.expand_roles', @mock.patch('tripleoclient.workflows.baremetal.expand_roles',
autospec=True) autospec=True)
@mock.patch('tripleoclient.workflows.baremetal.undeploy_roles', @mock.patch('tripleoclient.workflows.baremetal.undeploy_roles',
autospec=True) autospec=True)
def test_node_delete_baremetal_deployment(self, mock_undeploy_roles, def test_node_delete_baremetal_deployment(self, mock_undeploy_roles,
mock_expand_roles, mock_poll): mock_expand_roles,
mock_poll.return_value = ("CREATE_IN_PROGRESS", "MESSAGE") mock_playbook):
self.websocket.wait_for_messages.return_value = iter([{
"execution_id": "IDID",
"status": "SUCCESS",
"message": "Success.",
}])
bm_yaml = [{ bm_yaml = [{
'name': 'Compute', 'name': 'Compute',
'count': 5, 'count': 5,
@ -219,7 +208,6 @@ class TestDeleteNode(fakes.TestDeleteNode):
expand_to_translate expand_to_translate
] ]
self.stack_name.return_value = mock.Mock(stack_name="overcast")
res_list = self.app.client_manager.orchestration.resources.list res_list = self.app.client_manager.orchestration.resources.list
res_list.return_value = [ res_list.return_value = [
mock.Mock( mock.Mock(

View File

@ -13,75 +13,22 @@
# under the License. # under the License.
# #
import mock
from osc_lib.tests import utils
from tripleoclient import plugin
from tripleoclient.tests import fakes from tripleoclient.tests import fakes
class FakeClientWrapper(object): class TestOvercloudUpdatePrepare(fakes.FakePlaybookExecution):
def __init__(self):
self._instance = mock.Mock()
self.object_store = FakeObjectClient()
def messaging_websocket(self):
return fakes.FakeWebSocket()
class FakeObjectClient(object):
def __init__(self):
self._instance = mock.Mock()
self.put_object = mock.Mock()
def get_object(self, *args):
return
class TestOvercloudUpdatePrepare(utils.TestCommand):
def setUp(self): def setUp(self):
super(TestOvercloudUpdatePrepare, self).setUp() super(TestOvercloudUpdatePrepare, self).setUp()
self.app.client_manager.auth_ref = mock.Mock(auth_token="TOKEN")
self.app.client_manager.baremetal = mock.Mock()
self.app.client_manager.orchestration = mock.Mock()
workflow = execution = mock.Mock()
execution.id = "IDID"
workflow.executions.create.return_value = execution
self.app.client_manager.workflow_engine = workflow
tc = self.app.client_manager.tripleoclient = FakeClientWrapper()
tc.create_mistral_context = plugin.ClientWrapper(
instance=fakes.FakeInstanceData
).create_mistral_context
class TestOvercloudUpdateRun(fakes.FakePlaybookExecution):
class TestOvercloudUpdateRun(utils.TestCommand):
def setUp(self): def setUp(self):
super(TestOvercloudUpdateRun, self).setUp() super(TestOvercloudUpdateRun, self).setUp()
self.app.client_manager.auth_ref = mock.Mock(auth_token="TOKEN")
self.app.client_manager.workflow_engine = mock.Mock()
self.app.client_manager.orchestration = mock.Mock()
tc = self.app.client_manager.tripleoclient = FakeClientWrapper()
tc.create_mistral_context = plugin.ClientWrapper(
instance=fakes.FakeInstanceData
).create_mistral_context
class TestOvercloudUpdateConverge(fakes.FakePlaybookExecution):
class TestOvercloudUpdateConverge(utils.TestCommand):
def setUp(self): def setUp(self):
super(TestOvercloudUpdateConverge, self).setUp() super(TestOvercloudUpdateConverge, self).setUp()
self.app.client_manager.auth_ref = mock.Mock(auth_token="TOKEN")
self.app.client_manager.baremetal = mock.Mock()
self.app.client_manager.orchestration = mock.Mock()
self.app.client_manager.workflow_engine = mock.Mock()
tc = self.app.client_manager.tripleoclient = FakeClientWrapper()
tc.create_mistral_context = plugin.ClientWrapper(
instance=fakes.FakeInstanceData
).create_mistral_context

View File

@ -130,75 +130,7 @@ class TestOvercloudUpdateRun(fakes.TestOvercloudUpdateRun):
self.mock_uuid4 = uuid4_patcher.start() self.mock_uuid4 = uuid4_patcher.start()
self.addCleanup(self.mock_uuid4.stop) self.addCleanup(self.mock_uuid4.stop)
@mock.patch('tripleoclient.workflows.package_update.update_ansible', @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_playbook_and_user(self, mock_open, mock_execute,
mock_expanduser, update_ansible):
mock_expanduser.return_value = '/home/fake/'
argslist = ['--limit', 'Compute',
'--playbook', 'fake-playbook.yaml',
'--ssh-user', 'tripleo-admin']
verifylist = [
('limit', 'Compute'),
('static_inventory', None),
('playbook', 'fake-playbook.yaml'),
('ssh_user', 'tripleo-admin')
]
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
with mock.patch('os.path.exists') as mock_exists:
mock_exists.return_value = True
self.cmd.take_action(parsed_args)
update_ansible.assert_called_once_with(
self.app.client_manager,
container='overcloud',
nodes='Compute',
inventory_file=mock_open().__enter__().read(),
playbook='fake-playbook.yaml',
node_user='tripleo-admin',
tags='',
skip_tags='',
verbosity=0,
extra_vars=None
)
@mock.patch('tripleoclient.workflows.package_update.update_ansible',
autospec=True)
@mock.patch('os.path.expanduser')
@mock.patch('oslo_concurrency.processutils.execute')
@mock.patch('six.moves.builtins.open')
def test_update_limit_with_all_playbooks(self, mock_open, mock_execute,
mock_expanduser, update_ansible):
mock_expanduser.return_value = '/home/fake/'
argslist = ['--limit', 'Compute', '--playbook', 'all']
verifylist = [
('limit', 'Compute'),
('static_inventory', None),
('playbook', 'all')
]
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
with mock.patch('os.path.exists') as mock_exists:
mock_exists.return_value = True
self.cmd.take_action(parsed_args)
for book in constants.MINOR_UPDATE_PLAYBOOKS:
update_ansible.assert_any_call(
self.app.client_manager,
container='overcloud',
nodes='Compute',
inventory_file=mock_open().__enter__().read(),
playbook=book,
node_user='tripleo-admin',
tags='',
skip_tags='',
verbosity=0,
extra_vars=None
)
@mock.patch('tripleoclient.workflows.package_update.update_ansible',
autospec=True) autospec=True)
@mock.patch('os.path.expanduser') @mock.patch('os.path.expanduser')
@mock.patch('oslo_concurrency.processutils.execute') @mock.patch('oslo_concurrency.processutils.execute')

View File

@ -13,57 +13,16 @@
# under the License. # under the License.
# #
import mock
from osc_lib.tests import utils
from tripleoclient import plugin
from tripleoclient.tests import fakes from tripleoclient.tests import fakes
class FakeClientWrapper(object): class TestOvercloudUpgradePrepare(fakes.FakePlaybookExecution):
def __init__(self):
self._instance = mock.Mock()
self.object_store = FakeObjectClient()
def messaging_websocket(self):
return fakes.FakeWebSocket()
class FakeObjectClient(object):
def __init__(self):
self._instance = mock.Mock()
self.put_object = mock.Mock()
def get_object(self, *args):
return
class TestOvercloudUpgradePrepare(utils.TestCommand):
def setUp(self): def setUp(self):
super(TestOvercloudUpgradePrepare, self).setUp() super(TestOvercloudUpgradePrepare, self).setUp()
self.app.client_manager.auth_ref = mock.Mock(auth_token="TOKEN")
self.app.client_manager.baremetal = mock.Mock()
self.app.client_manager.orchestration = mock.Mock()
tc = self.app.client_manager.tripleoclient = FakeClientWrapper()
tc.create_mistral_context = plugin.ClientWrapper(
instance=fakes.FakeInstanceData
).create_mistral_context
workflow = execution = mock.Mock()
execution.id = "IDID"
workflow.executions.create.return_value = execution
self.app.client_manager.workflow_engine = workflow
class TestOvercloudUpgradeRun(fakes.FakePlaybookExecution):
class TestOvercloudUpgradeRun(utils.TestCommand):
def setUp(self): def setUp(self):
super(TestOvercloudUpgradeRun, self).setUp() super(TestOvercloudUpgradeRun, self).setUp()
self.app.client_manager.auth_ref = mock.Mock(auth_token="TOKEN")
self.app.client_manager.tripleoclient = FakeClientWrapper()
self.app.client_manager.workflow_engine = mock.Mock()
self.app.client_manager.orchestration = mock.Mock()

View File

@ -19,6 +19,7 @@ from osc_lib import exceptions as oscexc
from osc_lib.tests.utils import ParserException from osc_lib.tests.utils import ParserException
from tripleoclient import constants from tripleoclient import constants
from tripleoclient import exceptions from tripleoclient import exceptions
from tripleoclient.tests import fakes as ooofakes
from tripleoclient.tests.v1.overcloud_upgrade import fakes from tripleoclient.tests.v1.overcloud_upgrade import fakes
from tripleoclient.v1 import overcloud_upgrade from tripleoclient.v1 import overcloud_upgrade
@ -173,13 +174,23 @@ class TestOvercloudUpgradeRun(fakes.TestOvercloudUpgradeRun):
self.mock_uuid4 = uuid4_patcher.start() self.mock_uuid4 = uuid4_patcher.start()
self.addCleanup(self.mock_uuid4.stop) self.addCleanup(self.mock_uuid4.stop)
@mock.patch('tripleoclient.workflows.package_update.update_ansible', @mock.patch(
'ansible_runner.runner_config.RunnerConfig',
autospec=True,
return_value=ooofakes.FakeRunnerConfig()
)
@mock.patch(
'ansible_runner.Runner.run',
return_value=ooofakes.fake_ansible_runner_run_return()
)
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True) autospec=True)
@mock.patch('os.path.expanduser') @mock.patch('os.path.expanduser')
@mock.patch('oslo_concurrency.processutils.execute') @mock.patch('oslo_concurrency.processutils.execute')
@mock.patch('six.moves.builtins.open') @mock.patch('six.moves.builtins.open')
def test_upgrade_limit_with_playbook_and_user( def test_upgrade_limit_with_playbook_and_user(
self, mock_open, mock_execute, mock_expanduser, upgrade_ansible): self, mock_open, mock_execute, mock_expanduser, upgrade_ansible,
mock_run, mock_run_prepare):
mock_expanduser.return_value = '/home/fake/' mock_expanduser.return_value = '/home/fake/'
argslist = ['--limit', 'Compute, Controller', argslist = ['--limit', 'Compute, Controller',
'--playbook', 'fake-playbook.yaml', '--playbook', 'fake-playbook.yaml',
@ -195,95 +206,35 @@ class TestOvercloudUpgradeRun(fakes.TestOvercloudUpgradeRun):
mock_exists.return_value = True mock_exists.return_value = True
self.cmd.take_action(parsed_args) self.cmd.take_action(parsed_args)
upgrade_ansible.assert_called_once_with( upgrade_ansible.assert_called_once_with(
self.app.client_manager,
container='overcloud',
nodes='Compute, Controller',
inventory_file=mock_open().__enter__().read(),
playbook='fake-playbook.yaml', playbook='fake-playbook.yaml',
node_user='tripleo-admin', inventory=mock.ANY,
workdir=mock.ANY,
ssh_user='tripleo-admin',
key='/var/lib/mistral/overcloud/ssh_private_key',
module_path='/usr/share/ansible-modules',
limit_hosts='Compute, Controller',
tags='', tags='',
skip_tags='', skip_tags='',
verbosity=0, extra_vars={'ansible_become': True}
extra_vars=None
) )
@mock.patch('tripleoclient.workflows.package_update.update_ansible', @mock.patch(
autospec=True) 'ansible_runner.runner_config.RunnerConfig',
@mock.patch('os.path.expanduser') autospec=True,
@mock.patch('oslo_concurrency.processutils.execute') return_value=ooofakes.FakeRunnerConfig()
@mock.patch('six.moves.builtins.open') )
def test_upgrade_limit_all_playbooks_skip_validation( @mock.patch(
self, mock_open, mock_execute, mock_expanduser, upgrade_ansible): 'ansible_runner.Runner.run',
mock_expanduser.return_value = '/home/fake/' return_value=ooofakes.fake_ansible_runner_run_return()
argslist = ['--limit', 'Compute', '--playbook', 'all', )
'--skip-tags', 'validation'] @mock.patch('tripleoclient.utils.run_ansible_playbook',
verifylist = [
('limit', 'Compute'),
('static_inventory', None),
('playbook', 'all'),
('skip_tags', 'validation')
]
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
with mock.patch('os.path.exists') as mock_exists:
mock_exists.return_value = True
self.cmd.take_action(parsed_args)
for book in constants.MAJOR_UPGRADE_PLAYBOOKS:
upgrade_ansible.assert_any_call(
self.app.client_manager,
container='overcloud',
nodes='Compute',
inventory_file=mock_open().__enter__().read(),
playbook=book,
node_user='tripleo-admin',
tags='',
skip_tags='validation',
verbosity=0,
extra_vars=None
)
@mock.patch('tripleoclient.workflows.package_update.update_ansible',
autospec=True)
@mock.patch('os.path.expanduser')
@mock.patch('oslo_concurrency.processutils.execute')
@mock.patch('six.moves.builtins.open')
def test_upgrade_limit_all_playbooks_only_validation(
self, mock_open, mock_execute, mock_expanduser, upgrade_ansible):
mock_expanduser.return_value = '/home/fake/'
argslist = ['--limit', 'Compute', '--playbook', 'all',
'--tags', 'validation']
verifylist = [
('limit', 'Compute'),
('static_inventory', None),
('playbook', 'all'),
('tags', 'validation')
]
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
with mock.patch('os.path.exists') as mock_exists:
mock_exists.return_value = True
self.cmd.take_action(parsed_args)
for book in constants.MAJOR_UPGRADE_PLAYBOOKS:
upgrade_ansible.assert_any_call(
self.app.client_manager,
container='overcloud',
nodes='Compute',
inventory_file=mock_open().__enter__().read(),
playbook=book,
node_user='tripleo-admin',
tags='validation',
skip_tags='',
verbosity=0,
extra_vars=None
)
@mock.patch('tripleoclient.workflows.package_update.update_ansible',
autospec=True) autospec=True)
@mock.patch('os.path.expanduser') @mock.patch('os.path.expanduser')
@mock.patch('oslo_concurrency.processutils.execute') @mock.patch('oslo_concurrency.processutils.execute')
@mock.patch('six.moves.builtins.open') @mock.patch('six.moves.builtins.open')
def test_upgrade_nodes_with_playbook_no_skip_tags( def test_upgrade_nodes_with_playbook_no_skip_tags(
self, mock_open, mock_execute, mock_expanduser, upgrade_ansible): self, mock_open, mock_execute, mock_expanduser, upgrade_ansible,
mock_run, mock_run_prepare):
mock_expanduser.return_value = '/home/fake/' mock_expanduser.return_value = '/home/fake/'
argslist = ['--limit', 'compute-0, compute-1', argslist = ['--limit', 'compute-0, compute-1',
'--playbook', 'fake-playbook.yaml', ] '--playbook', 'fake-playbook.yaml', ]
@ -298,87 +249,19 @@ class TestOvercloudUpgradeRun(fakes.TestOvercloudUpgradeRun):
mock_exists.return_value = True mock_exists.return_value = True
self.cmd.take_action(parsed_args) self.cmd.take_action(parsed_args)
upgrade_ansible.assert_called_once_with( upgrade_ansible.assert_called_once_with(
self.app.client_manager,
container='overcloud',
nodes='compute-0, compute-1',
inventory_file=mock_open().__enter__().read(),
playbook='fake-playbook.yaml', playbook='fake-playbook.yaml',
node_user='tripleo-admin', inventory=mock.ANY,
workdir=mock.ANY,
ssh_user='tripleo-admin',
key='/var/lib/mistral/overcloud/ssh_private_key',
module_path='/usr/share/ansible-modules',
limit_hosts='compute-0, compute-1',
tags='', tags='',
skip_tags='', skip_tags='',
verbosity=0, extra_vars={'ansible_become': True}
extra_vars=None
) )
@mock.patch('tripleoclient.workflows.package_update.update_ansible', @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_upgrade_node_all_playbooks_skip_tags_default(
self, mock_open, mock_execute, mock_expanduser, upgrade_ansible):
mock_expanduser.return_value = '/home/fake/'
argslist = ['--limit', 'swift-1', '--playbook', 'all']
verifylist = [
('limit', 'swift-1'),
('static_inventory', None),
('playbook', 'all'),
]
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
with mock.patch('os.path.exists') as mock_exists:
mock_exists.return_value = True
self.cmd.take_action(parsed_args)
for book in constants.MAJOR_UPGRADE_PLAYBOOKS:
upgrade_ansible.assert_any_call(
self.app.client_manager,
container='overcloud',
nodes='swift-1',
inventory_file=mock_open().__enter__().read(),
playbook=book,
node_user='tripleo-admin',
tags='',
skip_tags='',
verbosity=0,
extra_vars=None
)
@mock.patch('tripleoclient.workflows.package_update.update_ansible',
autospec=True)
@mock.patch('os.path.expanduser')
@mock.patch('oslo_concurrency.processutils.execute')
@mock.patch('six.moves.builtins.open')
def test_upgrade_node_all_playbooks_skip_tags_all_supported(
self, mock_open, mock_execute, mock_expanduser, upgrade_ansible):
mock_expanduser.return_value = '/home/fake/'
argslist = ['--limit', 'swift-1', '--playbook', 'all',
'--skip-tags', 'pre-upgrade,validation']
verifylist = [
('limit', 'swift-1'),
('static_inventory', None),
('playbook', 'all'),
('skip_tags', 'pre-upgrade,validation')
]
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
with mock.patch('os.path.exists') as mock_exists:
mock_exists.return_value = True
self.cmd.take_action(parsed_args)
for book in constants.MAJOR_UPGRADE_PLAYBOOKS:
upgrade_ansible.assert_any_call(
self.app.client_manager,
container='overcloud',
nodes='swift-1',
inventory_file=mock_open().__enter__().read(),
playbook=book,
node_user='tripleo-admin',
tags='',
skip_tags='pre-upgrade,validation',
verbosity=0,
extra_vars=None
)
@mock.patch('tripleoclient.workflows.package_update.update_ansible',
autospec=True) autospec=True)
@mock.patch('os.path.expanduser') @mock.patch('os.path.expanduser')
@mock.patch('oslo_concurrency.processutils.execute') @mock.patch('oslo_concurrency.processutils.execute')
@ -391,7 +274,7 @@ class TestOvercloudUpgradeRun(fakes.TestOvercloudUpgradeRun):
self.assertRaises(ParserException, lambda: self.check_parser( self.assertRaises(ParserException, lambda: self.check_parser(
self.cmd, argslist, verifylist)) self.cmd, argslist, verifylist))
@mock.patch('tripleoclient.workflows.package_update.update_ansible', @mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True) autospec=True)
@mock.patch('os.path.expanduser') @mock.patch('os.path.expanduser')
@mock.patch('oslo_concurrency.processutils.execute') @mock.patch('oslo_concurrency.processutils.execute')
@ -414,7 +297,7 @@ class TestOvercloudUpgradeRun(fakes.TestOvercloudUpgradeRun):
self.assertRaises(exceptions.InvalidConfiguration, self.assertRaises(exceptions.InvalidConfiguration,
lambda: self.cmd.take_action(parsed_args)) lambda: self.cmd.take_action(parsed_args))
@mock.patch('tripleoclient.workflows.package_update.update_ansible', @mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True) autospec=True)
@mock.patch('os.path.expanduser') @mock.patch('os.path.expanduser')
@mock.patch('oslo_concurrency.processutils.execute') @mock.patch('oslo_concurrency.processutils.execute')
@ -437,7 +320,7 @@ class TestOvercloudUpgradeRun(fakes.TestOvercloudUpgradeRun):
self.assertRaises(exceptions.InvalidConfiguration, self.assertRaises(exceptions.InvalidConfiguration,
lambda: self.cmd.take_action(parsed_args)) lambda: self.cmd.take_action(parsed_args))
@mock.patch('tripleoclient.workflows.package_update.update_ansible', @mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True) autospec=True)
@mock.patch('os.path.expanduser') @mock.patch('os.path.expanduser')
@mock.patch('oslo_concurrency.processutils.execute') @mock.patch('oslo_concurrency.processutils.execute')

View File

@ -16,7 +16,8 @@ import mock
from osc_lib.tests import utils from osc_lib.tests import utils
from tripleoclient import exceptions from tripleoclient import plugin
from tripleoclient.tests.fakes import FakeInstanceData
from tripleoclient.tests.fakes import FakeStackObject from tripleoclient.tests.fakes import FakeStackObject
from tripleoclient.workflows import deployment from tripleoclient.workflows import deployment
@ -32,8 +33,28 @@ class TestDeploymentWorkflows(utils.TestCommand):
self.websocket.__enter__ = lambda s: self.websocket self.websocket.__enter__ = lambda s: self.websocket
self.websocket.__exit__ = lambda s, *exc: None self.websocket.__exit__ = lambda s, *exc: None
self.tripleoclient.messaging_websocket.return_value = self.websocket self.tripleoclient.messaging_websocket.return_value = self.websocket
self.app.client_manager.tripleoclient = self.tripleoclient tc = self.app.client_manager.tripleoclient = self.tripleoclient
tc.create_mistral_context = plugin.ClientWrapper(
instance=FakeInstanceData
).create_mistral_context
self.gcn = mock.patch(
'tripleo_common.actions.config.DownloadConfigAction',
autospec=True
)
self.gcn.start()
self.addCleanup(self.gcn.stop)
self.ansible = mock.patch(
'tripleo_common.actions.ansible.AnsibleGenerateInventoryAction',
autospec=True
)
self.ansible.start()
self.addCleanup(self.ansible.stop)
config_mock = mock.patch(
'tripleo_common.actions.config.GetOvercloudConfig',
autospec=True
)
config_mock.start()
self.addCleanup(config_mock.stop)
self.message_success = iter([{ self.message_success = iter([{
"execution": {"id": "IDID"}, "execution": {"id": "IDID"},
"status": "SUCCESS", "status": "SUCCESS",
@ -100,6 +121,7 @@ class TestDeploymentWorkflows(utils.TestCommand):
self, mock_role_net_ip_map, self, mock_role_net_ip_map,
mock_blacklisted_ip_addresses): mock_blacklisted_ip_addresses):
stack = mock.Mock() stack = mock.Mock()
stack.output_show.return_value = []
mock_role_net_ip_map.return_value = { mock_role_net_ip_map.return_value = {
'Controller': { 'Controller': {
'ctlplane': ['1.1.1.1', '2.2.2.2', '3.3.3.3'], 'ctlplane': ['1.1.1.1', '2.2.2.2', '3.3.3.3'],
@ -126,29 +148,15 @@ class TestDeploymentWorkflows(utils.TestCommand):
expected = ['4.4.4.4', '6.6.6.6', '11.11.11.11'] expected = ['4.4.4.4', '6.6.6.6', '11.11.11.11']
self.assertEqual(sorted(expected), sorted(ips)) self.assertEqual(sorted(expected), sorted(ips))
def test_config_download_already_in_progress( @mock.patch('tripleoclient.utils.run_ansible_playbook',
self): autospec=True)
log = mock.Mock()
stack = mock.Mock()
stack.stack_name = 'stacktest'
clients = mock.Mock()
mock_execution = mock.Mock()
mock_execution.input = '{"plan_name": "stacktest"}'
mock_return = mock.Mock(return_value=[mock_execution])
clients.workflow_engine.executions.find = mock_return
self.assertRaises(exceptions.ConfigDownloadInProgress,
deployment.config_download,
log, clients, stack, 'templates', 'ssh_user',
'ssh_key', 'ssh_networks', 'output_dir', False,
'timeout')
@mock.patch('tripleoclient.workflows.deployment.base') @mock.patch('tripleoclient.workflows.deployment.base')
def test_config_download_already_in_progress_for_diff_stack( def test_config_download_already_in_progress_for_diff_stack(
self, mock_base): self, mock_base, mock_playbook):
log = mock.Mock() log = mock.Mock()
stack = mock.Mock() stack = mock.Mock()
stack.stack_name = 'stacktest' stack.stack_name = 'stacktest'
stack.output_show.return_value = {'output': {'output_value': []}}
clients = mock.Mock() clients = mock.Mock()
mock_execution = mock.Mock() mock_execution = mock.Mock()
mock_execution.input = '{"plan_name": "someotherstack"}' mock_execution.input = '{"plan_name": "someotherstack"}'

View File

@ -60,9 +60,12 @@ from heatclient import exc as hc_exc
from six.moves.urllib import error as url_error from six.moves.urllib import error as url_error
from six.moves.urllib import request from six.moves.urllib import request
from tripleo_common.actions import config
from tripleoclient import constants from tripleoclient import constants
from tripleoclient import exceptions from tripleoclient import exceptions
LOG = logging.getLogger(__name__ + ".utils") LOG = logging.getLogger(__name__ + ".utils")
@ -209,7 +212,7 @@ def run_ansible_playbook(playbook, inventory, workdir, playbook_dir=None,
plan='overcloud', gathering_policy='smart', plan='overcloud', gathering_policy='smart',
extra_env_variables=None, parallel_run=False, extra_env_variables=None, parallel_run=False,
callback_whitelist=None, ansible_cfg=None, callback_whitelist=None, ansible_cfg=None,
ansible_timeout=30): ansible_timeout=30, reproduce_command=False):
"""Simple wrapper for ansible-playbook. """Simple wrapper for ansible-playbook.
:param playbook: Playbook filename. :param playbook: Playbook filename.
@ -286,6 +289,13 @@ def run_ansible_playbook(playbook, inventory, workdir, playbook_dir=None,
:param ansible_timeout: Timeout for ansible connections. :param ansible_timeout: Timeout for ansible connections.
:type ansible_timeout: int :type ansible_timeout: int
:param reproduce_command: Enable or disable option to reproduce ansible
commands upon failure. This option will produce
a bash script that can reproduce a failing
playbook command which is helpful for debugging
and retry purposes.
:type reproduce_command: Boolean
""" """
def _playbook_check(play): def _playbook_check(play):
@ -331,23 +341,7 @@ def run_ansible_playbook(playbook, inventory, workdir, playbook_dir=None,
'fact_cache' 'fact_cache'
) )
makedirs(ansible_fact_path) makedirs(ansible_fact_path)
extravars = { extravars = dict()
'ansible_ssh_extra_args': (
'-o UserKnownHostsFile={} '
'-o StrictHostKeyChecking=no '
'-o ControlMaster=auto '
'-o ControlPersist=30m '
'-o ServerAliveInterval=64 '
'-o ServerAliveCountMax=1024 '
'-o Compression=no '
'-o TCPKeepAlive=yes '
'-o VerifyHostKeyDNS=no '
'-o ForwardX11=no '
'-o ForwardAgent=yes '
'-o PreferredAuthentications=publickey '
'-T'
).format(os.devnull)
}
if extra_vars: if extra_vars:
if isinstance(extra_vars, dict): if isinstance(extra_vars, dict):
extravars.update(extra_vars) extravars.update(extra_vars)
@ -363,6 +357,21 @@ def run_ansible_playbook(playbook, inventory, workdir, playbook_dir=None,
callback_whitelist = ','.join([callback_whitelist, 'profile_tasks']) callback_whitelist = ','.join([callback_whitelist, 'profile_tasks'])
env = os.environ.copy() env = os.environ.copy()
env['ANSIBLE_SSH_ARGS'] = (
'-o UserKnownHostsFile={} '
'-o StrictHostKeyChecking=no '
'-o ControlMaster=auto '
'-o ControlPersist=30m '
'-o ServerAliveInterval=64 '
'-o ServerAliveCountMax=1024 '
'-o Compression=no '
'-o TCPKeepAlive=yes '
'-o VerifyHostKeyDNS=no '
'-o ForwardX11=no '
'-o ForwardAgent=yes '
'-o PreferredAuthentications=publickey '
'-T'
).format(os.devnull)
env['ANSIBLE_DISPLAY_FAILED_STDERR'] = True env['ANSIBLE_DISPLAY_FAILED_STDERR'] = True
env['ANSIBLE_FORKS'] = 36 env['ANSIBLE_FORKS'] = 36
env['ANSIBLE_TIMEOUT'] = ansible_timeout env['ANSIBLE_TIMEOUT'] = ansible_timeout
@ -483,6 +492,8 @@ def run_ansible_playbook(playbook, inventory, workdir, playbook_dir=None,
else: else:
env.update(extra_env_variables) env.update(extra_env_variables)
command_path = None
with TempDirs(chdir=False) as ansible_artifact_path: with TempDirs(chdir=False) as ansible_artifact_path:
if 'ANSIBLE_CONFIG' not in env and not ansible_cfg: if 'ANSIBLE_CONFIG' not in env and not ansible_cfg:
ansible_cfg = os.path.join(ansible_artifact_path, 'ansible.cfg') ansible_cfg = os.path.join(ansible_artifact_path, 'ansible.cfg')
@ -533,6 +544,21 @@ def run_ansible_playbook(playbook, inventory, workdir, playbook_dir=None,
runner_config.env['ANSIBLE_STDOUT_CALLBACK'] = \ runner_config.env['ANSIBLE_STDOUT_CALLBACK'] = \
r_opts['envvars']['ANSIBLE_STDOUT_CALLBACK'] r_opts['envvars']['ANSIBLE_STDOUT_CALLBACK']
runner = ansible_runner.Runner(config=runner_config) runner = ansible_runner.Runner(config=runner_config)
if reproduce_command:
command_path = os.path.join(
playbook_dir,
"ansible-playbook-command.sh"
)
with open(command_path, 'w') as f:
f.write('#!/usr/bin/env bash\n')
f.write('echo -e "Exporting environment variables"\n')
for key, value in r_opts['envvars'].items():
f.write('export {}="{}"\n'.format(key, value))
f.write('echo -e "Running Ansible command"\n')
f.write('{} $@\n'.format(' '.join(runner_config.command)))
os.chmod(command_path, 0o750)
status, rc = runner.run() status, rc = runner.run()
if rc != 0: if rc != 0:
@ -545,6 +571,14 @@ def run_ansible_playbook(playbook, inventory, workdir, playbook_dir=None,
rc rc
) )
) )
if command_path:
err_msg += (
', To rerun the failed command manually execute the'
' following script: {}'.format(
command_path
)
)
if not quiet: if not quiet:
LOG.error(err_msg) LOG.error(err_msg)
raise ansible_runner.AnsibleRunnerException(err_msg) raise ansible_runner.AnsibleRunnerException(err_msg)
@ -1337,6 +1371,51 @@ def load_environment_directories(directories):
return environments return environments
def get_config(clients, container):
"""Get cloud config.
:param clients: Application client object.
:type clients: Object
:param container: Container name to pull from.
:type container: String.
"""
context = clients.tripleoclient.create_mistral_context()
config_action = config.GetOvercloudConfig(container=container)
config_action.run(context=context)
def get_key(stack):
"""Returns the private key from the local file system.
Searches for and returns the stack private key. If the key is inaccessible
for any reason, the process will fall back to using the users key. If no
key is found, this method will return None.
:params stack: name of the stack to use
:type stack: String
:returns: String || None
"""
stack_dir = os.path.join(constants.DEFAULT_WORK_DIR, stack)
stack_key_file = os.path.join(stack_dir, 'ssh_private_key')
user_dir = os.path.join(os.path.expanduser("~"), '.ssh')
user_key_file = os.path.join(user_dir, 'id_rsa_tripleo')
legacy_dir = os.path.join(constants.DEFAULT_WORK_DIR, '.ssh')
legacy_key_file = os.path.join(legacy_dir, 'tripleo-admin-rsa')
for key_file in [stack_key_file, user_key_file, legacy_key_file]:
try:
if os.path.exists(key_file):
with open(key_file):
return key_file
except IOError:
pass
else:
return
def get_tripleo_ansible_inventory(inventory_file=None, def get_tripleo_ansible_inventory(inventory_file=None,
ssh_user='tripleo-admin', ssh_user='tripleo-admin',
stack='overcloud', stack='overcloud',
@ -1352,7 +1431,7 @@ def get_tripleo_ansible_inventory(inventory_file=None,
'--ansible_ssh_user', ssh_user, '--ansible_ssh_user', ssh_user,
'--undercloud-connection', undercloud_connection, '--undercloud-connection', undercloud_connection,
'--undercloud-key-file', '--undercloud-key-file',
'/var/lib/mistral/.ssh/tripleo-admin-rsa', get_key(stack=stack),
'--static-yaml-inventory', inventory_file) '--static-yaml-inventory', inventory_file)
except processutils.ProcessExecutionError as e: except processutils.ProcessExecutionError as e:
message = _("Failed to generate inventory: %s") % str(e) message = _("Failed to generate inventory: %s") % str(e)
@ -1483,7 +1562,8 @@ def run_update_ansible_action(log, clients, stack, nodes, inventory,
module_path='/usr/share/ansible-modules', module_path='/usr/share/ansible-modules',
limit_hosts=nodes, limit_hosts=nodes,
tags=tags, tags=tags,
skip_tags=skip_tags) skip_tags=skip_tags,
extra_vars=extra_vars)
def parse_extra_vars(extra_var_strings): def parse_extra_vars(extra_var_strings):

View File

@ -675,7 +675,7 @@ class DeployOvercloud(command.Command):
parser.add_argument( parser.add_argument(
'--overcloud-ssh-key', '--overcloud-ssh-key',
default=os.path.join( default=os.path.join(
os.path.expanduser('~'), '.ssh', 'id_rsa'), os.path.expanduser('~'), '.ssh', 'id_rsa_tripleo'),
help=_('Key path for ssh access to overcloud nodes.') help=_('Key path for ssh access to overcloud nodes.')
) )
parser.add_argument( parser.add_argument(
@ -972,16 +972,17 @@ class DeployOvercloud(command.Command):
parsed_args.deployment_python_interpreter parsed_args.deployment_python_interpreter
deployment.config_download( deployment.config_download(
self.log, self.clients, stack, self.log,
parsed_args.templates, parsed_args.overcloud_ssh_user, self.clients,
parsed_args.overcloud_ssh_key, stack,
parsed_args.overcloud_ssh_network, parsed_args.overcloud_ssh_network,
parsed_args.output_dir, parsed_args.output_dir,
parsed_args.override_ansible_cfg, parsed_args.override_ansible_cfg,
timeout, timeout,
verbosity=(self.app_args.verbose_level - 1), verbosity=(self.app_args.verbose_level - 1),
deployment_options=deployment_options, deployment_options=deployment_options,
in_flight_validations=parsed_args.inflight) in_flight_validations=parsed_args.inflight
)
except Exception: except Exception:
deployment.set_deployment_status( deployment.set_deployment_status(
clients=self.clients, clients=self.clients,

View File

@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
# #
from oslo_config import cfg from oslo_config import cfg
from oslo_log import log as logging from oslo_log import log as logging
@ -86,10 +87,8 @@ class ExternalUpdateRun(command.Command):
default=[]) default=[])
parser.add_argument('--no-workflow', dest='no_workflow', parser.add_argument('--no-workflow', dest='no_workflow',
action='store_true', action='store_true',
default=False, default=True,
help=_('Run ansible-playbook directly via ' help=_('This option no longer has any effect.')
'system command instead of running Ansible'
'via the TripleO mistral workflows.')
) )
return parser return parser
@ -101,19 +100,20 @@ class ExternalUpdateRun(command.Command):
verbosity = self.app_args.verbose_level - 1 verbosity = self.app_args.verbose_level - 1
stack = parsed_args.stack stack = parsed_args.stack
ansible_dir = None key, ansible_dir = self.get_ansible_key_and_dir(
key = package_update.get_key(stack=stack) no_workflow=parsed_args.no_workflow,
# Disable mistral stack=stack,
if parsed_args.no_workflow: orchestration=orchestration
ansible_dir = oooutils.download_ansible_playbooks(orchestration, )
stack)
# Run ansible: # Run ansible:
inventory = oooutils.get_tripleo_ansible_inventory( inventory = oooutils.get_tripleo_ansible_inventory(
parsed_args.static_inventory, parsed_args.ssh_user, stack) parsed_args.static_inventory, parsed_args.ssh_user, stack,
return_inventory_file_path=True)
limit_hosts = 'all' limit_hosts = 'all'
playbook = 'all' playbook = 'all'
extra_vars = oooutils.parse_extra_vars(parsed_args.extra_vars) extra_vars = oooutils.parse_extra_vars(parsed_args.extra_vars)
extra_vars['ansible_become'] = True
oooutils.run_update_ansible_action( oooutils.run_update_ansible_action(
self.log, clients, stack, limit_hosts, inventory, playbook, self.log, clients, stack, limit_hosts, inventory, playbook,

View File

@ -86,10 +86,8 @@ class ExternalUpgradeRun(command.Command):
default=[]) default=[])
parser.add_argument('--no-workflow', dest='no_workflow', parser.add_argument('--no-workflow', dest='no_workflow',
action='store_true', action='store_true',
default=False, default=True,
help=_('Run ansible-playbook directly via ' help=_('This option no longer has any effect.')
'system command instead of running Ansible'
'via the TripleO mistral workflows.')
) )
return parser return parser
@ -101,20 +99,20 @@ class ExternalUpgradeRun(command.Command):
verbosity = self.app_args.verbose_level - 1 verbosity = self.app_args.verbose_level - 1
stack = parsed_args.stack stack = parsed_args.stack
ansible_dir = None key, ansible_dir = self.get_ansible_key_and_dir(
key = package_update.get_key(stack=stack) no_workflow=parsed_args.no_workflow,
# Disable mistral stack=stack,
if parsed_args.no_workflow: orchestration=orchestration
ansible_dir = oooutils.download_ansible_playbooks(orchestration, )
stack)
# Run ansible: # Run ansible:
inventory = oooutils.get_tripleo_ansible_inventory( inventory = oooutils.get_tripleo_ansible_inventory(
parsed_args.static_inventory, parsed_args.ssh_user, stack) parsed_args.static_inventory, parsed_args.ssh_user, stack,
return_inventory_file_path=True)
limit_hosts = 'all' limit_hosts = 'all'
playbook = 'all' playbook = 'all'
extra_vars = oooutils.parse_extra_vars(parsed_args.extra_vars) extra_vars = oooutils.parse_extra_vars(parsed_args.extra_vars)
extra_vars['ansible_become'] = True
oooutils.run_update_ansible_action( oooutils.run_update_ansible_action(
self.log, clients, stack, limit_hosts, inventory, playbook, self.log, clients, stack, limit_hosts, inventory, playbook,
constants.EXTERNAL_UPGRADE_PLAYBOOKS, parsed_args.ssh_user, constants.EXTERNAL_UPGRADE_PLAYBOOKS, parsed_args.ssh_user,

View File

@ -83,7 +83,7 @@ class FFWDUpgradePrepare(DeployOvercloud):
super(FFWDUpgradePrepare, self).take_action(parsed_args) super(FFWDUpgradePrepare, self).take_action(parsed_args)
package_update.update(clients, container=stack_name) package_update.update(clients, container=stack_name)
package_update.get_config(clients, container=stack_name) oooutils.get_config(clients, container=stack_name)
overcloudrcs = deployment.create_overcloudrc( overcloudrcs = deployment.create_overcloudrc(
clients, container=stack_name) clients, container=stack_name)
@ -145,10 +145,8 @@ class FFWDUpgradeRun(command.Command):
) )
parser.add_argument('--no-workflow', dest='no_workflow', parser.add_argument('--no-workflow', dest='no_workflow',
action='store_true', action='store_true',
default=False, default=True,
help=_('Run ansible-playbook directly via ' help=_('This option no longer has any effect.')
'system command instead of running Ansible'
'via the TripleO mistral workflows.')
) )
return parser return parser
@ -160,24 +158,26 @@ class FFWDUpgradeRun(command.Command):
orchestration = clients.orchestration orchestration = clients.orchestration
stack = parsed_args.stack stack = parsed_args.stack
ansible_dir = None key, ansible_dir = self.get_ansible_key_and_dir(
key = package_update.get_key(stack=stack) no_workflow=parsed_args.no_workflow,
# Disable mistral stack=stack,
if parsed_args.no_workflow: orchestration=orchestration
ansible_dir = oooutils.download_ansible_playbooks(orchestration, )
stack)
# Run ansible: # Run ansible:
inventory = oooutils.get_tripleo_ansible_inventory( inventory = oooutils.get_tripleo_ansible_inventory(
inventory_file=parsed_args.static_inventory, inventory_file=parsed_args.static_inventory,
ssh_user=parsed_args.ssh_user, stack=parsed_args.stack) ssh_user=parsed_args.ssh_user, stack=parsed_args.stack,
return_inventory_file_path=True)
# Don't expost limit_hosts. We need this on the whole overcloud. # Don't expost limit_hosts. We need this on the whole overcloud.
limit_hosts = '' limit_hosts = ''
extra_vars = {'ansible_become': True}
oooutils.run_update_ansible_action( oooutils.run_update_ansible_action(
self.log, clients, parsed_args.stack, limit_hosts, inventory, self.log, clients, parsed_args.stack, limit_hosts, inventory,
constants.FFWD_UPGRADE_PLAYBOOK, [], parsed_args.ssh_user, constants.FFWD_UPGRADE_PLAYBOOK, [], parsed_args.ssh_user,
(None if parsed_args.no_workflow else package_update), (None if parsed_args.no_workflow else package_update),
verbosity=verbosity, workdir=ansible_dir, priv_key=key) verbosity=verbosity, workdir=ansible_dir, priv_key=key,
extra_vars=extra_vars)
class FFWDUpgradeConverge(DeployOvercloud): class FFWDUpgradeConverge(DeployOvercloud):

View File

@ -198,10 +198,11 @@ class DeleteNode(command.Command):
.format(stack=stack.stack_name, nodes=nodes_text)) .format(stack=stack.stack_name, nodes=nodes_text))
scale.scale_down( scale.scale_down(
clients, log=self.log,
stack.stack_name, clients=clients,
nodes, stack=stack,
parsed_args.timeout nodes=nodes,
timeout=parsed_args.timeout
) )
if parsed_args.baremetal_deployment: if parsed_args.baremetal_deployment:

View File

@ -72,7 +72,7 @@ class UpdatePrepare(DeployOvercloud):
super(UpdatePrepare, self).take_action(parsed_args) super(UpdatePrepare, self).take_action(parsed_args)
package_update.update(clients, container=stack_name) package_update.update(clients, container=stack_name)
package_update.get_config(clients, container=stack_name) oooutils.get_config(clients, container=stack_name)
self.log.info("Update init on stack {0} complete.".format( self.log.info("Update init on stack {0} complete.".format(
parsed_args.stack)) parsed_args.stack))
@ -131,10 +131,8 @@ class UpdateRun(command.Command):
) )
parser.add_argument('--no-workflow', dest='no_workflow', parser.add_argument('--no-workflow', dest='no_workflow',
action='store_true', action='store_true',
default=False, default=True,
help=_('Run ansible-playbook directly via ' help=_('This option no longer has any effect.')
'system command instead of running Ansible'
'via the TripleO mistral workflows.')
) )
return parser return parser
@ -146,19 +144,20 @@ class UpdateRun(command.Command):
verbosity = self.app_args.verbose_level - 1 verbosity = self.app_args.verbose_level - 1
stack = parsed_args.stack stack = parsed_args.stack
ansible_dir = None key, ansible_dir = self.get_ansible_key_and_dir(
key = package_update.get_key(stack=stack) no_workflow=parsed_args.no_workflow,
# Disable mistral stack=stack,
if parsed_args.no_workflow: orchestration=orchestration
ansible_dir = oooutils.download_ansible_playbooks(orchestration, )
stack)
# Run ansible: # Run ansible:
limit_hosts = parsed_args.limit limit_hosts = parsed_args.limit
playbook = parsed_args.playbook playbook = parsed_args.playbook
inventory = oooutils.get_tripleo_ansible_inventory( inventory = oooutils.get_tripleo_ansible_inventory(
parsed_args.static_inventory, parsed_args.ssh_user, stack) parsed_args.static_inventory, parsed_args.ssh_user, stack,
return_inventory_file_path=True)
extra_vars = {'ansible_become': True}
oooutils.run_update_ansible_action(self.log, clients, stack, oooutils.run_update_ansible_action(self.log, clients, stack,
limit_hosts, inventory, playbook, limit_hosts, inventory, playbook,
constants.MINOR_UPDATE_PLAYBOOKS, constants.MINOR_UPDATE_PLAYBOOKS,
@ -167,7 +166,8 @@ class UpdateRun(command.Command):
else package_update), else package_update),
verbosity=verbosity, verbosity=verbosity,
workdir=ansible_dir, workdir=ansible_dir,
priv_key=key) priv_key=key,
extra_vars=extra_vars)
class UpdateConverge(DeployOvercloud): class UpdateConverge(DeployOvercloud):

View File

@ -73,7 +73,7 @@ class UpgradePrepare(DeployOvercloud):
constants.UPGRADE_PREPARE_ENV) constants.UPGRADE_PREPARE_ENV)
super(UpgradePrepare, self).take_action(parsed_args) super(UpgradePrepare, self).take_action(parsed_args)
package_update.update(clients, container=stack_name) package_update.update(clients, container=stack_name)
package_update.get_config(clients, container=stack_name) oooutils.get_config(clients, container=stack_name)
overcloudrcs = deployment.create_overcloudrc( overcloudrcs = deployment.create_overcloudrc(
clients, container=stack_name) clients, container=stack_name)
@ -179,10 +179,8 @@ class UpgradeRun(command.Command):
default='overcloud')) default='overcloud'))
parser.add_argument('--no-workflow', dest='no_workflow', parser.add_argument('--no-workflow', dest='no_workflow',
action='store_true', action='store_true',
default=False, default=True,
help=_('Run ansible-playbook directly via ' help=_('This option no longer has any effect.')
'system command instead of running Ansible'
'via the TripleO mistral workflows.')
) )
return parser return parser
@ -204,20 +202,21 @@ class UpgradeRun(command.Command):
orchestration = clients.orchestration orchestration = clients.orchestration
stack = parsed_args.stack stack = parsed_args.stack
ansible_dir = None key, ansible_dir = self.get_ansible_key_and_dir(
key = package_update.get_key(stack=stack) no_workflow=parsed_args.no_workflow,
# Disable mistral stack=stack,
if parsed_args.no_workflow: orchestration=orchestration
ansible_dir = oooutils.download_ansible_playbooks(orchestration, )
stack)
# Run ansible: # Run ansible:
limit_hosts = parsed_args.limit limit_hosts = parsed_args.limit
playbook = parsed_args.playbook playbook = parsed_args.playbook
inventory = oooutils.get_tripleo_ansible_inventory( inventory = oooutils.get_tripleo_ansible_inventory(
parsed_args.static_inventory, parsed_args.ssh_user, stack) parsed_args.static_inventory, parsed_args.ssh_user, stack,
return_inventory_file_path=True)
skip_tags = self._validate_skip_tags(parsed_args.skip_tags) skip_tags = self._validate_skip_tags(parsed_args.skip_tags)
extra_vars = {'ansible_become': True}
oooutils.run_update_ansible_action(self.log, clients, stack, oooutils.run_update_ansible_action(self.log, clients, stack,
limit_hosts, inventory, playbook, limit_hosts, inventory, playbook,
constants.MAJOR_UPGRADE_PLAYBOOKS, constants.MAJOR_UPGRADE_PLAYBOOKS,
@ -228,7 +227,8 @@ class UpgradeRun(command.Command):
skip_tags, skip_tags,
verbosity, verbosity,
workdir=ansible_dir, workdir=ansible_dir,
priv_key=key) priv_key=key,
extra_vars=extra_vars)
playbooks = (constants.MAJOR_UPGRADE_PLAYBOOKS playbooks = (constants.MAJOR_UPGRADE_PLAYBOOKS
if playbook == 'all' else playbook) if playbook == 'all' else playbook)

View File

@ -12,18 +12,20 @@
from __future__ import print_function from __future__ import print_function
import copy import copy
import getpass
import os import os
import pprint import pprint
import time import time
import yaml
from heatclient.common import event_utils from heatclient.common import event_utils
from openstackclient import shell from openstackclient import shell
from tripleo_common.actions import ansible
from tripleo_common.actions import config from tripleo_common.actions import config
from tripleo_common.actions import deployment from tripleo_common.actions import deployment
from tripleo_common.actions import swifthelper from tripleo_common.actions import swifthelper
from tripleoclient.constants import ANSIBLE_TRIPLEO_PLAYBOOKS from tripleoclient.constants import ANSIBLE_TRIPLEO_PLAYBOOKS
from tripleoclient.constants import DEFAULT_WORK_DIR
from tripleoclient import exceptions from tripleoclient import exceptions
from tripleoclient import utils from tripleoclient import utils
@ -251,70 +253,209 @@ def enable_ssh_admin(stack, hosts, ssh_user, ssh_key, timeout):
print("Enabling ssh admin - COMPLETE.") print("Enabling ssh admin - COMPLETE.")
def config_download(log, clients, stack, templates, def config_download(log, clients, stack, ssh_network=None,
ssh_user, ssh_key, ssh_network, output_dir=None, override_ansible_cfg=None,
output_dir, override_ansible_cfg, timeout, verbosity=0, timeout=None, verbosity=0, deployment_options=None,
deployment_options={}, in_flight_validations=False,
in_flight_validations=False): ansible_playbook_name='deploy_steps_playbook.yaml',
workflow_client = clients.workflow_engine limit_list=None):
tripleoclients = clients.tripleoclient """Run config download.
if in_flight_validations: :param log: Logging object
skip_tags = '' :type log: Object
else:
:param clients: openstack clients
:type clients: Object
:param stack: Heat Stack object
:type stack: Object
:param ssh_network: Network named used to access the overcloud.
:type ssh_network: String
:param override_ansible_cfg: Ansible configuration file location.
:type override_ansible_cfg: String
:param timeout: Ansible connection timeout. If None, the effective
default will be set to 30 at playbook runtime.
:type timeout: Integer
:param verbosity: Ansible verbosity level.
:type verbosity: Integer
:param deployment_options: Additional deployment options.
:type deployment_options: Dictionary
:param in_flight_validations: Enable or Disable inflight validations.
:type in_flight_validations: Boolean
:param ansible_playbook_name: Name of the playbook to execute.
:type ansible_playbook_name: String
:param limit_list: List of hosts to limit the current playbook to.
:type limit_list: List
"""
def _log_and_print(message, logger, level='info', print_msg=True):
"""Print and log a given message.
:param message: Message to print and log.
:type message: String
:param log: Logging object
:type log: Object
:param level: Log level.
:type level: String
:param print_msg: Print messages to stdout.
:type print_msg: Boolean
"""
if print_msg:
print(message)
log = getattr(logger, level)
log(message)
if not output_dir:
output_dir = DEFAULT_WORK_DIR
if not deployment_options:
deployment_options = dict()
if not in_flight_validations:
skip_tags = 'opendev-validation' skip_tags = 'opendev-validation'
else:
skip_tags = None
workflow_input = { if not timeout:
'verbosity': verbosity, timeout = 30
'plan_name': stack.stack_name,
'ssh_network': ssh_network,
'config_download_timeout': timeout,
'deployment_options': deployment_options,
'skip_tags': skip_tags
}
if output_dir:
workflow_input.update(dict(work_dir=output_dir))
if override_ansible_cfg:
with open(override_ansible_cfg) as cfg:
override_ansible_cfg_contents = cfg.read()
workflow_input.update(
dict(override_ansible_cfg=override_ansible_cfg_contents))
workflow_name = 'tripleo.deployment.v1.config_download_deploy' # NOTE(cloudnull): List of hosts to limit the current playbook execution
# The list is later converted into an ansible compatible
# string. Storing hosts in list format will ensure all
# entries are consistent.
if not limit_list:
limit_list = list()
# Check to see if any existing executions for the same stack are already in with utils.TempDirs() as tmp:
# progress. utils.run_ansible_playbook(
log.info("Checking for existing executions of config_download for " playbook='cli-grant-local-access.yaml',
"%s" % stack.stack_name) inventory='localhost,',
for execution in workflow_client.executions.find( workdir=tmp,
workflow_name=workflow_name, playbook_dir=ANSIBLE_TRIPLEO_PLAYBOOKS,
state='RUNNING'): extra_vars={
'access_path': output_dir,
try: 'execution_user': getpass.getuser()
exec_input = yaml.safe_load(execution.input) }
except yaml.YAMLError as ye:
log.error("YAML error loading input for execution %s: %s" %
(execution.id, str(ye)))
raise
if exec_input.get('plan_name', 'overcloud') == stack.stack_name:
raise exceptions.ConfigDownloadInProgress(execution.id,
stack.stack_name)
with tripleoclients.messaging_websocket() as ws:
execution = base.start_workflow(
workflow_client,
workflow_name,
workflow_input=workflow_input
) )
for payload in base.wait_for_messages(workflow_client, ws, execution): stack_work_dir = os.path.join(output_dir, stack.stack_name)
print(payload['message']) context = clients.tripleoclient.create_mistral_context()
_log_and_print(
message='Checking for blacklisted hosts from stack: {}'.format(
stack.stack_name
),
logger=log,
print_msg=(verbosity == 0)
)
blacklist_show = stack.output_show('BlacklistedHostnames')
blacklist_stack_output = blacklist_show.get('output', dict())
blacklist_stack_output_value = blacklist_stack_output.get('output_value')
if blacklist_stack_output_value:
limit_list.extend(
['!{}'.format(i) for i in blacklist_stack_output_value if i]
)
_log_and_print(
message='Retrieving configuration for stack: {}'.format(
stack.stack_name
),
logger=log,
print_msg=(verbosity == 0)
)
utils.get_config(clients, container=stack.stack_name)
_log_and_print(
message='Downloading configuration for stack: {}'.format(
stack.stack_name
),
logger=log,
print_msg=(verbosity == 0)
)
download = config.DownloadConfigAction(
work_dir=stack_work_dir,
container_config='{}-config'.format(stack.stack_name)
)
work_dir = download.run(context=context)
_log_and_print(
message='Retrieving keyfile for stack: {}'.format(
stack.stack_name
),
logger=log,
print_msg=(verbosity == 0)
)
key_file = utils.get_key(stack=stack.stack_name)
_log_and_print(
message='Generating information for stack: {}'.format(
stack.stack_name
),
logger=log,
print_msg=(verbosity == 0)
)
inventory_kwargs = {
'ansible_ssh_user': 'tripleo-admin',
'work_dir': work_dir,
'plan_name': stack.stack_name,
'undercloud_key_file': key_file
}
if ssh_network:
inventory_kwargs['ssh_network'] = ssh_network
python_interpreter = deployment_options.get('ansible_python_interpreter')
if python_interpreter:
inventory_kwargs['ansible_python_interpreter'] = python_interpreter
inventory = ansible.AnsibleGenerateInventoryAction(**inventory_kwargs)
inventory_path = inventory.run(context=context)
_log_and_print(
message='Executing deployment playbook for stack: {}'.format(
stack.stack_name
),
logger=log,
print_msg=(verbosity == 0)
)
if payload['status'] == 'SUCCESS': # NOTE(cloudnull): Join the limit_list into an ansible compatible string.
print("Overcloud configuration completed.") # If it is an empty, the object will be reset to None.
else: limit_hosts = ':'.join(limit_list)
raise exceptions.DeploymentError("Overcloud configuration failed.")
with utils.TempDirs() as tmp:
utils.run_ansible_playbook(
playbook=os.path.join(
stack_work_dir,
ansible_playbook_name
),
inventory=inventory_path,
workdir=tmp,
playbook_dir=work_dir,
skip_tags=skip_tags,
ansible_cfg=override_ansible_cfg,
verbosity=verbosity,
ssh_user='tripleo-admin',
key=key_file,
limit_hosts=limit_hosts,
ansible_timeout=timeout,
reproduce_command=True,
extra_env_variables={
'ANSIBLE_BECOME': True,
}
)
_log_and_print(
message='Overcloud configuration completed for stack: {}'.format(
stack.stack_name
),
logger=log,
print_msg=(verbosity == 0)
)
def config_download_export(clients, plan, config_type): def config_download_export(clients, plan, config_type):

View File

@ -11,20 +11,17 @@
# under the License. # under the License.
from __future__ import print_function from __future__ import print_function
import os
import pprint import pprint
import time import time
from heatclient.common import event_utils from heatclient.common import event_utils
from openstackclient import shell from openstackclient import shell
from tripleo_common.actions import config
from tripleoclient import constants
from tripleoclient import exceptions from tripleoclient import exceptions
from tripleoclient import utils from tripleoclient import utils
from tripleoclient.workflows import base from tripleoclient.workflows import base
_WORKFLOW_TIMEOUT = 120 * 60 # 2h _WORKFLOW_TIMEOUT = 120 * 60 # 2h
@ -67,49 +64,6 @@ def update(clients, **workflow_input):
raise exceptions.DeploymentError("Heat Stack update failed.") raise exceptions.DeploymentError("Heat Stack update failed.")
def get_config(clients, container):
"""Get cloud config.
:param clients: Application client object.
:type clients: Object
:param container: Container name to pull from.
:type container: String.
"""
context = clients.tripleoclient.create_mistral_context()
config_action = config.GetOvercloudConfig(container=container)
config_action.run(context=context)
def get_key(stack):
"""Returns the private key from the local file system.
Searches for and returns the stack private key. If the key is inaccessible
for any reason, the process will fall back to using the users key. If no
key is found, this method will return None.
:params stack: name of the stack to use
:type stack: String
:returns: String || None
"""
stack_dir = os.path.join(constants.DEFAULT_WORK_DIR, stack)
stack_key_file = os.path.join(stack_dir, 'ssh_private_key')
user_dir = os.path.join(os.path.expanduser("~"), '.ssh')
user_key_file = os.path.join(user_dir, 'id_rsa_tripleo')
for key_file in [stack_key_file, user_key_file]:
try:
if os.path.exists(key_file):
with open(key_file):
return key_file
except IOError:
pass
else:
return
def update_ansible(clients, **workflow_input): def update_ansible(clients, **workflow_input):
workflow_client = clients.workflow_engine workflow_client = clients.workflow_engine
tripleoclients = clients.tripleoclient tripleoclients = clients.tripleoclient

View File

@ -16,65 +16,58 @@ from __future__ import print_function
from tripleo_common.actions import scale from tripleo_common.actions import scale
from tripleoclient import exceptions
from tripleoclient import utils from tripleoclient import utils
from tripleoclient.workflows import base from tripleoclient.workflows import deployment
def ansible_tear_down(clients, **workflow_input): def scale_down(log, clients, stack, nodes, timeout=None):
workflow_client = clients.workflow_engine
tripleoclients = clients.tripleoclient
workflow_input['playbook_name'] = 'scale_playbook.yaml'
with tripleoclients.messaging_websocket() as ws:
execution = base.start_workflow(
workflow_client,
'tripleo.deployment.v1.config_download_deploy',
workflow_input=workflow_input
)
for payload in base.wait_for_messages(workflow_client, ws, execution):
print(payload['message'])
if payload['status'] == 'SUCCESS':
print("Scale-down configuration completed.")
else:
raise exceptions.DeploymentError("Scale-down configuration failed.")
def scale_down(clients, plan_name, nodes, timeout=None):
"""Unprovision and deletes overcloud nodes from a heat stack. """Unprovision and deletes overcloud nodes from a heat stack.
:param log: Logging object
:type log: Object
:param clients: Application client object. :param clients: Application client object.
:type clients: Object :type clients: Object
:param stack: Heat Stack object
:type stack: Object
:param nodes: List of nodes to delete. If the node UUID is used the
UUID will be used to lookup the node name before being
passed through to the cleanup playbook.
:type nodes: List
:param timeout: Timeout to use when deleting nodes. If timeout is None :param timeout: Timeout to use when deleting nodes. If timeout is None
it will be set to 240. it will be set to 240.
:type timeout: Integer :type timeout: Integer
:param plan: Plan name.
:type plan: String
:param nodes: List of nodes to delete.
:type nodes: List
""" """
workflow_input = {
"plan_name": plan_name,
"nodes": nodes,
}
ansible_tear_down(clients, **workflow_input)
if not timeout: if not timeout:
timeout = 240 timeout = 240
limit_list = list()
for node in nodes:
try:
_node = clients.compute.servers.get(node)
limit_list.append(_node.name)
except Exception:
limit_list.append(node)
deployment.config_download(
log=log,
clients=clients,
stack=stack,
timeout=timeout,
ansible_playbook_name='scale_playbook.yaml',
limit_list=limit_list
)
print('Running scale down')
context = clients.tripleoclient.create_mistral_context() context = clients.tripleoclient.create_mistral_context()
scale_down_action = scale.ScaleDownAction(nodes=nodes, timeout=timeout) scale_down_action = scale.ScaleDownAction(nodes=nodes, timeout=timeout)
scale_down_action.run(context=context) scale_down_action.run(context=context)
utils.wait_for_stack_ready( utils.wait_for_stack_ready(
orchestration_client=clients.orchestration, orchestration_client=clients.orchestration,
stack_name=plan_name, stack_name=stack.stack_name,
action='UPDATE' action='UPDATE'
) )