From 52fb87ce976d78450f141716cec779cd1daba134 Mon Sep 17 00:00:00 2001 From: Thomas Herve Date: Wed, 5 Dec 2018 16:47:31 +0100 Subject: [PATCH] Modify roles to remove unused services When we leave services defined on roles for nodes but the services are actually disabled, we still have to process the resource in heat. This change itterates through the services to find the currently disabled services and removes them from the role files in the plan. Depends-On: https://review.openstack.org/#/c/637604/ Change-Id: I294893c20bb9f622f9118925c92c478f2151f85e --- tripleo_common/actions/templates.py | 53 +++++++++++-------- .../tests/actions/test_templates.py | 15 +++--- 2 files changed, 37 insertions(+), 31 deletions(-) diff --git a/tripleo_common/actions/templates.py b/tripleo_common/actions/templates.py index b8046ae43..0a8a410ca 100644 --- a/tripleo_common/actions/templates.py +++ b/tripleo_common/actions/templates.py @@ -37,16 +37,10 @@ class J2SwiftLoader(jinja2.BaseLoader): only the absolute path relative to the container root is searched. """ - def __init__(self, swift, container, searchpath=None): + def __init__(self, swift, container, searchpath): self.swift = swift self.container = container - if searchpath is not None: - if isinstance(searchpath, six.string_types): - self.searchpath = [searchpath] - else: - self.searchpath = list(searchpath) - else: - self.searchpath = [] + self.searchpath = [searchpath] # Always search the absolute path from the root of the swift container if '' not in self.searchpath: self.searchpath.append('') @@ -96,15 +90,9 @@ class ProcessTemplatesAction(base.TripleOAction): def __init__(self, container=constants.DEFAULT_CONTAINER_NAME): super(ProcessTemplatesAction, self).__init__() self.container = container + self.check_none = True - def _j2_render_and_put(self, - j2_template, - j2_data, - outfile_name=None, - context=None): - swift = self.get_object_client(context) - yaml_f = outfile_name or j2_template.replace('.j2.yaml', '.yaml') - + def _j2_render_and_put(self, j2_template, j2_data, yaml_f, swift): # Search for templates relative to the current template path first template_base = os.path.dirname(yaml_f) j2_loader = J2SwiftLoader(swift, self.container, template_base) @@ -282,7 +270,7 @@ class ProcessTemplatesAction(base.TripleOAction): self._j2_render_and_put(j2_template, j2_data, out_f_path, - context=context) + swift) else: # Backwards compatibility with templates # that specify {{role}} vs {{role.name}} @@ -293,12 +281,12 @@ class ProcessTemplatesAction(base.TripleOAction): self._j2_render_and_put(j2_template, j2_data, out_f_path, - context=context) + swift) else: LOG.info("Skipping rendering of %s, defined in %s" % (out_f_path, j2_excl_data)) - elif (f.endswith('.network.j2.yaml')): + elif f.endswith('.network.j2.yaml'): LOG.info("jinja2 rendering network template %s" % f) j2_template = swift.get_object(self.container, f)[1] LOG.info("jinja2 rendering networks %s" % ",".join(n_map)) @@ -318,7 +306,7 @@ class ProcessTemplatesAction(base.TripleOAction): self._j2_render_and_put(j2_template, j2_data, out_f_path, - context=context) + swift) else: LOG.info("Skipping rendering of %s, defined in %s" % (out_f_path, j2_excl_data)) @@ -331,7 +319,8 @@ class ProcessTemplatesAction(base.TripleOAction): self._j2_render_and_put(j2_template, j2_data, out_f, - context=context) + swift) + return role_data def run(self, context): error_text = None @@ -353,7 +342,7 @@ class ProcessTemplatesAction(base.TripleOAction): # not found in swift, but if they are found and an exception # occurs during processing, that exception will cause the # ProcessTemplatesAction to return an error result. - self._process_custom_roles(context) + role_data = self._process_custom_roles(context) except Exception as err: LOG.exception("Error occurred while processing custom roles.") return actions.Result(error=six.text_type(err)) @@ -387,6 +376,26 @@ class ProcessTemplatesAction(base.TripleOAction): if error_text: return actions.Result(error=error_text) + if self.check_none and role_data: + to_remove = set() + for key, value in env.get('resource_registry', {}).items(): + if (key.startswith('OS::TripleO::Services::') and + value == 'OS::Heat::None'): + to_remove.add(key) + if to_remove: + for role in role_data: + for service in to_remove: + try: + role.get('ServicesDefault', []).remove(service) + except ValueError: + pass + LOG.info('Removing unused services, updating roles') + swift.put_object( + self.container, constants.OVERCLOUD_J2_ROLES_NAME, + yaml.safe_dump(role_data)) + self.check_none = False + return ProcessTemplatesAction.run(self, context) + files = dict(list(template_files.items()) + list(env_files.items())) return { diff --git a/tripleo_common/tests/actions/test_templates.py b/tripleo_common/tests/actions/test_templates.py index 7959fd6fb..16297690e 100644 --- a/tripleo_common/tests/actions/test_templates.py +++ b/tripleo_common/tests/actions/test_templates.py @@ -165,7 +165,7 @@ class J2SwiftLoaderTest(base.TestCase): return swift def test_include_absolute_path(self): - j2_loader = templates.J2SwiftLoader(self._setup_swift(), None) + j2_loader = templates.J2SwiftLoader(self._setup_swift(), None, '') template = jinja2.Environment(loader=j2_loader).from_string( r''' Included this: @@ -193,7 +193,7 @@ class J2SwiftLoaderTest(base.TestCase): ''') def test_include_not_found(self): - j2_loader = templates.J2SwiftLoader(self._setup_swift(), None) + j2_loader = templates.J2SwiftLoader(self._setup_swift(), None, '') template = jinja2.Environment(loader=j2_loader).from_string( r''' Included this: @@ -204,7 +204,7 @@ class J2SwiftLoaderTest(base.TestCase): template.render) def test_include_invalid_path(self): - j2_loader = templates.J2SwiftLoader(self._setup_swift(), 'bar') + j2_loader = templates.J2SwiftLoader(self._setup_swift(), 'bar', '') template = jinja2.Environment(loader=j2_loader).from_string( r''' Included this: @@ -409,13 +409,12 @@ class ProcessTemplatesActionTest(base.TestCase): swift.get_object = mock.MagicMock() swift.get_container = mock.MagicMock() get_obj_client_mock.return_value = swift - mock_ctx = mock.MagicMock() # Test action = templates.ProcessTemplatesAction() action._j2_render_and_put(JINJA_SNIPPET_CONFIG, {'role': 'CustomRole'}, - 'customrole-config.yaml', context=mock_ctx) + 'customrole-config.yaml', swift) action_result = swift.put_object._mock_mock_calls[0] @@ -437,14 +436,13 @@ class ProcessTemplatesActionTest(base.TestCase): swift.get_container = mock.MagicMock( side_effect=return_container_files) get_obj_client_mock.return_value = swift - mock_ctx = mock.MagicMock() # Test action = templates.ProcessTemplatesAction() action._j2_render_and_put(r"{% include 'foo.yaml' %}", {'role': 'CustomRole'}, 'customrole-config.yaml', - context=mock_ctx) + swift) action_result = swift.put_object._mock_mock_calls[0] @@ -468,14 +466,13 @@ class ProcessTemplatesActionTest(base.TestCase): swift.get_container = mock.MagicMock( side_effect=return_container_files) get_obj_client_mock.return_value = swift - mock_ctx = mock.MagicMock() # Test action = templates.ProcessTemplatesAction() action._j2_render_and_put(r"{% include 'foo.yaml' %}", {'role': 'CustomRole'}, 'bar/customrole-config.yaml', - context=mock_ctx) + swift) action_result = swift.put_object._mock_mock_calls[0]