def __init__(self, config, osc=None): """Constructor: the signature should be identical within the subclasses :param config: Configuration related to this plugin :type config: :py:class:`~.Struct` :param osc: An OpenStackClients instance :type osc: :py:class:`~.OpenStackClients` instance """ super(BaseStrategy, self).__init__(config) self.ctx = context.make_context() self._name = self.get_name() self._display_name = self.get_display_name() self._goal = self.get_goal() # default strategy level self._strategy_level = level.StrategyLevel.conservative self._cluster_state_collector = None # the solution given by the strategy self._solution = default.DefaultSolution(goal=self.goal, strategy=self) self._osc = osc self._collector_manager = None self._compute_model = None self._storage_model = None self._baremetal_model = None self._input_parameters = utils.Struct() self._audit_scope = None self._datasource_backend = None
def test_schedule_two_actions(self): solution = dsol.DefaultSolution(goal=mock.Mock(), strategy=self.strategy) parameters = { "source_node": "server1", "destination_node": "server2", } solution.add_action(action_type="migrate", resource_id="b199db0c-1408-4d52-b5a5-5ca14de0ff36", input_parameters=parameters) solution.add_action(action_type="nop", input_parameters={"message": "Hello world"}) with mock.patch.object( pbase.WorkloadStabilizationPlanner, "create_action", wraps=self.planner.create_action) as m_create_action: self.planner.config.weights = {'migrate': 3, 'nop': 5} action_plan = self.planner.schedule(self.context, self.audit.id, solution) self.assertIsNotNone(action_plan.uuid) self.assertEqual(2, m_create_action.call_count) # check order filters = {'action_plan_id': action_plan.id} actions = objects.Action.dbapi.get_action_list(self.context, filters) self.assertEqual("nop", actions[0].action_type) self.assertEqual("migrate", actions[1].action_type)
def test_schedule_migrate_resize_actions(self, m_nova, m_generate_uuid): m_generate_uuid.side_effect = [ "00000000-0000-0000-0000-000000000000", # Action plan "11111111-1111-1111-1111-111111111111", # Migrate 1 "22222222-2222-2222-2222-222222222222", # Migrate 2 "33333333-3333-3333-3333-333333333333", # Migrate 3 "44444444-4444-4444-4444-444444444444", # Migrate 4 "55555555-5555-5555-5555-555555555555", # Migrate 5 "66666666-6666-6666-6666-666666666666", # Resize 1 "77777777-7777-7777-7777-777777777777", # Resize 2 "88888888-8888-8888-8888-888888888888", # Nop "99999999-9999-9999-9999-999999999999", ] m_nova.return_value = 'server1' solution = dsol.DefaultSolution(goal=mock.Mock(), strategy=self.strategy) parameters = { "source_node": "server1", "destination_node": "server2", } solution.add_action(action_type="migrate", resource_id="DOESNOTMATTER", input_parameters=parameters) solution.add_action(action_type="resize", resource_id="DOESNOTMATTER", input_parameters={"flavor": "x1"}) with mock.patch.object(pbase.WeightPlanner, "create_scheduled_actions", wraps=self.planner.create_scheduled_actions ) as m_create_scheduled_actions: action_plan = self.planner.schedule(self.context, self.audit.id, solution) self.assertIsNotNone(action_plan.uuid) self.assertEqual(1, m_create_scheduled_actions.call_count) action_graph = m_create_scheduled_actions.call_args[0][1] expected_edges = \ [({'action_type': 'migrate', 'parents': [], 'uuid': '11111111-1111-1111-1111-111111111111'}, {'action_type': 'resize', 'parents': ['11111111-1111-1111-1111-111111111111'], 'uuid': '22222222-2222-2222-2222-222222222222'})] edges = sorted([(src.as_dict(), dst.as_dict()) for src, dst in action_graph.edges()], key=lambda pair: pair[0]['uuid']) for src, dst in edges: for key in ('id', 'action_plan', 'action_plan_id', 'created_at', 'input_parameters', 'deleted_at', 'updated_at', 'state'): del src[key] del dst[key] self.assertEqual(len(expected_edges), len(edges)) for pair in expected_edges: self.assertIn(pair, edges)
def test_schedule_actions_with_unknown_action(self): solution = dsol.DefaultSolution(goal=mock.Mock(), strategy=self.strategy) parameters = { "src_uuid_node": "server1", "dst_uuid_node": "server2", } solution.add_action(action_type="migrate", resource_id="b199db0c-1408-4d52-b5a5-5ca14de0ff36", input_parameters=parameters) solution.add_action(action_type="new_action_type", resource_id="", input_parameters={}) with mock.patch.object( pbase.WorkloadStabilizationPlanner, "create_action", wraps=self.planner.create_action) as m_create_action: with mock.patch.object(nova_helper, 'NovaHelper') as m_nova: self.planner.config.weights = {'migrate': 0} self.assertRaises(KeyError, self.planner.schedule, self.context, self.audit.id, solution) assert not m_nova.called self.assertEqual(2, m_create_action.call_count)
def test_schedule_actions_with_unsupported_action(self): solution = dsol.DefaultSolution(goal=mock.Mock(), strategy=self.strategy) parameters = { "src_uuid_node": "server1", "dst_uuid_node": "server2", } solution.add_action(action_type="migrate", resource_id="b199db0c-1408-4d52-b5a5-5ca14de0ff36", input_parameters=parameters) solution.add_action(action_type="new_action_type", resource_id="", input_parameters={}) with mock.patch.object( pbase.WorkloadStabilizationPlanner, "create_action", wraps=self.planner.create_action) as m_create_action: with mock.patch.object(nova_helper, 'NovaHelper') as m_nova: self.planner.config.weights = { 'turn_host_to_acpi_s3_state': 0, 'resize': 1, 'migrate': 2, 'sleep': 3, 'change_nova_service_state': 4, 'nop': 5, 'new_action_type': 6 } self.assertRaises(exception.UnsupportedActionType, self.planner.schedule, self.context, self.audit.id, solution) assert not m_nova.called self.assertEqual(2, m_create_action.call_count)
def test_schedule_two_actions(self): default_planner = pbase.DefaultPlanner() audit = db_utils.create_test_audit(uuid=utils.generate_uuid()) solution = dsol.DefaultSolution() parameters = { "src_uuid_hypervisor": "server1", "dst_uuid_hypervisor": "server2", } solution.add_action(action_type="migrate", resource_id="b199db0c-1408-4d52-b5a5-5ca14de0ff36", input_parameters=parameters) solution.add_action(action_type="nop", resource_id="", input_parameters={}) with mock.patch.object( pbase.DefaultPlanner, "create_action", wraps=default_planner.create_action) as m_create_action: action_plan = default_planner.schedule(self.context, audit.id, solution) self.assertIsNotNone(action_plan.uuid) self.assertEqual(2, m_create_action.call_count) # check order filters = {'action_plan_id': action_plan.id} actions = objects.Action.dbapi.get_action_list(self.context, filters) self.assertEqual("nop", actions[0].action_type) self.assertEqual("migrate", actions[1].action_type)
def test_schedule_migrate_resize_actions(self, mock_nova): mock_nova.return_value = 'server1' solution = dsol.DefaultSolution(goal=mock.Mock(), strategy=self.strategy) parameters = { "source_node": "server1", "destination_node": "server2", } solution.add_action(action_type="migrate", resource_id="b199db0c-1408-4d52-b5a5-5ca14de0ff36", input_parameters=parameters) solution.add_action(action_type="resize", resource_id="b199db0c-1408-4d52-b5a5-5ca14de0ff36", input_parameters={"flavor": "x1"}) with mock.patch.object( pbase.WorkloadStabilizationPlanner, "create_action", wraps=self.planner.create_action) as m_create_action: with mock.patch.object(nova_helper, 'NovaHelper') as m_nova: self.planner.config.weights = {'migrate': 3, 'resize': 2} action_plan = self.planner.schedule(self.context, self.audit.id, solution) self.assertEqual(1, m_nova.call_count) self.assertIsNotNone(action_plan.uuid) self.assertEqual(2, m_create_action.call_count) # check order filters = {'action_plan_id': action_plan.id} actions = objects.Action.dbapi.get_action_list(self.context, filters) self.assertEqual("migrate", actions[0].action_type) self.assertEqual("resize", actions[1].action_type) self.assertEqual(actions[0].uuid, actions[1].parents[0])
def __init__(self, name=None, description=None, osc=None): """:param osc: an OpenStackClients instance""" self._name = name self.description = description # default strategy level self._strategy_level = level.StrategyLevel.conservative self._cluster_state_collector = None # the solution given by the strategy self._solution = default.DefaultSolution() self._osc = osc
def test_schedule_actions(self, m_generate_uuid): m_generate_uuid.side_effect = [ "00000000-0000-0000-0000-000000000000", # Action plan "11111111-1111-1111-1111-111111111111", # Migrate 1 "22222222-2222-2222-2222-222222222222", "33333333-3333-3333-3333-333333333333", # "44444444-4444-4444-4444-444444444444", # "55555555-5555-5555-5555-555555555555", # "66666666-6666-6666-6666-666666666666", # "77777777-7777-7777-7777-777777777777", # "88888888-8888-8888-8888-888888888888", # "99999999-9999-9999-9999-999999999999", ] solution = dsol.DefaultSolution(goal=mock.Mock(), strategy=self.strategy) solution.add_action(action_type="migrate", resource_id="DOESNOTMATTER", input_parameters={ "source_node": "server1", "destination_node": "server2" }) self.planner.config.weights = {'migrate': 3} action_plan = self.planner.schedule(self.context, self.audit.id, solution) self.assertIsNotNone(action_plan.uuid) with mock.patch.object(pbase.WeightPlanner, "create_scheduled_actions", wraps=self.planner.create_scheduled_actions ) as m_create_scheduled_actions: action_plan = self.planner.schedule(self.context, self.audit.id, solution) self.assertIsNotNone(action_plan.uuid) self.assertEqual(1, m_create_scheduled_actions.call_count) action_graph = m_create_scheduled_actions.call_args[0][1] expected_edges = [] edges = sorted([(src.as_dict(), dst.as_dict()) for src, dst in action_graph.edges()], key=lambda pair: pair[0]['uuid']) for src, dst in edges: for key in ('id', 'action_plan', 'action_plan_id', 'created_at', 'input_parameters', 'deleted_at', 'updated_at', 'state'): del src[key] del dst[key] self.assertEqual(len(expected_edges), len(edges)) for pair in expected_edges: self.assertIn(pair, edges)
def test_schedule_actions_with_unknown_action(self, m_generate_uuid): m_generate_uuid.side_effect = [ "00000000-0000-0000-0000-000000000000", # Action plan "11111111-1111-1111-1111-111111111111", # Migrate 1 "22222222-2222-2222-2222-222222222222", # new_action_type "33333333-3333-3333-3333-333333333333", ] solution = dsol.DefaultSolution(goal=mock.Mock(), strategy=self.strategy) parameters = { "src_uuid_node": "server1", "dst_uuid_node": "server2", } solution.add_action(action_type="migrate", resource_id="DOESNOTMATTER", input_parameters=parameters) solution.add_action(action_type="new_action_type", resource_id="", input_parameters={}) with mock.patch.object(pbase.WeightPlanner, "create_scheduled_actions", wraps=self.planner.create_scheduled_actions ) as m_create_scheduled_actions: action_plan = self.planner.schedule(self.context, self.audit.id, solution) self.assertIsNotNone(action_plan.uuid) self.assertEqual(1, m_create_scheduled_actions.call_count) action_graph = m_create_scheduled_actions.call_args[0][1] expected_edges = \ [({'action_type': 'new_action_type', 'parents': [], 'uuid': '22222222-2222-2222-2222-222222222222'}, {'action_type': 'migrate', 'parents': ['22222222-2222-2222-2222-222222222222'], 'uuid': '11111111-1111-1111-1111-111111111111'})] edges = sorted([(src.as_dict(), dst.as_dict()) for src, dst in action_graph.edges()], key=lambda pair: pair[0]['uuid']) for src, dst in edges: for key in ('id', 'action_plan', 'action_plan_id', 'created_at', 'input_parameters', 'deleted_at', 'updated_at', 'state'): del src[key] del dst[key] self.assertEqual(len(expected_edges), len(edges)) for pair in expected_edges: self.assertIn(pair, edges)
def test_default_solution_with_no_input_parameters(self): solution = default.DefaultSolution(goal=mock.Mock(), strategy=mock.Mock()) solution.add_action(action_type="nop", resource_id="b199db0c-1408-4d52-b5a5-5ca14de0ff36") self.assertEqual(1, len(solution.actions)) expected_action_type = "nop" expected_parameters = { "resource_id": "b199db0c-1408-4d52-b5a5-5ca14de0ff36" } self.assertEqual(expected_action_type, solution.actions[0].get('action_type')) self.assertEqual(expected_parameters, solution.actions[0].get('input_parameters'))
def test_default_solution(self): solution = default.DefaultSolution() parameters = { "src_uuid_hypervisor": "server1", "dst_uuid_hypervisor": "server2", } solution.add_action(action_type="nop", resource_id="b199db0c-1408-4d52-b5a5-5ca14de0ff36", input_parameters=parameters) self.assertEqual(len(solution.actions), 1) expected_action_type = "nop" expected_parameters = { "src_uuid_hypervisor": "server1", "dst_uuid_hypervisor": "server2", "resource_id": "b199db0c-1408-4d52-b5a5-5ca14de0ff36" } self.assertEqual(solution.actions[0].get('action_type'), expected_action_type) self.assertEqual(solution.actions[0].get('input_parameters'), expected_parameters)
def test_default_solution(self): solution = default.DefaultSolution( goal=mock.Mock(), strategy=strategies.DummyStrategy(config=mock.Mock())) parameters = { "source_node": "server1", "destination_node": "server2", } solution.add_action(action_type="nop", resource_id="b199db0c-1408-4d52-b5a5-5ca14de0ff36", input_parameters=parameters) self.assertEqual(1, len(solution.actions)) expected_action_type = "nop" expected_parameters = { "source_node": "server1", "destination_node": "server2", "resource_id": "b199db0c-1408-4d52-b5a5-5ca14de0ff36" } self.assertEqual(expected_action_type, solution.actions[0].get('action_type')) self.assertEqual(expected_parameters, solution.actions[0].get('input_parameters')) self.assertEqual('weight', solution.strategy.planner)
def test_schedule_actions_with_unknown_action(self): solution = dsol.DefaultSolution(goal=mock.Mock(), strategy=self.strategy) parameters = { "src_uuid_node": "host1", "dst_uuid_node": "host2", } solution.add_action(action_type="migrate", resource_id="b199db0c-1408-4d52-b5a5-5ca14de0ff36", input_parameters=parameters) solution.add_action(action_type="new_action_type", resource_id="", input_parameters={}) with mock.patch.object( pbase.NodeResourceConsolidationPlanner, "create_action", wraps=self.planner.create_action) as m_create_action: self.assertRaises(exception.UnsupportedActionType, self.planner.schedule, self.context, self.audit.id, solution) self.assertEqual(2, m_create_action.call_count)
def test_schedule_actions(self): solution = dsol.DefaultSolution(goal=mock.Mock(), strategy=self.strategy) parameters = { "source_node": "host1", "destination_node": "host2", } solution.add_action(action_type="migrate", resource_id="b199db0c-1408-4d52-b5a5-5ca14de0ff36", input_parameters=parameters) with mock.patch.object( pbase.NodeResourceConsolidationPlanner, "create_action", wraps=self.planner.create_action) as m_create_action: action_plan = self.planner.schedule(self.context, self.audit.id, solution) self.assertIsNotNone(action_plan.uuid) self.assertEqual(1, m_create_action.call_count) filters = {'action_plan_id': action_plan.id} actions = objects.Action.dbapi.get_action_list(self.context, filters) self.assertEqual("migrate", actions[0].action_type)
def test_schedule_two_actions(self): solution = dsol.DefaultSolution(goal=mock.Mock(), strategy=self.strategy) server1_uuid = "b199db0c-1408-4d52-b5a5-5ca14de0ff36" server2_uuid = "b199db0c-1408-4d52-b5a5-5ca14de0ff37" solution.add_action(action_type="migrate", resource_id=server1_uuid, input_parameters={ "source_node": "host1", "destination_node": "host2", }) solution.add_action(action_type="migrate", resource_id=server2_uuid, input_parameters={ "source_node": "host1", "destination_node": "host3", }) with mock.patch.object( pbase.NodeResourceConsolidationPlanner, "create_action", wraps=self.planner.create_action) as m_create_action: action_plan = self.planner.schedule(self.context, self.audit.id, solution) self.assertIsNotNone(action_plan.uuid) self.assertEqual(2, m_create_action.call_count) # check order filters = {'action_plan_id': action_plan.id} actions = objects.Action.dbapi.get_action_list(self.context, filters) self.assertEqual(server1_uuid, actions[0]['input_parameters'].get('resource_id')) self.assertEqual(server2_uuid, actions[1]['input_parameters'].get('resource_id')) self.assertIn(actions[0]['uuid'], actions[1]['parents'])
def test_schedule_two_actions(self, m_generate_uuid): m_generate_uuid.side_effect = [ "00000000-0000-0000-0000-000000000000", # Action plan "11111111-1111-1111-1111-111111111111", "22222222-2222-2222-2222-222222222222", "33333333-3333-3333-3333-333333333333", "44444444-4444-4444-4444-444444444444", # Migrate 1 "55555555-5555-5555-5555-555555555555", # Nop 1 ] solution = dsol.DefaultSolution(goal=mock.Mock(), strategy=self.strategy) # We create the migrate action before but we then schedule # after the nop action solution.add_action(action_type="migrate", resource_id="DOESNOTMATTER", input_parameters={ "source_node": "server1", "destination_node": "server2" }) solution.add_action(action_type="nop", input_parameters={"message": "Hello world"}) self.planner.config.weights = {'migrate': 3, 'nop': 5} action_plan = self.planner.schedule(self.context, self.audit.id, solution) self.assertIsNotNone(action_plan.uuid) with mock.patch.object(pbase.WeightPlanner, "create_scheduled_actions", wraps=self.planner.create_scheduled_actions ) as m_create_scheduled_actions: action_plan = self.planner.schedule(self.context, self.audit.id, solution) self.assertIsNotNone(action_plan.uuid) self.assertEqual(1, m_create_scheduled_actions.call_count) action_graph = m_create_scheduled_actions.call_args[0][1] expected_edges = \ [({'action_type': 'nop', 'parents': [], 'uuid': '55555555-5555-5555-5555-555555555555'}, {'action_type': 'migrate', 'parents': ['55555555-5555-5555-5555-555555555555'], 'uuid': '44444444-4444-4444-4444-444444444444'})] edges = sorted([(src.as_dict(), dst.as_dict()) for src, dst in action_graph.edges()], key=lambda pair: pair[0]['uuid']) for src, dst in edges: for key in ('id', 'action_plan', 'action_plan_id', 'created_at', 'input_parameters', 'deleted_at', 'updated_at', 'state'): del src[key] del dst[key] self.assertEqual(len(expected_edges), len(edges)) for pair in expected_edges: self.assertIn(pair, edges)
def test_schedule_migrate_resize_acpi_s3_actions(self): solution = dsol.DefaultSolution(goal=mock.Mock(), strategy=self.strategy) parameters = { "source_node": "server1", "destination_node": "server2", } parent_migration = "b199db0c-1408-4d52-b5a5-5ca14de0ff36" solution.add_action(action_type="migrate", resource_id="b199db0c-1408-4d52-b5a5-5ca14de0ff36", input_parameters=parameters) solution.add_action(action_type="resize", resource_id="b199db0c-1408-4d52-b5a5-5ca14de0ff36", input_parameters={'flavor': 'x1'}) solution.add_action(action_type="migrate", resource_id="f6416850-da28-4047-a547-8c49f53e95fe", input_parameters={ "source_node": "server1", "destination_node": "server2" }) solution.add_action(action_type="migrate", resource_id="bb404e74-2caf-447b-bd1e-9234db386ca5", input_parameters={ "source_node": "server2", "destination_node": "server3" }) solution.add_action(action_type="turn_host_to_acpi_s3_state", resource_id="server1", input_parameters={}) with mock.patch.object( pbase.WorkloadStabilizationPlanner, "create_action", wraps=self.planner.create_action) as m_create_action: with mock.patch.object(nova_helper, 'NovaHelper') as m_nova: m_nova().get_hostname.return_value = 'server1' m_nova().get_instance_by_uuid.return_value = ['uuid1'] self.planner.config.weights = { 'turn_host_to_acpi_s3_state': 0, 'resize': 1, 'migrate': 2, 'sleep': 3, 'change_nova_service_state': 4, 'nop': 5 } action_plan = self.planner.schedule(self.context, self.audit.id, solution) self.assertEqual(3, m_nova.call_count) self.assertIsNotNone(action_plan.uuid) self.assertEqual(5, m_create_action.call_count) # check order filters = {'action_plan_id': action_plan.id} actions = objects.Action.dbapi.get_action_list(self.context, filters) self.assertEqual("migrate", actions[0].action_type) self.assertEqual("migrate", actions[1].action_type) self.assertEqual("migrate", actions[2].action_type) self.assertEqual("resize", actions[3].action_type) self.assertEqual("turn_host_to_acpi_s3_state", actions[4].action_type) for action in actions: if action.input_parameters['resource_id'] == parent_migration: parent_migration = action break self.assertEqual(parent_migration.uuid, actions[3].parents[0])
def test_schedule_5_migrate_2_resize_actions_for_2_swimlanes( self, m_generate_uuid): self.planner.config.parallelization["migrate"] = 2 self.planner.config.parallelization["resize"] = 2 m_generate_uuid.side_effect = [ "00000000-0000-0000-0000-000000000000", # Action plan "11111111-1111-1111-1111-111111111111", # Migrate 1 "22222222-2222-2222-2222-222222222222", # Migrate 2 "33333333-3333-3333-3333-333333333333", # Migrate 3 "44444444-4444-4444-4444-444444444444", # Migrate 4 "55555555-5555-5555-5555-555555555555", # Migrate 5 "66666666-6666-6666-6666-666666666666", # Resize 1 "77777777-7777-7777-7777-777777777777", # Resize 2 "88888888-8888-8888-8888-888888888888", # Nop "99999999-9999-9999-9999-999999999999", ] solution = dsol.DefaultSolution(goal=mock.Mock(), strategy=self.strategy) solution.add_action(action_type="migrate", resource_id="DOESNOTMATTER", input_parameters={ "source_node": "server1", "destination_node": "server6" }) solution.add_action(action_type="migrate", resource_id="DOESNOTMATTER", input_parameters={ "source_node": "server2", "destination_node": "server6" }) solution.add_action(action_type="migrate", resource_id="DOESNOTMATTER", input_parameters={ "source_node": "server3", "destination_node": "server6" }) solution.add_action(action_type="migrate", resource_id="DOESNOTMATTER", input_parameters={ "source_node": "server4", "destination_node": "server6" }) solution.add_action(action_type="migrate", resource_id="DOESNOTMATTER", input_parameters={ "source_node": "server5", "destination_node": "server6" }) solution.add_action(action_type="resize", resource_id="DOESNOTMATTER", input_parameters={'flavor': 'x1'}) solution.add_action(action_type="resize", resource_id="DOESNOTMATTER", input_parameters={'flavor': 'x2'}) solution.add_action(action_type="turn_host_to_acpi_s3_state", resource_id="DOESNOTMATTER") with mock.patch.object(pbase.WeightPlanner, "create_scheduled_actions", wraps=self.planner.create_scheduled_actions ) as m_create_scheduled_actions: action_plan = self.planner.schedule(self.context, self.audit.id, solution) self.assertIsNotNone(action_plan.uuid) self.assertEqual(1, m_create_scheduled_actions.call_count) action_graph = m_create_scheduled_actions.call_args[0][0] expected_edges = \ [({'action_type': 'migrate', 'parents': [], 'uuid': '11111111-1111-1111-1111-111111111111'}, {'action_type': 'migrate', 'parents': ['11111111-1111-1111-1111-111111111111', '22222222-2222-2222-2222-222222222222'], 'uuid': '33333333-3333-3333-3333-333333333333'}), ({'action_type': 'migrate', 'parents': [], 'uuid': '11111111-1111-1111-1111-111111111111'}, {'action_type': 'migrate', 'parents': ['11111111-1111-1111-1111-111111111111', '22222222-2222-2222-2222-222222222222'], 'uuid': '44444444-4444-4444-4444-444444444444'}), ({'action_type': 'migrate', 'parents': [], 'uuid': '22222222-2222-2222-2222-222222222222'}, {'action_type': 'migrate', 'parents': ['11111111-1111-1111-1111-111111111111', '22222222-2222-2222-2222-222222222222'], 'uuid': '33333333-3333-3333-3333-333333333333'}), ({'action_type': 'migrate', 'parents': [], 'uuid': '22222222-2222-2222-2222-222222222222'}, {'action_type': 'migrate', 'parents': ['11111111-1111-1111-1111-111111111111', '22222222-2222-2222-2222-222222222222'], 'uuid': '44444444-4444-4444-4444-444444444444'}), ({'action_type': 'migrate', 'parents': ['11111111-1111-1111-1111-111111111111', '22222222-2222-2222-2222-222222222222'], 'uuid': '33333333-3333-3333-3333-333333333333'}, {'action_type': 'migrate', 'parents': ['33333333-3333-3333-3333-333333333333', '44444444-4444-4444-4444-444444444444'], 'uuid': '55555555-5555-5555-5555-555555555555'}), ({'action_type': 'migrate', 'parents': ['11111111-1111-1111-1111-111111111111', '22222222-2222-2222-2222-222222222222'], 'uuid': '44444444-4444-4444-4444-444444444444'}, {'action_type': 'migrate', 'parents': ['33333333-3333-3333-3333-333333333333', '44444444-4444-4444-4444-444444444444'], 'uuid': '55555555-5555-5555-5555-555555555555'}), ({'action_type': 'migrate', 'parents': ['33333333-3333-3333-3333-333333333333', '44444444-4444-4444-4444-444444444444'], 'uuid': '55555555-5555-5555-5555-555555555555'}, {'action_type': 'resize', 'parents': ['55555555-5555-5555-5555-555555555555'], 'uuid': '66666666-6666-6666-6666-666666666666'}), ({'action_type': 'migrate', 'parents': ['33333333-3333-3333-3333-333333333333', '44444444-4444-4444-4444-444444444444'], 'uuid': '55555555-5555-5555-5555-555555555555'}, {'action_type': 'resize', 'parents': ['55555555-5555-5555-5555-555555555555'], 'uuid': '77777777-7777-7777-7777-777777777777'}), ({'action_type': 'resize', 'parents': ['55555555-5555-5555-5555-555555555555'], 'uuid': '66666666-6666-6666-6666-666666666666'}, {'action_type': 'turn_host_to_acpi_s3_state', 'parents': ['66666666-6666-6666-6666-666666666666', '77777777-7777-7777-7777-777777777777'], 'uuid': '88888888-8888-8888-8888-888888888888'}), ({'action_type': 'resize', 'parents': ['55555555-5555-5555-5555-555555555555'], 'uuid': '77777777-7777-7777-7777-777777777777'}, {'action_type': 'turn_host_to_acpi_s3_state', 'parents': ['66666666-6666-6666-6666-666666666666', '77777777-7777-7777-7777-777777777777'], 'uuid': '88888888-8888-8888-8888-888888888888'})] edges = sorted([(src.as_dict(), dst.as_dict()) for src, dst in action_graph.edges()], key=lambda pair: pair[0]['uuid']) for src, dst in edges: for key in ('id', 'action_plan', 'action_plan_id', 'created_at', 'input_parameters', 'deleted_at', 'updated_at', 'state'): del src[key] del dst[key] self.assertEqual(len(expected_edges), len(edges)) for pair in expected_edges: self.assertIn(pair, edges)
def test_schedule_migrate_change_state_actions(self): solution = dsol.DefaultSolution(goal=mock.Mock(), strategy=self.strategy) solution.add_action(action_type="change_nova_service_state", resource_id="b199db0c-1408-4d52-b5a5-5ca14de0ff36", input_parameters={"state": "disabled"}) solution.add_action(action_type="change_nova_service_state", resource_id="b199db0c-1408-4d52-b5a5-5ca14de0ff37", input_parameters={"state": "disabled"}) solution.add_action(action_type="migrate", resource_id="f6416850-da28-4047-a547-8c49f53e95fe", input_parameters={"source_node": "host1"}) solution.add_action(action_type="migrate", resource_id="bb404e74-2caf-447b-bd1e-9234db386ca5", input_parameters={"source_node": "host2"}) solution.add_action(action_type="migrate", resource_id="f6416850-da28-4047-a547-8c49f53e95ff", input_parameters={"source_node": "host1"}) solution.add_action(action_type="change_nova_service_state", resource_id="b199db0c-1408-4d52-b5a5-5ca14de0ff36", input_parameters={"state": "enabled"}) solution.add_action(action_type="change_nova_service_state", resource_id="b199db0c-1408-4d52-b5a5-5ca14de0ff37", input_parameters={"state": "enabled"}) with mock.patch.object( pbase.NodeResourceConsolidationPlanner, "create_action", wraps=self.planner.create_action) as m_create_action: action_plan = self.planner.schedule(self.context, self.audit.id, solution) self.assertIsNotNone(action_plan.uuid) self.assertEqual(7, m_create_action.call_count) # check order filters = {'action_plan_id': action_plan.id} actions = objects.Action.dbapi.get_action_list(self.context, filters) self.assertEqual("change_nova_service_state", actions[0].action_type) self.assertEqual("change_nova_service_state", actions[1].action_type) self.assertEqual("migrate", actions[2].action_type) self.assertEqual("migrate", actions[3].action_type) self.assertEqual("migrate", actions[4].action_type) self.assertEqual("change_nova_service_state", actions[5].action_type) self.assertEqual("change_nova_service_state", actions[6].action_type) action0_uuid = actions[0]['uuid'] action1_uuid = actions[1]['uuid'] action2_uuid = actions[2]['uuid'] action3_uuid = actions[3]['uuid'] action4_uuid = actions[4]['uuid'] action5_uuid = actions[5]['uuid'] action6_uuid = actions[6]['uuid'] # parents of action3,4,5 are action0,1 # resource2 and 4 have the same source, # so action about resource4 depends on # action about resource2 parents = [] for action in actions: if action.parents: parents.extend(action.parents) self.assertIn(action0_uuid, parents) self.assertIn(action1_uuid, parents) self.assertIn(action2_uuid, parents) self.assertIn(action3_uuid, parents) self.assertIn(action4_uuid, parents) self.assertNotIn(action5_uuid, parents) self.assertNotIn(action6_uuid, parents)