Use a Zaqar queue to get stack events
This adds the ability to use Zaqar to retrieve Heat events instead of polling the API. Change-Id: I3b836637d4e72aaf7183dbabf0b0e32c2caa8270 Closes-Bug: #1639283
This commit is contained in:
parent
9e670a18d4
commit
f4f0e92d75
|
@ -22,6 +22,7 @@ from unittest import TestCase
|
|||
import yaml
|
||||
|
||||
from tripleoclient import exceptions
|
||||
from tripleoclient.tests import fakes
|
||||
from tripleoclient import utils
|
||||
|
||||
|
||||
|
@ -109,6 +110,20 @@ class TestWaitForStackUtil(TestCase):
|
|||
result = utils.wait_for_stack_ready(self.mock_orchestration, 'stack')
|
||||
self.assertEqual(False, result)
|
||||
|
||||
@mock.patch("heatclient.common.event_utils.wait_for_events")
|
||||
def test_wait_for_stack_websocket(self, mock_wait_for_events):
|
||||
|
||||
mock_wait_for_events.return_value = ("CREATE_IN_PROGRESS", "MESSAGE")
|
||||
|
||||
stack = mock.Mock()
|
||||
stack.stack_name = 'stack'
|
||||
stack.stack_status = 'CREATE_IN_PROGRESS'
|
||||
self.mock_orchestration.stacks.get.return_value = stack
|
||||
|
||||
result = utils.wait_for_stack_ready(self.mock_orchestration, 'stack',
|
||||
ws_client=fakes.FakeWebSocket())
|
||||
self.assertEqual(False, result)
|
||||
|
||||
@mock.patch('tripleoclient.utils.wait_for_provision_state')
|
||||
def test_set_nodes_state(self, wait_for_state_mock):
|
||||
|
||||
|
|
|
@ -463,10 +463,13 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
|
|||
self.assertEqual(*args)
|
||||
|
||||
def _fake_heat_deploy(self, stack, stack_name, template_path,
|
||||
parameters, environments, timeout, tht_root,
|
||||
env, update_plan_only, run_validations):
|
||||
parameters, environments, timeout, tht_root, env,
|
||||
update_plan_only, run_validations, ws_client):
|
||||
queue = env['event_sinks'][0]['target']
|
||||
assertEqual(
|
||||
{'parameter_defaults': {},
|
||||
'event_sinks': [
|
||||
{'target': queue, 'ttl': 14400, 'type': 'zaqar-queue'}],
|
||||
'resource_registry': {'Test': u'OS::Heat::None'}}, env)
|
||||
|
||||
mock_deploy_heat.side_effect = _fake_heat_deploy
|
||||
|
@ -519,10 +522,13 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
|
|||
self.assertEqual(*args)
|
||||
|
||||
def _fake_heat_deploy(self, stack, stack_name, template_path,
|
||||
parameters, environments, timeout, tht_root,
|
||||
env, update_plan_only, run_validations):
|
||||
parameters, environments, timeout, tht_root, env,
|
||||
update_plan_only, run_validations, ws_client):
|
||||
queue = env['event_sinks'][0]['target']
|
||||
assertEqual(
|
||||
{'parameter_defaults': {},
|
||||
'event_sinks': [
|
||||
{'target': queue, 'ttl': 14400, 'type': 'zaqar-queue'}],
|
||||
'resource_registry': {'Test': u'OS::Heat::None'}}, env)
|
||||
|
||||
mock_deploy_heat.side_effect = _fake_heat_deploy
|
||||
|
@ -760,13 +766,14 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
|
|||
self, mock_heat_deploy_func):
|
||||
result = self.cmd._try_overcloud_deploy_with_compat_yaml(
|
||||
'/fake/path', {}, 'overcloud', {}, ['~/overcloud-env.json'], 1,
|
||||
{}, False, True)
|
||||
{}, False, True, mock.ANY)
|
||||
# If it returns None it succeeded
|
||||
self.assertIsNone(result)
|
||||
mock_heat_deploy_func.assert_called_once_with(
|
||||
self.cmd, {}, 'overcloud',
|
||||
'/fake/path/' + constants.OVERCLOUD_YAML_NAME, {},
|
||||
['~/overcloud-env.json'], 1, '/fake/path', {}, False, True)
|
||||
['~/overcloud-env.json'], 1, '/fake/path', {}, False, True,
|
||||
mock.ANY)
|
||||
|
||||
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
|
||||
'_heat_deploy', autospec=True)
|
||||
|
@ -775,7 +782,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
|
|||
mock_heat_deploy_func.side_effect = ObjectClientException('error')
|
||||
self.assertRaises(ValueError,
|
||||
self.cmd._try_overcloud_deploy_with_compat_yaml,
|
||||
'/fake/path', mock.ANY, mock.ANY, mock.ANY,
|
||||
'/fake/path', mock.ANY, mock.ANY, mock.ANY, mock.ANY,
|
||||
mock.ANY, mock.ANY, mock.ANY, mock.ANY, mock.ANY)
|
||||
|
||||
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
|
||||
|
@ -786,8 +793,8 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
|
|||
ObjectClientException('/fake/path not found')
|
||||
try:
|
||||
self.cmd._try_overcloud_deploy_with_compat_yaml(
|
||||
'/fake/path', mock.ANY, mock.ANY, mock.ANY,
|
||||
mock.ANY, mock.ANY, mock.ANY, mock.ANY, mock.ANY)
|
||||
'/fake/path', mock.ANY, mock.ANY, mock.ANY, mock.ANY, mock.ANY,
|
||||
mock.ANY, mock.ANY, mock.ANY, mock.ANY)
|
||||
except ValueError as value_error:
|
||||
self.assertIn('/fake/path', str(value_error))
|
||||
|
||||
|
@ -1256,7 +1263,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
|
|||
mock_get_template_contents.return_value = [{}, {}]
|
||||
|
||||
self.cmd._heat_deploy(mock_stack, 'mock_stack', '/tmp', {},
|
||||
{}, 1, '/tmp', {}, True, False)
|
||||
{}, 1, '/tmp', {}, True, False, mock.ANY)
|
||||
|
||||
self.assertFalse(mock_deploy_and_wait.called)
|
||||
|
||||
|
|
|
@ -153,7 +153,7 @@ def check_hypervisor_stats(compute_client, nodes=1, memory=0, vcpu=0):
|
|||
|
||||
|
||||
def wait_for_stack_ready(orchestration_client, stack_name, marker=None,
|
||||
action='CREATE', verbose=False):
|
||||
action='CREATE', verbose=False, ws_client=None):
|
||||
"""Check the status of an orchestration stack
|
||||
|
||||
Get the status of an orchestration stack and check whether it is complete
|
||||
|
@ -183,9 +183,14 @@ def wait_for_stack_ready(orchestration_client, stack_name, marker=None,
|
|||
out = sys.stdout
|
||||
else:
|
||||
out = open(os.devnull, "w")
|
||||
stack_status, msg = event_utils.poll_for_events(
|
||||
orchestration_client, stack_name, action=action,
|
||||
poll_period=5, marker=marker, out=out, nested_depth=2)
|
||||
if ws_client is not None:
|
||||
with ws_client:
|
||||
stack_status, msg = event_utils.wait_for_events(
|
||||
ws_client, stack_name, out=out)
|
||||
else:
|
||||
stack_status, msg = event_utils.poll_for_events(
|
||||
orchestration_client, stack_name, action=action,
|
||||
poll_period=5, marker=marker, out=out, nested_depth=2)
|
||||
print(msg)
|
||||
return stack_status == '%s_COMPLETE' % action
|
||||
|
||||
|
|
|
@ -192,7 +192,7 @@ class DeployOvercloud(command.Command):
|
|||
|
||||
def _heat_deploy(self, stack, stack_name, template_path, parameters,
|
||||
env_files, timeout, tht_root, env, update_plan_only,
|
||||
run_validations):
|
||||
run_validations, ws_client):
|
||||
"""Verify the Baremetal nodes are available and do a stack update"""
|
||||
|
||||
clients = self.app.client_manager
|
||||
|
@ -242,7 +242,8 @@ class DeployOvercloud(command.Command):
|
|||
deployment.deploy_and_wait(self.log, clients, stack, stack_name,
|
||||
self.app_args.verbose_level,
|
||||
timeout=timeout,
|
||||
run_validations=run_validations)
|
||||
run_validations=run_validations,
|
||||
ws_client=ws_client)
|
||||
|
||||
def _load_environment_directories(self, directories):
|
||||
if os.environ.get('TRIPLEO_ENVIRONMENT_DIRECTORY'):
|
||||
|
@ -433,6 +434,13 @@ class DeployOvercloud(command.Command):
|
|||
parsed_args.environment_directories))
|
||||
env.update(self._create_parameters_env(parameters))
|
||||
|
||||
event_queue = str(uuid.uuid4())
|
||||
env['event_sinks'] = [
|
||||
{'type': 'zaqar-queue', 'target': event_queue,
|
||||
'ttl': parsed_args.timeout * 60}]
|
||||
clients = self.app.client_manager
|
||||
ws_client = clients.tripleoclient.messaging_websocket(event_queue)
|
||||
|
||||
if parsed_args.rhel_reg:
|
||||
reg_env_files, reg_env = self._create_registration_env(parsed_args)
|
||||
created_env_files.extend(reg_env_files)
|
||||
|
@ -449,19 +457,19 @@ class DeployOvercloud(command.Command):
|
|||
self._try_overcloud_deploy_with_compat_yaml(
|
||||
tht_root, stack, parsed_args.stack, parameters, env_files,
|
||||
parsed_args.timeout, env, parsed_args.update_plan_only,
|
||||
parsed_args.run_validations)
|
||||
parsed_args.run_validations, ws_client)
|
||||
|
||||
def _try_overcloud_deploy_with_compat_yaml(self, tht_root, stack,
|
||||
stack_name, parameters,
|
||||
env_files, timeout,
|
||||
env, update_plan_only,
|
||||
run_validations):
|
||||
run_validations, ws_client):
|
||||
overcloud_yaml = os.path.join(tht_root, constants.OVERCLOUD_YAML_NAME)
|
||||
try:
|
||||
self._heat_deploy(stack, stack_name, overcloud_yaml,
|
||||
parameters, env_files, timeout,
|
||||
tht_root, env, update_plan_only,
|
||||
run_validations)
|
||||
run_validations, ws_client)
|
||||
except ClientException as e:
|
||||
messages = 'Failed to deploy: %s' % str(e)
|
||||
raise ValueError(messages)
|
||||
|
|
|
@ -45,7 +45,7 @@ def deploy(clients, **workflow_input):
|
|||
|
||||
|
||||
def deploy_and_wait(log, clients, stack, plan_name, verbose_level,
|
||||
timeout=None, run_validations=False):
|
||||
timeout=None, run_validations=False, ws_client=None):
|
||||
"""Start the deploy and wait for it to finish"""
|
||||
|
||||
workflow_input = {
|
||||
|
@ -79,7 +79,8 @@ def deploy_and_wait(log, clients, stack, plan_name, verbose_level,
|
|||
time.sleep(10)
|
||||
verbose_events = verbose_level > 0
|
||||
create_result = utils.wait_for_stack_ready(
|
||||
orchestration_client, plan_name, marker, action, verbose_events)
|
||||
orchestration_client, plan_name, marker, action, verbose_events,
|
||||
ws_client)
|
||||
if not create_result:
|
||||
shell.OpenStackShell().run(["stack", "failures", "list", plan_name])
|
||||
if stack is None:
|
||||
|
|
Loading…
Reference in New Issue