From 35066dfe60e078b1dc6ee5dc37e43d8f30e6a277 Mon Sep 17 00:00:00 2001 From: David TARDIVEL Date: Mon, 9 Jan 2017 13:58:04 +0100 Subject: [PATCH] Update Server Consolidation global efficacy As instance migration cost is petty compared to the cost of compute node release, I update the way to compute the global efficacy for a server consolidation goal. The new formula is simplest and it's only based on compute node. Change-Id: Ibcce31a85af70429f412c96c584a761d681366a2 --- .../goal/efficacy/indicators.py | 14 ++++++++++ .../decision_engine/goal/efficacy/specs.py | 7 +++-- .../strategies/basic_consolidation.py | 28 +++++-------------- .../strategies/vm_workload_consolidation.py | 4 +++ .../strategies/test_basic_consolidation.py | 5 +--- 5 files changed, 30 insertions(+), 28 deletions(-) diff --git a/watcher/decision_engine/goal/efficacy/indicators.py b/watcher/decision_engine/goal/efficacy/indicators.py index b4548bfd7..1b2426291 100644 --- a/watcher/decision_engine/goal/efficacy/indicators.py +++ b/watcher/decision_engine/goal/efficacy/indicators.py @@ -104,6 +104,20 @@ class MigrationEfficacy(IndicatorSpecification): voluptuous.Range(min=0, max=100), required=True) +class ComputeNodesCount(IndicatorSpecification): + def __init__(self): + super(ComputeNodesCount, self).__init__( + name="compute_nodes_count", + description=_("The total number of enabled compute nodes."), + unit=None, + ) + + @property + def schema(self): + return voluptuous.Schema( + voluptuous.Range(min=0), required=True) + + class ReleasedComputeNodesCount(IndicatorSpecification): def __init__(self): super(ReleasedComputeNodesCount, self).__init__( diff --git a/watcher/decision_engine/goal/efficacy/specs.py b/watcher/decision_engine/goal/efficacy/specs.py index 818099c9b..474459ebd 100644 --- a/watcher/decision_engine/goal/efficacy/specs.py +++ b/watcher/decision_engine/goal/efficacy/specs.py @@ -33,20 +33,21 @@ class ServerConsolidation(base.EfficacySpecification): def get_indicators_specifications(self): return [ + indicators.ComputeNodesCount(), indicators.ReleasedComputeNodesCount(), indicators.InstanceMigrationsCount(), ] def get_global_efficacy_indicator(self, indicators_map=None): value = 0 - if indicators_map and indicators_map.instance_migrations_count > 0: + if indicators_map and indicators_map.compute_nodes_count > 0: value = (float(indicators_map.released_compute_nodes_count) / - float(indicators_map.instance_migrations_count)) * 100 + float(indicators_map.compute_nodes_count)) * 100 return efficacy.Indicator( name="released_nodes_ratio", description=_("Ratio of released compute nodes divided by the " - "number of VM migrations."), + "total number of enabled compute nodes."), unit='%', value=value, ) diff --git a/watcher/decision_engine/strategy/strategies/basic_consolidation.py b/watcher/decision_engine/strategy/strategies/basic_consolidation.py index 98f1a4d85..d0a70771c 100644 --- a/watcher/decision_engine/strategy/strategies/basic_consolidation.py +++ b/watcher/decision_engine/strategy/strategies/basic_consolidation.py @@ -75,6 +75,8 @@ class BasicConsolidation(base.ServerConsolidationBaseStrategy): """ super(BasicConsolidation, self).__init__(config, osc) + # set default value for the number of enabled compute nodes + self.number_of_enabled_nodes = 0 # set default value for the number of released nodes self.number_of_released_nodes = 0 # set default value for the number of migrations @@ -337,18 +339,6 @@ class BasicConsolidation(base.ServerConsolidationBaseStrategy): return self.calculate_weight(node, total_cores_used, 0, 0) - def calculate_migration_efficacy(self): - """Calculate migration efficacy - - :return: The efficacy tells us that every instance migration resulted - in releasing on node - """ - if self.number_of_migrations > 0: - return (float(self.number_of_released_nodes) / float( - self.number_of_migrations)) * 100 - else: - return 0 - def calculate_score_instance(self, instance): """Calculate Score of virtual machine @@ -394,6 +384,9 @@ class BasicConsolidation(base.ServerConsolidationBaseStrategy): """Calculate score of nodes based on load by VMs""" score = [] for node in self.compute_model.get_all_compute_nodes().values(): + if node.status == element.ServiceState.ENABLED.value: + self.number_of_enabled_nodes += 1 + count = self.compute_model.mapping.get_node_instances(node) if len(count) > 0: result = self.calculate_score_node(node) @@ -481,15 +474,6 @@ class BasicConsolidation(base.ServerConsolidationBaseStrategy): def do_execute(self): unsuccessful_migration = 0 - for node_uuid, node in self.compute_model.get_all_compute_nodes( - ).items(): - node_instances = self.compute_model.mapping.get_node_instances( - node) - if node_instances: - if node.state == element.ServiceState.ENABLED: - self.add_change_service_state( - node_uuid, element.ServiceState.DISABLED.value) - scores = self.compute_score_of_nodes() # Sort compute nodes by Score decreasing sorted_scores = sorted(scores, reverse=True, key=lambda x: (x[1])) @@ -526,6 +510,7 @@ class BasicConsolidation(base.ServerConsolidationBaseStrategy): sorted_scores.pop() infos = { + "compute_nodes_count": self.number_of_enabled_nodes, "released_compute_nodes_count": self.number_of_released_nodes, "instance_migrations_count": self.number_of_migrations, "efficacy": self.efficacy @@ -534,6 +519,7 @@ class BasicConsolidation(base.ServerConsolidationBaseStrategy): def post_execute(self): self.solution.set_efficacy_indicators( + compute_nodes_count=self.number_of_enabled_nodes, released_compute_nodes_count=self.number_of_released_nodes, instance_migrations_count=self.number_of_migrations, ) diff --git a/watcher/decision_engine/strategy/strategies/vm_workload_consolidation.py b/watcher/decision_engine/strategy/strategies/vm_workload_consolidation.py index c96ab9115..aa9583d9b 100644 --- a/watcher/decision_engine/strategy/strategies/vm_workload_consolidation.py +++ b/watcher/decision_engine/strategy/strategies/vm_workload_consolidation.py @@ -526,6 +526,8 @@ class VMWorkloadConsolidation(base.ServerConsolidationBaseStrategy): rcu_after = self.get_relative_cluster_utilization(model) info = { + "compute_nodes_count": len( + self.compute_model.get_all_compute_nodes()), 'number_of_migrations': self.number_of_migrations, 'number_of_released_nodes': self.number_of_released_nodes, @@ -537,6 +539,8 @@ class VMWorkloadConsolidation(base.ServerConsolidationBaseStrategy): def post_execute(self): self.solution.set_efficacy_indicators( + compute_nodes_count=len( + self.compute_model.get_all_compute_nodes()), released_compute_nodes_count=self.number_of_released_nodes, instance_migrations_count=self.number_of_migrations, ) diff --git a/watcher/tests/decision_engine/strategy/strategies/test_basic_consolidation.py b/watcher/tests/decision_engine/strategy/strategies/test_basic_consolidation.py index ebc464b6b..870a6f997 100644 --- a/watcher/tests/decision_engine/strategy/strategies/test_basic_consolidation.py +++ b/watcher/tests/decision_engine/strategy/strategies/test_basic_consolidation.py @@ -153,9 +153,6 @@ class TestBasicConsolidation(base.TestCase): instance_0_weight_assert, self.strategy.calculate_weight(instance_0, cores, disk, mem)) - def test_calculate_migration_efficacy(self): - self.strategy.calculate_migration_efficacy() - def test_exception_model(self): self.m_model.return_value = None self.assertRaises( @@ -224,7 +221,7 @@ class TestBasicConsolidation(base.TestCase): expected_num_migrations = 5 expected_power_state = 3 - expected_global_efficacy = 60 + expected_global_efficacy = 75 num_migrations = actions_counter.get("migrate", 0) num_node_state_change = actions_counter.get(