From 79a501a3ee03b0f4fee8592560401601087e28fb Mon Sep 17 00:00:00 2001 From: Ilya Kutukov Date: Tue, 12 Apr 2016 15:45:24 +0300 Subject: [PATCH] Custom graph support for OpenstackConfigExecuteHandler /openstack-config/execute/ handler now support ?graph_type=my-graph-name parameter Change-Id: Iaed6af093f0e2a66db29d2185104bc1e8c80fad2 Partial-Bug: #1567504 --- .../api/v1/handlers/openstack_config.py | 3 ++- nailgun/nailgun/objects/cluster.py | 6 +++-- nailgun/nailgun/task/manager.py | 3 ++- nailgun/nailgun/task/task.py | 7 +++--- .../test_openstack_config_task_manager.py | 23 +++++++++++++++++++ nailgun/nailgun/test/unit/test_objects.py | 20 ++++++++++++++++ .../unit/test_openstack_config_handler.py | 15 ++++++++++++ 7 files changed, 70 insertions(+), 7 deletions(-) diff --git a/nailgun/nailgun/api/v1/handlers/openstack_config.py b/nailgun/nailgun/api/v1/handlers/openstack_config.py index 1bd0bd65bb..6a8fcf9a09 100644 --- a/nailgun/nailgun/api/v1/handlers/openstack_config.py +++ b/nailgun/nailgun/api/v1/handlers/openstack_config.py @@ -116,6 +116,7 @@ class OpenstackConfigExecuteHandler(BaseHandler): * 400 (Invalid data) * 404 (Object dependencies not found) """ + graph_type = web.input(graph_type=None).graph_type filters = self.checked_data(self.validator.validate_execute) cluster = self.get_object_or_404( @@ -124,7 +125,7 @@ class OpenstackConfigExecuteHandler(BaseHandler): # Execute upload task for nodes task_manager = self.task_manager(cluster_id=cluster.id) try: - task = task_manager.execute(filters) + task = task_manager.execute(filters, graph_type=graph_type) except Exception as exc: logger.warn( u'Cannot execute %s task nodes: %s', diff --git a/nailgun/nailgun/objects/cluster.py b/nailgun/nailgun/objects/cluster.py index 1de903d007..e74345db7a 100644 --- a/nailgun/nailgun/objects/cluster.py +++ b/nailgun/nailgun/objects/cluster.py @@ -1124,7 +1124,8 @@ class Cluster(NailgunObject): return PluginManager.get_legacy_tasks_for_cluster(instance) @classmethod - def get_refreshable_tasks(cls, instance, filter_by_configs=None): + def get_refreshable_tasks(cls, instance, filter_by_configs=None, + graph_type=None): """Return list of refreshable tasks If 'filter_by_configs' specified then only tasks needed to update @@ -1133,12 +1134,13 @@ class Cluster(NailgunObject): :param instance: a Cluster instance :param filter_by_configs: a list with configs resources + :param graph_type: deployment graph type :return: list of tasks """ if filter_by_configs: filter_by_configs = set(filter_by_configs) tasks = [] - for task in cls.get_deployment_tasks(instance): + for task in cls.get_deployment_tasks(instance, graph_type): refresh_on = task.get(consts.TASK_REFRESH_FIELD) if (refresh_on and (filter_by_configs is None diff --git a/nailgun/nailgun/task/manager.py b/nailgun/nailgun/task/manager.py index cb644c3e33..ef4f88d1e9 100644 --- a/nailgun/nailgun/task/manager.py +++ b/nailgun/nailgun/task/manager.py @@ -1317,7 +1317,7 @@ class OpenstackConfigTaskManager(TaskManager): return tasks.ClusterTransaction return tasks.UpdateOpenstackConfigTask - def execute(self, filters, force=False, **kwargs): + def execute(self, filters, force=False, graph_type=None, **kwargs): self.check_running_task(consts.TASK_NAMES.deployment) task = Task(name=consts.TASK_NAMES.deployment, @@ -1332,6 +1332,7 @@ class OpenstackConfigTaskManager(TaskManager): task, self.get_deployment_task(), nodes_to_update, + graph_type=graph_type, method_name='message', force=force ) diff --git a/nailgun/nailgun/task/task.py b/nailgun/nailgun/task/task.py index e8daa356d1..3bb3051463 100644 --- a/nailgun/nailgun/task/task.py +++ b/nailgun/nailgun/task/task.py @@ -2086,7 +2086,7 @@ class UpdateOpenstackConfigTask(BaseDeploymentTask): }) @classmethod - def message(cls, task, nodes, **kwargs): + def message(cls, task, nodes, graph_type, **kwargs): configs = objects.OpenstackConfigCollection.find_configs_for_nodes( task.cluster, nodes) updated_configs = set() @@ -2099,10 +2099,11 @@ class UpdateOpenstackConfigTask(BaseDeploymentTask): raise errors.NoChanges() refreshable_tasks = objects.Cluster.get_refreshable_tasks( - task.cluster, updated_configs + task.cluster, updated_configs, graph_type ) task_ids = {t['id'] for t in refreshable_tasks} - deployment_tasks = objects.Cluster.get_deployment_tasks(task.cluster) + deployment_tasks = objects.Cluster.get_deployment_tasks( + task.cluster, graph_type) return cls.call_deployment_method( task, tasks=deployment_tasks, nodes=nodes, task_ids=task_ids )[1] diff --git a/nailgun/nailgun/test/integration/test_openstack_config_task_manager.py b/nailgun/nailgun/test/integration/test_openstack_config_task_manager.py index 9c35ad139e..7ce3e4d8b0 100644 --- a/nailgun/nailgun/test/integration/test_openstack_config_task_manager.py +++ b/nailgun/nailgun/test/integration/test_openstack_config_task_manager.py @@ -16,6 +16,7 @@ from mock import patch from nailgun import consts from nailgun.db.sqlalchemy.models import DeploymentGraphTask +from nailgun import objects from nailgun.orchestrator.tasks_templates import make_generic_task from nailgun.task.manager import OpenstackConfigTaskManager from nailgun.test import base @@ -120,6 +121,28 @@ class TestOpenstackConfigTaskManager80(base.BaseIntegrationTest): self.assertItemsEqual(deployment_tasks, [ make_generic_task([self.nodes[0].uid], self.refreshable_task)]) + @patch('nailgun.rpc.cast') + def test_configuration_execute_w_custom_graph(self, mocked_rpc): + custom_tasks = [ + { + 'id': 'custom-task', + 'type': 'puppet', + 'roles': '*' + } + ] + objects.DeploymentGraph.create_for_model( + {'tasks': custom_tasks}, self.cluster, 'custom-graph') + task_manager = OpenstackConfigTaskManager(self.cluster.id) + task = task_manager.execute( + {'cluster_id': self.cluster.id}, graph_type='custom-graph') + + self.assertEqual(task.status, consts.TASK_STATUSES.pending) + + self.assertEqual( + mocked_rpc.call_args[0][1]['args']['tasks'][0]['task_name'], + 'custom-task' + ) + @patch('nailgun.rpc.cast') def test_configuration_execute_by_node_id(self, mocked_rpc): task_manager = OpenstackConfigTaskManager(self.cluster.id) diff --git a/nailgun/nailgun/test/unit/test_objects.py b/nailgun/nailgun/test/unit/test_objects.py index 78f8d25071..f7b6b2fb76 100644 --- a/nailgun/nailgun/test/unit/test_objects.py +++ b/nailgun/nailgun/test/unit/test_objects.py @@ -1378,6 +1378,26 @@ class TestClusterObject(BaseTestCase): self.assertIn(deployment_tasks[1]['id'], tasks_ids) self.assertNotIn(deployment_tasks[0]['id'], tasks_ids) + def test_get_refreshable_tasks_w_custom_graph(self): + deployment_tasks = [ + self.env.get_default_plugin_deployment_tasks(**{ + 'id': 'refreshable_task_on_keystone', + consts.TASK_REFRESH_FIELD: ['keystone_config'] + })[0] + ] + cluster = self.cluster + release_graph = objects.DeploymentGraph.get_for_model(cluster.release) + release_tasks = objects.DeploymentGraph.get_tasks(release_graph) + objects.DeploymentGraph.create_for_model( + {'tasks': release_tasks}, cluster.release, 'custom-graph') + objects.DeploymentGraph.create_for_model( + {'tasks': deployment_tasks}, cluster, 'custom-graph') + + refreshable_tasks = objects.Cluster.get_refreshable_tasks( + cluster, None, 'custom-graph') + tasks_ids = [t['id'] for t in refreshable_tasks] + self.assertIn(deployment_tasks[0]['id'], tasks_ids) + def test_get_plugin_network_roles(self): network_roles = [self._get_network_role_metadata()] plugin_data = self.env.get_default_plugin_metadata( diff --git a/nailgun/nailgun/test/unit/test_openstack_config_handler.py b/nailgun/nailgun/test/unit/test_openstack_config_handler.py index ff1f3fa70d..7e4c018c2d 100644 --- a/nailgun/nailgun/test/unit/test_openstack_config_handler.py +++ b/nailgun/nailgun/test/unit/test_openstack_config_handler.py @@ -473,6 +473,21 @@ class TestOpenstackConfigHandlers(BaseIntegrationTest): expect_errors=True) self.check_fail_deploy_running(deploy_task_id, resp) + @mock.patch('objects.Cluster.get_deployment_tasks') + @mock.patch('nailgun.task.task.rpc.cast') + def test_execute_update_open_stack_config_w_custom_graph( + self, mock_rpc, tasks_mock): + data = {'cluster_id': self.clusters[0].id} + resp = self.app.put( + reverse('OpenstackConfigExecuteHandler') + + '?graph_type=custom-graph', + jsonutils.dumps(data), + headers=self.default_headers, + expect_errors=False + ) + self.assertEqual(202, resp.status_code) + self.assertIn('custom-graph', tasks_mock.call_args[0]) + @classmethod def _make_filter_url(cls, **kwargs): return '{0}?{1}'.format(