From 5dee9345654aaaab1aad02574f14aa1fbfa87fce Mon Sep 17 00:00:00 2001 From: junjie huang Date: Thu, 14 Jul 2016 18:11:06 +0000 Subject: [PATCH] use parameters to set the threshold use parameters to set the threshold for strategies of Uniform Airflow,Workload balance. Change-Id: I5a547929eb1e2413468e9a5de16d3fd42cabadf9 Close-bug: #1600707 --- .../strategy/strategies/uniform_airflow.py | 47 ++++++++++++++----- .../strategy/strategies/workload_balance.py | 28 +++++++---- .../strategies/test_uniform_airflow.py | 10 ++++ .../strategies/test_workload_balance.py | 27 ++++------- 4 files changed, 73 insertions(+), 39 deletions(-) diff --git a/watcher/decision_engine/strategy/strategies/uniform_airflow.py b/watcher/decision_engine/strategy/strategies/uniform_airflow.py index 7bda184fd..65c2a0ac6 100644 --- a/watcher/decision_engine/strategy/strategies/uniform_airflow.py +++ b/watcher/decision_engine/strategy/strategies/uniform_airflow.py @@ -60,15 +60,7 @@ class UniformAirflow(base.BaseStrategy): METER_NAME_INLET_T = "hardware.ipmi.node.temperature" # The meter to report system power of physical server in ceilometer METER_NAME_POWER = "hardware.ipmi.node.power" - # TODO(Junjie): make below thresholds configurable - # Unit: 0.1 CFM - THRESHOLD_AIRFLOW = 400.0 - # Unit: degree C - THRESHOLD_INLET_T = 28.0 - # Unit: watts - THRESHOLD_POWER = 350.0 # choose 300 seconds as the default duration of meter aggregation - # TODO(Junjie): make it configurable PERIOD = 300 MIGRATION = "migrate" @@ -83,10 +75,6 @@ class UniformAirflow(base.BaseStrategy): super(UniformAirflow, self).__init__(config, osc) # The migration plan will be triggered when the airflow reaches # threshold - # TODO(Junjie): Threshold should be configurable for each audit - self.threshold_airflow = self.THRESHOLD_AIRFLOW - self.threshold_inlet_t = self.THRESHOLD_INLET_T - self.threshold_power = self.THRESHOLD_POWER self.meter_name_airflow = self.METER_NAME_AIRFLOW self.meter_name_inlet_t = self.METER_NAME_INLET_T self.meter_name_power = self.METER_NAME_POWER @@ -127,6 +115,37 @@ class UniformAirflow(base.BaseStrategy): def get_translatable_goal_display_name(cls): return "Airflow optimization" + @classmethod + def get_schema(cls): + # Mandatory default setting for each element + return { + "properties": { + "threshold_airflow": { + "description": "airflow threshold for migration, Unit is\ + 0.1CFM", + "type": "number", + "default": 400.0 + }, + "threshold_inlet_t": { + "description": "inlet temperature threshold for migration\ + decision", + "type": "number", + "default": 28.0 + }, + "threshold_power": { + "description": "system power threshold for migration\ + decision", + "type": "number", + "default": 350.0 + }, + "period": { + "description": "aggregate time period of ceilometer", + "type": "number", + "default": 300 + }, + }, + } + def calculate_used_resource(self, hypervisor, cap_cores, cap_mem, cap_disk): """Calculate the used vcpus, memory and disk based on VM flavors""" @@ -274,6 +293,10 @@ class UniformAirflow(base.BaseStrategy): raise wexc.ClusterStateNotDefined() def do_execute(self): + self.threshold_airflow = self.input_parameters.threshold_airflow + self.threshold_inlet_t = self.input_parameters.threshold_inlet_t + self.threshold_power = self.input_parameters.threshold_power + self._period = self.input_parameters.period src_hypervisors, target_hypervisors = ( self.group_hosts_by_airflow()) diff --git a/watcher/decision_engine/strategy/strategies/workload_balance.py b/watcher/decision_engine/strategy/strategies/workload_balance.py index 43ac76583..ea8bac5c2 100644 --- a/watcher/decision_engine/strategy/strategies/workload_balance.py +++ b/watcher/decision_engine/strategy/strategies/workload_balance.py @@ -59,11 +59,6 @@ class WorkloadBalance(base.WorkloadStabilizationBaseStrategy): # The meter to report CPU utilization % of VM in ceilometer METER_NAME = "cpu_util" # Unit: %, value range is [0 , 100] - # TODO(Junjie): make it configurable - THRESHOLD = 25.0 - # choose 300 seconds as the default duration of meter aggregation - # TODO(Junjie): make it configurable - PERIOD = 300 MIGRATION = "migrate" @@ -77,11 +72,8 @@ class WorkloadBalance(base.WorkloadStabilizationBaseStrategy): super(WorkloadBalance, self).__init__(config, osc) # the migration plan will be triggered when the CPU utlization % # reaches threshold - # TODO(Junjie): Threshold should be configurable for each audit - self.threshold = self.THRESHOLD self._meter = self.METER_NAME self._ceilometer = None - self._period = self.PERIOD @property def ceilometer(self): @@ -105,6 +97,24 @@ class WorkloadBalance(base.WorkloadStabilizationBaseStrategy): def get_translatable_display_name(cls): return "Workload Balance Migration Strategy" + @classmethod + def get_schema(cls): + # Mandatory default setting for each element + return { + "properties": { + "threshold": { + "description": "workload threshold for migration", + "type": "number", + "default": 25.0 + }, + "period": { + "description": "aggregate time period of ceilometer", + "type": "number", + "default": 300 + }, + }, + } + def calculate_used_resource(self, hypervisor, cap_cores, cap_mem, cap_disk): """Calculate the used vcpus, memory and disk based on VM flavors""" @@ -270,6 +280,8 @@ class WorkloadBalance(base.WorkloadStabilizationBaseStrategy): This phase is where you should put the main logic of your strategy. """ + self.threshold = self.input_parameters.threshold + self._period = self.input_parameters.period src_hypervisors, target_hypervisors, avg_workload, workload_cache = ( self.group_hosts_by_cpu_util()) diff --git a/watcher/tests/decision_engine/strategy/strategies/test_uniform_airflow.py b/watcher/tests/decision_engine/strategy/strategies/test_uniform_airflow.py index bc2d1ab44..c557b71df 100644 --- a/watcher/tests/decision_engine/strategy/strategies/test_uniform_airflow.py +++ b/watcher/tests/decision_engine/strategy/strategies/test_uniform_airflow.py @@ -21,6 +21,7 @@ import mock from watcher.applier.loading import default from watcher.common import exception +from watcher.common import utils from watcher.decision_engine.model import model_root from watcher.decision_engine.model import resource from watcher.decision_engine.strategy import strategies @@ -56,6 +57,15 @@ class TestUniformAirflow(base.BaseTestCase): self.m_ceilometer.return_value = mock.Mock( statistic_aggregation=self.fake_metrics.mock_get_statistics) self.strategy = strategies.UniformAirflow(config=mock.Mock()) + self.strategy.input_parameters = utils.Struct() + self.strategy.input_parameters.update({'threshold_airflow': 400.0, + 'threshold_inlet_t': 28.0, + 'threshold_power': 350.0, + 'period': 300}) + self.strategy.threshold_airflow = 400 + self.strategy.threshold_inlet_t = 28 + self.strategy.threshold_power = 350 + self._period = 300 def test_calc_used_res(self): model = self.fake_cluster.generate_scenario_7_with_2_hypervisors() diff --git a/watcher/tests/decision_engine/strategy/strategies/test_workload_balance.py b/watcher/tests/decision_engine/strategy/strategies/test_workload_balance.py index 96a3fb535..114a70834 100644 --- a/watcher/tests/decision_engine/strategy/strategies/test_workload_balance.py +++ b/watcher/tests/decision_engine/strategy/strategies/test_workload_balance.py @@ -21,6 +21,7 @@ import mock from watcher.applier.loading import default from watcher.common import exception +from watcher.common import utils from watcher.decision_engine.model import model_root from watcher.decision_engine.model import resource from watcher.decision_engine.strategy import strategies @@ -47,15 +48,20 @@ class TestWorkloadBalance(base.BaseTestCase): self.addCleanup(p_model.stop) p_ceilometer = mock.patch.object( - strategies.BasicConsolidation, "ceilometer", + strategies.WorkloadBalance, "ceilometer", new_callable=mock.PropertyMock) self.m_ceilometer = p_ceilometer.start() self.addCleanup(p_ceilometer.stop) self.m_model.return_value = model_root.ModelRoot() self.m_ceilometer.return_value = mock.Mock( - statistic_aggregation=self.fake_metrics.mock_get_statistics) + statistic_aggregation=self.fake_metrics.mock_get_statistics_wb) self.strategy = strategies.WorkloadBalance(config=mock.Mock()) + self.strategy.input_parameters = utils.Struct() + self.strategy.input_parameters.update({'threshold': 25.0, + 'period': 300}) + self.strategy.threshold = 25.0 + self.strategy._period = 300 def test_calc_used_res(self): model = self.fake_cluster.generate_scenario_6_with_2_hypervisors() @@ -74,10 +80,7 @@ class TestWorkloadBalance(base.BaseTestCase): model = self.fake_cluster.generate_scenario_6_with_2_hypervisors() self.m_model.return_value = model self.strategy.threshold = 30 - self.strategy.ceilometer = mock.MagicMock( - statistic_aggregation=self.fake_metrics.mock_get_statistics_wb) h1, h2, avg, w_map = self.strategy.group_hosts_by_cpu_util() - # print h1, h2, avg, w_map self.assertEqual(h1[0]['hv'].uuid, 'Node_0') self.assertEqual(h2[0]['hv'].uuid, 'Node_1') self.assertEqual(avg, 8.0) @@ -85,8 +88,6 @@ class TestWorkloadBalance(base.BaseTestCase): def test_choose_vm_to_migrate(self): model = self.fake_cluster.generate_scenario_6_with_2_hypervisors() self.m_model.return_value = model - self.strategy.ceilometer = mock.MagicMock( - statistic_aggregation=self.fake_metrics.mock_get_statistics_wb) h1, h2, avg, w_map = self.strategy.group_hosts_by_cpu_util() vm_to_mig = self.strategy.choose_vm_to_migrate(h1, avg, w_map) self.assertEqual(vm_to_mig[0].uuid, 'Node_0') @@ -96,8 +97,6 @@ class TestWorkloadBalance(base.BaseTestCase): def test_choose_vm_notfound(self): model = self.fake_cluster.generate_scenario_6_with_2_hypervisors() self.m_model.return_value = model - self.strategy.ceilometer = mock.MagicMock( - statistic_aggregation=self.fake_metrics.mock_get_statistics_wb) h1, h2, avg, w_map = self.strategy.group_hosts_by_cpu_util() vms = model.get_all_vms() vms.clear() @@ -107,8 +106,6 @@ class TestWorkloadBalance(base.BaseTestCase): def test_filter_destination_hosts(self): model = self.fake_cluster.generate_scenario_6_with_2_hypervisors() self.m_model.return_value = model - self.strategy.ceilometer = mock.MagicMock( - statistic_aggregation=self.fake_metrics.mock_get_statistics_wb) h1, h2, avg, w_map = self.strategy.group_hosts_by_cpu_util() vm_to_mig = self.strategy.choose_vm_to_migrate(h1, avg, w_map) dest_hosts = self.strategy.filter_destination_hosts( @@ -129,23 +126,17 @@ class TestWorkloadBalance(base.BaseTestCase): def test_execute_cluster_empty(self): model = model_root.ModelRoot() self.m_model.return_value = model - self.strategy.ceilometer = mock.MagicMock( - statistic_aggregation=self.fake_metrics.mock_get_statistics_wb) self.assertRaises(exception.ClusterEmpty, self.strategy.execute) def test_execute_no_workload(self): model = self.fake_cluster.generate_scenario_4_with_1_hypervisor_no_vm() self.m_model.return_value = model - self.strategy.ceilometer = mock.MagicMock( - statistic_aggregation=self.fake_metrics.mock_get_statistics_wb) solution = self.strategy.execute() self.assertEqual([], solution.actions) def test_execute(self): model = self.fake_cluster.generate_scenario_6_with_2_hypervisors() self.m_model.return_value = model - self.strategy.ceilometer = mock.MagicMock( - statistic_aggregation=self.fake_metrics.mock_get_statistics_wb) solution = self.strategy.execute() actions_counter = collections.Counter( [action.get('action_type') for action in solution.actions]) @@ -156,8 +147,6 @@ class TestWorkloadBalance(base.BaseTestCase): def test_check_parameters(self): model = self.fake_cluster.generate_scenario_6_with_2_hypervisors() self.m_model.return_value = model - self.strategy.ceilometer = mock.MagicMock( - statistic_aggregation=self.fake_metrics.mock_get_statistics_wb) solution = self.strategy.execute() loader = default.DefaultActionLoader() for action in solution.actions: