Get the stack name if possible before running the validations group

If we run the group validations in the Undercloud and we
do not specify the stack name, this will fail if the
Overcloud stack is not called 'overcloud'.

In this case we try to fetch the stack name and we compare it
with the swift containers to match the deployment plan name
if there is a match, then we know the stack name.

Change-Id: Ib2e27b1b43f573385c089e57bd2290daac49d814
Closes-Bug: 1806684
Resolves: rhbz#1573120
This commit is contained in:
Carlos Camacho 2018-11-21 00:05:14 +01:00
parent 0b9002106a
commit 227ce3fc90
2 changed files with 149 additions and 13 deletions

View File

@ -999,7 +999,12 @@ class TestPostConfig(BaseTestCase):
@mock.patch('instack_undercloud.undercloud._get_auth_values')
@mock.patch('instack_undercloud.undercloud._get_session')
@mock.patch('mistralclient.api.client.client', autospec=True)
def test_run_validation_groups_success(self, mock_mistral_client,
@mock.patch('swiftclient.client.Connection', autospec=True)
@mock.patch('os_client_config.make_client')
def test_run_validation_groups_success(self,
mock_make_client,
mock_swift_client,
mock_mistral_client,
mock_get_session,
mock_auth_values):
mock_mistral = mock.Mock()
@ -1007,19 +1012,76 @@ class TestPostConfig(BaseTestCase):
mock_mistral.environments.list.return_value = []
mock_mistral.executions.get.return_value = mock.Mock(state="SUCCESS")
mock_get_session.return_value = mock.MagicMock()
mock_auth_values.return_value = ('aturing', '3nigma', 'hut8',
'http://bletchley:5000/')
mock_instance_swift = mock.Mock()
mock_instance_swift.get_account.return_value = [None,
[{'name': 'hut8'},
{'name': 'mystack'}]]
mock_swift_client.return_value = mock_instance_swift
mock_heat = mock.Mock()
aux_stack = {}
aux_stack['stack_name'] = "mystack"
mock_heat.stacks.list.return_value = [aux_stack]
mock_make_client.return_value = mock_heat
undercloud._run_validation_groups(["post-upgrade"])
mock_mistral.executions.create.assert_called_once_with(
'tripleo.validations.v1.run_groups',
workflow_input={
'group_names': ['post-upgrade'],
'plan': 'mystack',
}
)
@mock.patch('instack_undercloud.undercloud._get_auth_values')
@mock.patch('instack_undercloud.undercloud._get_session')
@mock.patch('mistralclient.api.client.client', autospec=True)
@mock.patch('swiftclient.client.Connection', autospec=True)
@mock.patch('os_client_config.make_client')
def test_run_validation_groups_no_overcloud(self,
mock_make_client,
mock_swift_client,
mock_mistral_client,
mock_get_session,
mock_auth_values):
mock_mistral = mock.Mock()
mock_mistral_client.return_value = mock_mistral
mock_mistral.environments.list.return_value = []
mock_mistral.executions.get.return_value = mock.Mock(state="SUCCESS")
mock_get_session.return_value = mock.MagicMock()
mock_auth_values.return_value = ('aturing', '3nigma', 'hut8',
'http://bletchley:5000/')
mock_instance_swift = mock.Mock()
mock_instance_swift.get_account.return_value = [None,
[{'name': 'hut8'},
{'name': 'mystack'}]]
mock_swift_client.return_value = mock_instance_swift
mock_heat = mock.Mock()
aux_stack = {}
aux_stack['stack_name'] = "mystackooo"
mock_heat.stacks.list.return_value = [aux_stack]
mock_make_client.return_value = mock_heat
undercloud._run_validation_groups(["post-upgrade"])
mock_mistral.executions.create.assert_not_called()
@mock.patch('instack_undercloud.undercloud._get_auth_values')
@mock.patch('instack_undercloud.undercloud._get_session')
@mock.patch('mistralclient.api.client.client', autospec=True)
@mock.patch('time.strptime')
def test_run_validation_groups_fail(self, mock_strptime,
@mock.patch('swiftclient.client.Connection', autospec=True)
@mock.patch('os_client_config.make_client')
def test_run_validation_groups_fail(self,
mock_make_client,
mock_swift_client,
mock_strptime,
mock_mistral_client, mock_get_session,
mock_auth_values):
mock_mistral = mock.Mock()
@ -1029,6 +1091,22 @@ class TestPostConfig(BaseTestCase):
mock_mistral.executions.get_output.return_value = "ERROR!"
mock_mistral.executions.get.id = "1234"
mock_mistral.action_executions.list.return_value = []
mock_auth_values.return_value = ('aturing', '3nigma', 'hut8',
'http://bletchley:5000/')
mock_instance_swift = mock.Mock()
mock_instance_swift.get_account.return_value = [None,
[{'name': 'hut8'},
{'name': 'mystack'}]]
mock_swift_client.return_value = mock_instance_swift
mock_heat = mock.Mock()
aux_stack = {}
aux_stack['stack_name'] = "mystack"
mock_heat.stacks.list.return_value = [aux_stack]
mock_make_client.return_value = mock_heat
mock_strptime.return_value = time.mktime(time.localtime())
mock_get_session.return_value = mock.MagicMock()
self.assertRaises(
@ -1039,7 +1117,12 @@ class TestPostConfig(BaseTestCase):
@mock.patch('instack_undercloud.undercloud._get_session')
@mock.patch('mistralclient.api.client.client', autospec=True)
@mock.patch('time.strptime')
def test_run_validation_groups_timeout(self, mock_strptime,
@mock.patch('swiftclient.client.Connection', autospec=True)
@mock.patch('os_client_config.make_client')
def test_run_validation_groups_timeout(self,
mock_make_client,
mock_swift_client,
mock_strptime,
mock_mistral_client,
mock_get_session, mock_auth_values):
mock_mistral = mock.Mock()
@ -1047,7 +1130,23 @@ class TestPostConfig(BaseTestCase):
mock_mistral.environments.list.return_value = []
mock_mistral.executions.get.id = "1234"
mock_mistral.action_executions.list.return_value = []
mock_get_session.return_value = mock.MagicMock()
mock_instance_swift = mock.Mock()
mock_auth_values.return_value = ('aturing', '3nigma', 'hut8',
'http://bletchley:5000/')
mock_instance_swift = mock.Mock()
mock_instance_swift.get_account.return_value = [None,
[{'name': 'hut8'},
{'name': 'mystack'}]]
mock_swift_client.return_value = mock_instance_swift
mock_heat = mock.Mock()
aux_stack = {}
aux_stack['stack_name'] = "mystack"
mock_heat.stacks.list.return_value = [aux_stack]
mock_make_client.return_value = mock_heat
mock_time = mock.MagicMock()
mock_time.return_value = time.mktime(time.localtime())
mock_strptime.return_value = time.mktime(time.localtime())

View File

@ -1846,15 +1846,52 @@ def _run_validation_groups(groups=[], mistral_url='', timeout=540,
fail_on_error=False):
sess = _get_session()
mistral = mistralclient.client(mistral_url=mistral_url, session=sess)
LOG.info('Starting and waiting for validation groups %s ', groups)
execution = mistral.executions.create(
'tripleo.validations.v1.run_groups',
workflow_input={'group_names': groups}
)
fail_message = ("error running the validation groups %s " % groups)
timeout_at = time.time() + timeout
_wait_for_mistral_execution(timeout_at, mistral, execution, fail_message,
fail_on_error)
# Here we fetch all the containers names from swift, we should have
# a container called with the same name as the deployment plan.
swift_client = swiftclient.Connection(session=sess)
swift = swift_client.get_account()[1]
plans = [container["name"] for container in swift]
user, password, project, auth_url = _get_auth_values()
heat = os_client_config.make_client('orchestration',
auth_url=auth_url,
username=user,
password=password,
project_name=project,
project_domain_name='Default',
user_domain_name='Default')
# Here we get all the stack names, we should have only one.
stack_names_list = [stack['stack_name'] for stack in heat.stacks.list()]
# We calculate the interception of the two previous list, the
# result should be only one value in case the Overcloud exists.
existing_stack = list(set(plans) & set(stack_names_list))
# We can not run the validations if we do not have the Overcloud deployed
# We are running a group validation and if the validation runs in both
# the Undercloud and Overcloud nodes is mandatory to define the Overcloud
# stack name. For example there are validations in the post-upgrade group
# that will run in both the Undercloud and Overcloud making this mistral
# execution fail.
if existing_stack:
LOG.info('Starting and waiting for validation groups %s ', groups)
execution = mistral.executions.create(
'tripleo.validations.v1.run_groups',
workflow_input={'group_names': groups, 'plan': existing_stack[0]}
)
fail_message = ("error running the validation groups %s " % groups)
timeout_at = time.time() + timeout
_wait_for_mistral_execution(timeout_at,
mistral,
execution,
fail_message,
fail_on_error)
else:
LOG.info('We can not run validations if the Overcloud is not deployed')
def _create_default_plan(mistral, plans, timeout=360):