From 4cb2b45e3a78f1e6afa88ed12371719cd60e5433 Mon Sep 17 00:00:00 2001 From: suzhengwei Date: Thu, 29 Jun 2017 14:40:49 +0800 Subject: [PATCH] Restrict existing strategies to their default scope Diffrent stratege has diffrent default scope, restrict them to their default scope will avoid usage problems. 1)workload_balancing/thermal_optimization/airflow_optimization goals react on enabled nodes, so restrict default scope to compute nodes with up state and enabled status. 2)server_consolidation goal react on enabled or disabled nodes, So restrict default scope to compute nodes with up state and enabled/disabled status. Change-Id: I7437dee699ee2d3dd227a047196d4d8db811b81e Closes-Bug: #1714002 --- .../strategies/basic_consolidation.py | 12 +++++++++-- .../strategies/outlet_temp_control.py | 9 ++++++++- .../strategy/strategies/uniform_airflow.py | 9 ++++++++- .../strategies/vm_workload_consolidation.py | 20 +++++++++++++------ .../strategy/strategies/workload_balance.py | 9 ++++++++- .../model/data/scenario_1_with_metrics.xml | 4 ++-- 6 files changed, 50 insertions(+), 13 deletions(-) mode change 100755 => 100644 watcher/decision_engine/strategy/strategies/vm_workload_consolidation.py diff --git a/watcher/decision_engine/strategy/strategies/basic_consolidation.py b/watcher/decision_engine/strategy/strategies/basic_consolidation.py index 5618d0f6e..8825a0d3d 100644 --- a/watcher/decision_engine/strategy/strategies/basic_consolidation.py +++ b/watcher/decision_engine/strategy/strategies/basic_consolidation.py @@ -197,6 +197,14 @@ class BasicConsolidation(base.ServerConsolidationBaseStrategy): def gnocchi(self, gnocchi): self._gnocchi = gnocchi + def get_available_compute_nodes(self): + default_node_scope = [element.ServiceState.ENABLED.value, + element.ServiceState.DISABLED.value] + return {uuid: cn for uuid, cn in + self.compute_model.get_all_compute_nodes().items() + if cn.state == element.ServiceState.ONLINE.value and + cn.status in default_node_scope} + def check_migration(self, source_node, destination_node, instance_to_migrate): """Check if the migration is possible @@ -428,7 +436,7 @@ class BasicConsolidation(base.ServerConsolidationBaseStrategy): def compute_score_of_nodes(self): """Calculate score of nodes based on load by VMs""" score = [] - for node in self.compute_model.get_all_compute_nodes().values(): + for node in self.get_available_compute_nodes().values(): if node.status == element.ServiceState.ENABLED.value: self.number_of_enabled_nodes += 1 @@ -502,7 +510,7 @@ class BasicConsolidation(base.ServerConsolidationBaseStrategy): if not self.compute_model: raise exception.ClusterStateNotDefined() - if len(self.compute_model.get_all_compute_nodes()) == 0: + if len(self.get_available_compute_nodes()) == 0: raise exception.ClusterEmpty() if self.compute_model.stale: diff --git a/watcher/decision_engine/strategy/strategies/outlet_temp_control.py b/watcher/decision_engine/strategy/strategies/outlet_temp_control.py index bc657ef98..09b78be6b 100644 --- a/watcher/decision_engine/strategy/strategies/outlet_temp_control.py +++ b/watcher/decision_engine/strategy/strategies/outlet_temp_control.py @@ -171,6 +171,13 @@ class OutletTempControl(base.ThermalOptimizationBaseStrategy): choices=["ceilometer", "gnocchi"]) ] + def get_available_compute_nodes(self): + default_node_scope = [element.ServiceState.ENABLED.value] + return {uuid: cn for uuid, cn in + self.compute_model.get_all_compute_nodes().items() + if cn.state == element.ServiceState.ONLINE.value and + cn.status in default_node_scope} + def calc_used_resource(self, node): """Calculate the used vcpus, memory and disk based on VM flavors""" instances = self.compute_model.get_node_instances(node) @@ -186,7 +193,7 @@ class OutletTempControl(base.ThermalOptimizationBaseStrategy): def group_hosts_by_outlet_temp(self): """Group hosts based on outlet temp meters""" - nodes = self.compute_model.get_all_compute_nodes() + nodes = self.get_available_compute_nodes() size_cluster = len(nodes) if size_cluster == 0: raise wexc.ClusterEmpty() diff --git a/watcher/decision_engine/strategy/strategies/uniform_airflow.py b/watcher/decision_engine/strategy/strategies/uniform_airflow.py index e58b73329..c235923eb 100644 --- a/watcher/decision_engine/strategy/strategies/uniform_airflow.py +++ b/watcher/decision_engine/strategy/strategies/uniform_airflow.py @@ -214,6 +214,13 @@ class UniformAirflow(base.BaseStrategy): choices=["ceilometer", "gnocchi"]) ] + def get_available_compute_nodes(self): + default_node_scope = [element.ServiceState.ENABLED.value] + return {uuid: cn for uuid, cn in + self.compute_model.get_all_compute_nodes().items() + if cn.state == element.ServiceState.ONLINE.value and + cn.status in default_node_scope} + def calculate_used_resource(self, node): """Compute the used vcpus, memory and disk based on instance flavors""" instances = self.compute_model.get_node_instances(node) @@ -334,7 +341,7 @@ class UniformAirflow(base.BaseStrategy): def group_hosts_by_airflow(self): """Group hosts based on airflow meters""" - nodes = self.compute_model.get_all_compute_nodes() + nodes = self.get_available_compute_nodes() if not nodes: raise wexc.ClusterEmpty() overload_hosts = [] diff --git a/watcher/decision_engine/strategy/strategies/vm_workload_consolidation.py b/watcher/decision_engine/strategy/strategies/vm_workload_consolidation.py old mode 100755 new mode 100644 index 681f34d36..bc88aafbf --- a/watcher/decision_engine/strategy/strategies/vm_workload_consolidation.py +++ b/watcher/decision_engine/strategy/strategies/vm_workload_consolidation.py @@ -169,6 +169,14 @@ class VMWorkloadConsolidation(base.ServerConsolidationBaseStrategy): choices=["ceilometer", "gnocchi"]) ] + def get_available_compute_nodes(self): + default_node_scope = [element.ServiceState.ENABLED.value, + element.ServiceState.DISABLED.value] + return {uuid: cn for uuid, cn in + self.compute_model.get_all_compute_nodes().items() + if cn.state == element.ServiceState.ONLINE.value and + cn.status in default_node_scope} + def get_instance_state_str(self, instance): """Get instance state in string format. @@ -273,7 +281,7 @@ class VMWorkloadConsolidation(base.ServerConsolidationBaseStrategy): :return: None """ - for node in self.compute_model.get_all_compute_nodes().values(): + for node in self.get_available_compute_nodes().values(): if (len(self.compute_model.get_node_instances(node)) == 0 and node.status != element.ServiceState.DISABLED.value): @@ -422,7 +430,7 @@ class VMWorkloadConsolidation(base.ServerConsolidationBaseStrategy): RCU is an average of relative utilizations (rhu) of active nodes. :return: {'cpu': <0,1>, 'ram': <0,1>, 'disk': <0,1>} """ - nodes = self.compute_model.get_all_compute_nodes().values() + nodes = self.get_available_compute_nodes().values() rcu = {} counters = {} for node in nodes: @@ -534,7 +542,7 @@ class VMWorkloadConsolidation(base.ServerConsolidationBaseStrategy): :param cc: dictionary containing resource capacity coefficients """ sorted_nodes = sorted( - self.compute_model.get_all_compute_nodes().values(), + self.get_available_compute_nodes().values(), key=lambda x: self.get_node_utilization(x)['cpu']) for node in reversed(sorted_nodes): if self.is_overloaded(node, cc): @@ -567,7 +575,7 @@ class VMWorkloadConsolidation(base.ServerConsolidationBaseStrategy): :param cc: dictionary containing resource capacity coefficients """ sorted_nodes = sorted( - self.compute_model.get_all_compute_nodes().values(), + self.get_available_compute_nodes().values(), key=lambda x: self.get_node_utilization(x)['cpu']) asc = 0 for node in sorted_nodes: @@ -630,7 +638,7 @@ class VMWorkloadConsolidation(base.ServerConsolidationBaseStrategy): rcu_after = self.get_relative_cluster_utilization() info = { "compute_nodes_count": len( - self.compute_model.get_all_compute_nodes()), + self.get_available_compute_nodes()), 'number_of_migrations': self.number_of_migrations, 'number_of_released_nodes': self.number_of_released_nodes, @@ -643,7 +651,7 @@ class VMWorkloadConsolidation(base.ServerConsolidationBaseStrategy): def post_execute(self): self.solution.set_efficacy_indicators( compute_nodes_count=len( - self.compute_model.get_all_compute_nodes()), + self.get_available_compute_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/workload_balance.py b/watcher/decision_engine/strategy/strategies/workload_balance.py index 63e638c8c..0924f2ed7 100644 --- a/watcher/decision_engine/strategy/strategies/workload_balance.py +++ b/watcher/decision_engine/strategy/strategies/workload_balance.py @@ -180,6 +180,13 @@ class WorkloadBalance(base.WorkloadStabilizationBaseStrategy): choices=["ceilometer", "gnocchi"]) ] + def get_available_compute_nodes(self): + default_node_scope = [element.ServiceState.ENABLED.value] + return {uuid: cn for uuid, cn in + self.compute_model.get_all_compute_nodes().items() + if cn.state == element.ServiceState.ONLINE.value and + cn.status in default_node_scope} + def calculate_used_resource(self, node): """Calculate the used vcpus, memory and disk based on VM flavors""" instances = self.compute_model.get_node_instances(node) @@ -271,7 +278,7 @@ class WorkloadBalance(base.WorkloadStabilizationBaseStrategy): and also generate the instance workload map. """ - nodes = self.compute_model.get_all_compute_nodes() + nodes = self.get_available_compute_nodes() cluster_size = len(nodes) if not nodes: raise wexc.ClusterEmpty() diff --git a/watcher/tests/decision_engine/model/data/scenario_1_with_metrics.xml b/watcher/tests/decision_engine/model/data/scenario_1_with_metrics.xml index d8b80afca..17c084c40 100644 --- a/watcher/tests/decision_engine/model/data/scenario_1_with_metrics.xml +++ b/watcher/tests/decision_engine/model/data/scenario_1_with_metrics.xml @@ -1,8 +1,8 @@ - + - +