From 6a264b6f1169675af3056d53524e2fd8c860274f Mon Sep 17 00:00:00 2001 From: Bharath Thiruveedula Date: Sat, 29 Aug 2015 21:15:05 +0530 Subject: [PATCH] Updates the node count key for all types of bay By default the key to get node count is "number_of_minions" which is not true for baymodels other than kubernetes and it raises "KeyError" so that status of bay will not be updated. Closes-Bug: #1489725 Change-Id: I9f6a8ebbc26f501d54ef97937329845a12002d6c --- magnum/conductor/handlers/bay_conductor.py | 11 ++- magnum/conductor/template_definition.py | 15 +++ .../conductor/handlers/test_bay_conductor.py | 95 ++++++++++++++++++- .../conductor/test_template_definition.py | 21 ++++ 4 files changed, 139 insertions(+), 3 deletions(-) diff --git a/magnum/conductor/handlers/bay_conductor.py b/magnum/conductor/handlers/bay_conductor.py index f33fab878b..cbd3030f2c 100644 --- a/magnum/conductor/handlers/bay_conductor.py +++ b/magnum/conductor/handlers/bay_conductor.py @@ -217,6 +217,9 @@ class HeatPoller(object): self.context = self.openstack_client.context self.bay = bay self.attempts = 0 + baymodel = conductor_utils.retrieve_baymodel(self.context, bay) + self.template_def = TDef.get_template_definition( + 'vm', baymodel.cluster_distro, baymodel.coe) def poll_and_check(self): # TODO(yuanying): temporary implementation to update api_address, @@ -240,13 +243,17 @@ class HeatPoller(object): self.bay.status = stack.stack_status self.bay.status_reason = stack.stack_status_reason - self.bay.node_count = stack.parameters['number_of_minions'] + stack_nc_param = self.template_def.get_heat_param( + bay_attr='node_count') + self.bay.node_count = stack.parameters[stack_nc_param] self.bay.save() raise loopingcall.LoopingCallDone() elif stack.stack_status != self.bay.status: self.bay.status = stack.stack_status self.bay.status_reason = stack.stack_status_reason - self.bay.node_count = stack.parameters['number_of_minions'] + stack_nc_param = self.template_def.get_heat_param( + bay_attr='node_count') + self.bay.node_count = stack.parameters[stack_nc_param] self.bay.save() if stack.stack_status == bay_status.CREATE_FAILED: LOG.error(_LE('Unable to create bay, stack_id: %(stack_id)s, ' diff --git a/magnum/conductor/template_definition.py b/magnum/conductor/template_definition.py index 2a590b7893..ca21cef759 100644 --- a/magnum/conductor/template_definition.py +++ b/magnum/conductor/template_definition.py @@ -299,6 +299,21 @@ class TemplateDefinition(object): return template_params + def get_heat_param(self, bay_attr=None, baymodel_attr=None): + """Returns stack param name using bay and baymodel attributes + :param bay_attr bay attribute from which it maps to stack attribute + :param baymodel_attr baymodel attribute from which it maps + to stack attribute + + :return stack parameter name or None + """ + for mapping in self.param_mappings: + if (mapping.bay_attr == bay_attr and + mapping.baymodel_attr == baymodel_attr): + return mapping.heat_param + + return None + def update_outputs(self, stack, bay): for output in self.output_mappings: output.set_output(stack, bay) diff --git a/magnum/tests/unit/conductor/handlers/test_bay_conductor.py b/magnum/tests/unit/conductor/handlers/test_bay_conductor.py index 5108dc7f79..5f88db7c57 100644 --- a/magnum/tests/unit/conductor/handlers/test_bay_conductor.py +++ b/magnum/tests/unit/conductor/handlers/test_bay_conductor.py @@ -536,15 +536,19 @@ class TestBayConductorWithK8s(base.TestCase): mock_heat_client.stacks.update.assert_called_once_with(mock_stack_id, **expected_args) + @patch('magnum.conductor.utils.retrieve_baymodel') @patch('oslo_config.cfg') @patch('magnum.common.clients.OpenStackClients') - def setup_poll_test(self, mock_openstack_client, cfg): + def setup_poll_test(self, mock_openstack_client, cfg, + mock_retrieve_baymodel): cfg.CONF.bay_heat.max_attempts = 10 bay = mock.MagicMock() mock_heat_stack = mock.MagicMock() mock_heat_client = mock.MagicMock() mock_heat_client.stacks.get.return_value = mock_heat_stack mock_openstack_client.heat.return_value = mock_heat_client + baymodel = objects.BayModel(self.context, **self.baymodel_dict) + mock_retrieve_baymodel.return_value = baymodel poller = bay_conductor.HeatPoller(mock_openstack_client, bay) return (mock_heat_stack, bay, poller) @@ -691,6 +695,25 @@ class TestBayConductorWithK8s(base.TestCase): mock_heat_stack.timeout_mins = 60 self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check) + def test_poll_node_count(self): + mock_heat_stack, bay, poller = self.setup_poll_test() + + mock_heat_stack.parameters = {'number_of_minions': 1} + mock_heat_stack.stack_status = bay_status.CREATE_IN_PROGRESS + poller.poll_and_check() + + self.assertEqual(bay.node_count, 1) + + @patch('magnum.conductor.handlers.bay_conductor._update_stack_outputs') + def test_poll_node_count_by_update(self, mock_update_stack_outputs): + mock_heat_stack, bay, poller = self.setup_poll_test() + + mock_heat_stack.parameters = {'number_of_minions': 2} + mock_heat_stack.stack_status = bay_status.UPDATE_COMPLETE + self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check) + + self.assertEqual(bay.node_count, 2) + class TestHandler(db_base.DbTestCase): @@ -881,6 +904,41 @@ class TestBayConductorWithSwarm(base.TestCase): } self.assertEqual(expected, definition) + @patch('magnum.conductor.utils.retrieve_baymodel') + @patch('oslo_config.cfg') + @patch('magnum.common.clients.OpenStackClients') + def setup_poll_test(self, mock_openstack_client, cfg, + mock_retrieve_baymodel): + cfg.CONF.bay_heat.max_attempts = 10 + bay = mock.MagicMock() + mock_heat_stack = mock.MagicMock() + mock_heat_client = mock.MagicMock() + mock_heat_client.stacks.get.return_value = mock_heat_stack + mock_openstack_client.heat.return_value = mock_heat_client + baymodel = objects.BayModel(self.context, **self.baymodel_dict) + mock_retrieve_baymodel.return_value = baymodel + poller = bay_conductor.HeatPoller(mock_openstack_client, bay) + return (mock_heat_stack, bay, poller) + + def test_poll_node_count(self): + mock_heat_stack, bay, poller = self.setup_poll_test() + + mock_heat_stack.parameters = {'number_of_nodes': 1} + mock_heat_stack.stack_status = bay_status.CREATE_IN_PROGRESS + poller.poll_and_check() + + self.assertEqual(bay.node_count, 1) + + @patch('magnum.conductor.handlers.bay_conductor._update_stack_outputs') + def test_poll_node_count_by_update(self, mock_update_stack_outputs): + mock_heat_stack, bay, poller = self.setup_poll_test() + + mock_heat_stack.parameters = {'number_of_nodes': 2} + mock_heat_stack.stack_status = bay_status.UPDATE_COMPLETE + self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check) + + self.assertEqual(bay.node_count, 2) + class TestBayConductorWithMesos(base.TestCase): def setUp(self): @@ -961,3 +1019,38 @@ class TestBayConductorWithMesos(base.TestCase): 'number_of_slaves': '1', } self.assertEqual(expected, definition) + + @patch('magnum.conductor.utils.retrieve_baymodel') + @patch('oslo_config.cfg') + @patch('magnum.common.clients.OpenStackClients') + def setup_poll_test(self, mock_openstack_client, cfg, + mock_retrieve_baymodel): + cfg.CONF.bay_heat.max_attempts = 10 + bay = mock.MagicMock() + mock_heat_stack = mock.MagicMock() + mock_heat_client = mock.MagicMock() + mock_heat_client.stacks.get.return_value = mock_heat_stack + mock_openstack_client.heat.return_value = mock_heat_client + baymodel = objects.BayModel(self.context, **self.baymodel_dict) + mock_retrieve_baymodel.return_value = baymodel + poller = bay_conductor.HeatPoller(mock_openstack_client, bay) + return (mock_heat_stack, bay, poller) + + def test_poll_node_count(self): + mock_heat_stack, bay, poller = self.setup_poll_test() + + mock_heat_stack.parameters = {'number_of_slaves': 1} + mock_heat_stack.stack_status = bay_status.CREATE_IN_PROGRESS + poller.poll_and_check() + + self.assertEqual(bay.node_count, 1) + + @patch('magnum.conductor.handlers.bay_conductor._update_stack_outputs') + def test_poll_node_count_by_update(self, mock_update_stack_outputs): + mock_heat_stack, bay, poller = self.setup_poll_test() + + mock_heat_stack.parameters = {'number_of_slaves': 2} + mock_heat_stack.stack_status = bay_status.UPDATE_COMPLETE + self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check) + + self.assertEqual(bay.node_count, 2) diff --git a/magnum/tests/unit/conductor/test_template_definition.py b/magnum/tests/unit/conductor/test_template_definition.py index e104033334..cad69bb7e8 100644 --- a/magnum/tests/unit/conductor/test_template_definition.py +++ b/magnum/tests/unit/conductor/test_template_definition.py @@ -186,6 +186,12 @@ class AtomicK8sTemplateDefinitionTestCase(base.TestCase): self.assertEqual(mock_bay.discovery_url, expected_discovery_url) self.assertEqual(discovery_url, expected_discovery_url) + def test_k8s_get_heat_param(self): + k8s_def = tdef.AtomicK8sTemplateDefinition() + + heat_param = k8s_def.get_heat_param(bay_attr='node_count') + self.assertEqual(heat_param, 'number_of_minions') + class AtomicSwarmTemplateDefinitionTestCase(base.TestCase): @@ -246,3 +252,18 @@ class AtomicSwarmTemplateDefinitionTestCase(base.TestCase): actual_url = swarm_def.get_discovery_url(mock_bay) self.assertEqual(mock_bay.discovery_url, actual_url) + + def test_swarm_get_heat_param(self): + k8s_def = tdef.AtomicSwarmTemplateDefinition() + + heat_param = k8s_def.get_heat_param(bay_attr='node_count') + self.assertEqual(heat_param, 'number_of_nodes') + + +class AtomicMesosTemplateDefinitionTestCase(base.TestCase): + + def test_mesos_get_heat_param(self): + k8s_def = tdef.UbuntuMesosTemplateDefinition() + + heat_param = k8s_def.get_heat_param(bay_attr='node_count') + self.assertEqual(heat_param, 'number_of_slaves')