From 5dcc3c0fb5e926cc040ac5cac4a629509fe03d00 Mon Sep 17 00:00:00 2001 From: Dougal Matthews Date: Fri, 14 Oct 2016 13:08:56 +0100 Subject: [PATCH] Only create the Mistral config env if it doesn't exist From I71edae4a4dee2204edf32e3b2800f075d221b856 we started to create a Mistral env in instack-undercloud. This happens at install time. We failed to only do this if the environment doesn't exist, at the moment instack will fail on a second undercloud install as Mistral will attempt to create the environment again and raise an exception. This patch also fixes a regression introduced by I71edae4a4dee2204edf32e3b2800f075d221b856 which created the config env *after* creating the default plan - given the default plan creation depends on the environment, this was an error. Closes-Bug: #1633450 Change-Id: I186217fd0e1125519149763e610d3efdff583388 (cherry picked from commit a370e16be69a1d4a72038f26eb58f33a40120f48) --- instack_undercloud/tests/test_undercloud.py | 32 ++++++++++++++++++++- instack_undercloud/undercloud.py | 32 ++++++++++++++------- 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/instack_undercloud/tests/test_undercloud.py b/instack_undercloud/tests/test_undercloud.py index a18f046d4..0ac1fc1fc 100644 --- a/instack_undercloud/tests/test_undercloud.py +++ b/instack_undercloud/tests/test_undercloud.py @@ -19,6 +19,7 @@ import subprocess import fixtures import mock +from mistralclient.api import base as mistralclient_base from novaclient import exceptions from oslo_config import fixture as config_fixture from oslotest import base @@ -525,7 +526,8 @@ class TestPostConfig(base.BaseTestCase): mock.call(mock_instance, 'swift-storage', 'swift-storage'), ] mock_ensure_flavor.assert_has_calls(calls) - mock_post_config_mistral.assert_called_once_with(mock_instance_mistral) + mock_post_config_mistral.assert_called_once_with(instack_env, + mock_instance_mistral) def test_create_default_plan(self): mock_mistral = mock.Mock() @@ -551,6 +553,34 @@ class TestPostConfig(base.BaseTestCase): undercloud._create_default_plan(mock_mistral) mock_mistral.executions.create.assert_not_called() + def test_create_config_environment(self): + mock_mistral = mock.Mock() + mock_mistral.environments.get.side_effect = ( + mistralclient_base.APIException) + + env = { + "UNDERCLOUD_CEILOMETER_SNMPD_PASSWORD": "snmpd-pass" + } + json_string = '{"undercloud_ceilometer_snmpd_password": "snmpd-pass"}' + + undercloud._create_mistral_config_environment(env, mock_mistral) + + mock_mistral.environments.create.assert_called_once_with( + name="tripleo.undercloud-config", + variables=json_string) + + def test_create_config_environment_existing(self): + mock_mistral = mock.Mock() + environment = collections.namedtuple('environment', ['name']) + mock_mistral.environments.get.return_value = environment( + name='overcloud') + env = { + "UNDERCLOUD_CEILOMETER_SNMPD_PASSWORD": "snmpd-pass" + } + + undercloud._create_mistral_config_environment(env, mock_mistral) + mock_mistral.executions.create.assert_not_called() + def test_prepare_ssh_environment(self): mock_mistral = mock.Mock() undercloud._prepare_ssh_environment(mock_mistral) diff --git a/instack_undercloud/undercloud.py b/instack_undercloud/undercloud.py index 15d1f962c..f7caf6052 100644 --- a/instack_undercloud/undercloud.py +++ b/instack_undercloud/undercloud.py @@ -35,6 +35,7 @@ from keystoneclient import auth from keystoneclient import session from keystoneclient import discover from mistralclient.api import client as mistralclient +from mistralclient.api import base as mistralclient_base from novaclient import client as novaclient from novaclient import exceptions from oslo_config import cfg @@ -1092,6 +1093,22 @@ def _clean_os_refresh_config(): _run_command(args, name='Clean os-refresh-config') +def _create_mistral_config_environment(instack_env, mistral): + # Store the snmpd password in a Mistral environment so it can be accessed + # by the Mistral actions. + snmpd_password = instack_env["UNDERCLOUD_CEILOMETER_SNMPD_PASSWORD"] + + env_name = "tripleo.undercloud-config" + try: + mistral.environments.get(env_name) + except mistralclient_base.APIException: + mistral.environments.create( + name=env_name, + variables=json.dumps({ + "undercloud_ceilometer_snmpd_password": snmpd_password + })) + + def _create_default_plan(mistral, timeout=180): plan_name = 'overcloud' queue_name = str(uuid.uuid4()) @@ -1134,17 +1151,10 @@ def _prepare_ssh_environment(mistral): mistral.executions.create('tripleo.validations.v1.copy_ssh_key') -def _post_config_mistral(mistral): - _create_default_plan(mistral) +def _post_config_mistral(instack_env, mistral): - # Store the snmpd password in a Mistral environment so it can be accessed - # by the Mistral actions. - snmpd_password = CONF.auth["undercloud_ceilometer_snmpd_password"] - mistral.environments.create( - name="tripleo.undercloud-config", - variables=json.dumps({ - "undercloud_ceilometer_snmpd_password": snmpd_password - })) + _create_mistral_config_environment(instack_env, mistral) + _create_default_plan(mistral) if CONF.enable_validations: _prepare_ssh_environment(mistral) @@ -1173,7 +1183,7 @@ def _post_config(instack_env): api_key=password, project_name=tenant, auth_url=auth_url) - _post_config_mistral(mistral) + _post_config_mistral(instack_env, mistral) def install(instack_root):