Example #1
0
    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
Example #2
0
    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)
Example #4
0
    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)
Example #5
0
    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)
Example #7
0
    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])
Example #8
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)
Example #11
0
 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'))
Example #12
0
 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)
Example #13
0
 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)
Example #14
0
    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)
Example #15
0
    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)
Example #16
0
    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)
Example #18
0
    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])
Example #19
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)
Example #20
0
    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)