From 377889859d8c471897d286b1ce710bec85f1d657 Mon Sep 17 00:00:00 2001 From: Santhosh Fernandes Date: Fri, 10 Mar 2017 22:58:46 +0530 Subject: [PATCH] Add period input parameter to vm workload consolidation and outlet temp control strategy. Closes-Bug: #1614021 Change-Id: Iec975e4a4a39168a65ae89ca75a5ca9445c14f9d --- doc/source/strategies/outlet_temp_control.rst | 3 ++ .../strategies/vm_workload_consolidation.rst | 14 ++++++++ .../strategies/outlet_temp_control.py | 12 ++++++- .../strategies/vm_workload_consolidation.py | 35 +++++++++++++------ .../model/ceilometer_metrics.py | 2 +- .../strategies/test_outlet_temp_control.py | 18 ++++++++++ .../test_vm_workload_consolidation.py | 15 ++++++++ 7 files changed, 87 insertions(+), 12 deletions(-) diff --git a/doc/source/strategies/outlet_temp_control.rst b/doc/source/strategies/outlet_temp_control.rst index 612f89b91..cbd4a4183 100644 --- a/doc/source/strategies/outlet_temp_control.rst +++ b/doc/source/strategies/outlet_temp_control.rst @@ -72,6 +72,9 @@ Strategy parameter is: parameter type default Value description ============== ====== ============= ==================================== ``threshold`` Number 35.0 Temperature threshold for migration +``period`` Number 30 The time interval in seconds for + getting statistic aggregation from + metric data source ============== ====== ============= ==================================== Efficacy Indicator diff --git a/doc/source/strategies/vm_workload_consolidation.rst b/doc/source/strategies/vm_workload_consolidation.rst index d7dcd8714..b0dc0d6fc 100644 --- a/doc/source/strategies/vm_workload_consolidation.rst +++ b/doc/source/strategies/vm_workload_consolidation.rst @@ -70,6 +70,20 @@ Default Watcher's planner: .. watcher-term:: watcher.decision_engine.planner.default.DefaultPlanner +Configuration +------------- + +Strategy parameter is: + +====================== ====== ============= =================================== +parameter type default Value description +====================== ====== ============= =================================== +``period`` Number 3600 The time interval in seconds + for getting statistic aggregation + from metric data source +====================== ====== ============= =================================== + + Efficacy Indicator ------------------ diff --git a/watcher/decision_engine/strategy/strategies/outlet_temp_control.py b/watcher/decision_engine/strategy/strategies/outlet_temp_control.py index c260e462c..fa55150a8 100644 --- a/watcher/decision_engine/strategy/strategies/outlet_temp_control.py +++ b/watcher/decision_engine/strategy/strategies/outlet_temp_control.py @@ -98,6 +98,10 @@ class OutletTempControl(base.ThermalOptimizationBaseStrategy): def get_translatable_display_name(cls): return "Outlet temperature based strategy" + @property + def period(self): + return self.input_parameters.get('period', 30) + @classmethod def get_schema(cls): # Mandatory default setting for each element @@ -108,6 +112,12 @@ class OutletTempControl(base.ThermalOptimizationBaseStrategy): "type": "number", "default": 35.0 }, + "period": { + "description": "The time interval in seconds for " + "getting statistic aggregation", + "type": "number", + "default": 30 + }, }, } @@ -149,7 +159,7 @@ class OutletTempControl(base.ThermalOptimizationBaseStrategy): outlet_temp = self.ceilometer.statistic_aggregation( resource_id=resource_id, meter_name=self._meter, - period="30", + period=self.period, aggregate='avg') # some hosts may not have outlet temp meters, remove from target if outlet_temp is None: diff --git a/watcher/decision_engine/strategy/strategies/vm_workload_consolidation.py b/watcher/decision_engine/strategy/strategies/vm_workload_consolidation.py index 0270c87ff..dcd9fbaa7 100644 --- a/watcher/decision_engine/strategy/strategies/vm_workload_consolidation.py +++ b/watcher/decision_engine/strategy/strategies/vm_workload_consolidation.py @@ -87,6 +87,10 @@ class VMWorkloadConsolidation(base.ServerConsolidationBaseStrategy): def get_translatable_display_name(cls): return "VM Workload Consolidation Strategy" + @property + def period(self): + return self.input_parameters.get('period', 3600) + @property def ceilometer(self): if self._ceilometer is None: @@ -97,6 +101,20 @@ class VMWorkloadConsolidation(base.ServerConsolidationBaseStrategy): def ceilometer(self, ceilometer): self._ceilometer = ceilometer + @classmethod + def get_schema(cls): + # Mandatory default setting for each element + return { + "properties": { + "period": { + "description": "The time interval in seconds for " + "getting statistic aggregation", + "type": "number", + "default": 3600 + } + } + } + def get_state_str(self, state): """Get resource state in string format. @@ -187,12 +205,10 @@ class VMWorkloadConsolidation(base.ServerConsolidationBaseStrategy): element.ServiceState.DISABLED.value): self.add_action_disable_node(node) - def get_instance_utilization(self, instance, - period=3600, aggr='avg'): + def get_instance_utilization(self, instance, aggr='avg'): """Collect cpu, ram and disk utilization statistics of a VM. :param instance: instance object - :param period: seconds :param aggr: string :return: dict(cpu(number of vcpus used), ram(MB used), disk(B used)) """ @@ -206,7 +222,7 @@ class VMWorkloadConsolidation(base.ServerConsolidationBaseStrategy): disk_alloc_metric = 'disk.root.size' instance_cpu_util = self.ceilometer.statistic_aggregation( resource_id=instance.uuid, meter_name=cpu_util_metric, - period=period, aggregate=aggr) + period=self.period, aggregate=aggr) if instance_cpu_util: total_cpu_utilization = ( @@ -216,16 +232,16 @@ class VMWorkloadConsolidation(base.ServerConsolidationBaseStrategy): instance_ram_util = self.ceilometer.statistic_aggregation( resource_id=instance.uuid, meter_name=ram_util_metric, - period=period, aggregate=aggr) + period=self.period, aggregate=aggr) if not instance_ram_util: instance_ram_util = self.ceilometer.statistic_aggregation( resource_id=instance.uuid, meter_name=ram_alloc_metric, - period=period, aggregate=aggr) + period=self.period, aggregate=aggr) instance_disk_util = self.ceilometer.statistic_aggregation( resource_id=instance.uuid, meter_name=disk_alloc_metric, - period=period, aggregate=aggr) + period=self.period, aggregate=aggr) if not instance_ram_util or not instance_disk_util: LOG.error( @@ -238,11 +254,10 @@ class VMWorkloadConsolidation(base.ServerConsolidationBaseStrategy): disk=instance_disk_util) return self.ceilometer_instance_data_cache.get(instance.uuid) - def get_node_utilization(self, node, period=3600, aggr='avg'): + def get_node_utilization(self, node, aggr='avg'): """Collect cpu, ram and disk utilization statistics of a node. :param node: node object - :param period: seconds :param aggr: string :return: dict(cpu(number of cores used), ram(MB used), disk(B used)) """ @@ -252,7 +267,7 @@ class VMWorkloadConsolidation(base.ServerConsolidationBaseStrategy): node_cpu_util = 0 for instance in node_instances: instance_util = self.get_instance_utilization( - instance, period, aggr) + instance, aggr) node_cpu_util += instance_util['cpu'] node_ram_util += instance_util['ram'] node_disk_util += instance_util['disk'] diff --git a/watcher/tests/decision_engine/model/ceilometer_metrics.py b/watcher/tests/decision_engine/model/ceilometer_metrics.py index e767d1ce6..c8834ea2f 100644 --- a/watcher/tests/decision_engine/model/ceilometer_metrics.py +++ b/watcher/tests/decision_engine/model/ceilometer_metrics.py @@ -65,7 +65,7 @@ class FakeCeilometerMetrics(object): mock['Node_1'] = 100 if uuid not in mock.keys(): mock[uuid] = 100 - return mock[str(uuid)] + return float(mock[str(uuid)]) @staticmethod def get_usage_node_ram(uuid): diff --git a/watcher/tests/decision_engine/strategy/strategies/test_outlet_temp_control.py b/watcher/tests/decision_engine/strategy/strategies/test_outlet_temp_control.py index a3e31adf4..52cecfe6d 100644 --- a/watcher/tests/decision_engine/strategy/strategies/test_outlet_temp_control.py +++ b/watcher/tests/decision_engine/strategy/strategies/test_outlet_temp_control.py @@ -151,3 +151,21 @@ class TestOutletTempControl(base.TestCase): loaded_action = loader.load(action['action_type']) loaded_action.input_parameters = action['input_parameters'] loaded_action.validate_parameters() + + def test_periods(self): + model = self.fake_cluster.generate_scenario_3_with_2_nodes() + self.m_model.return_value = model + p_ceilometer = mock.patch.object( + strategies.OutletTempControl, "ceilometer") + m_ceilometer = p_ceilometer.start() + self.addCleanup(p_ceilometer.stop) + m_ceilometer.statistic_aggregation = mock.Mock( + side_effect=self.fake_metrics.mock_get_statistics) + node = model.get_node_by_uuid('Node_0') + self.strategy.input_parameters.update({'threshold': 35.0}) + self.strategy.threshold = 35.0 + self.strategy.group_hosts_by_outlet_temp() + m_ceilometer.statistic_aggregation.assert_any_call( + aggregate='avg', + meter_name='hardware.ipmi.node.outlet_temperature', + period=30, resource_id=node.uuid) diff --git a/watcher/tests/decision_engine/strategy/strategies/test_vm_workload_consolidation.py b/watcher/tests/decision_engine/strategy/strategies/test_vm_workload_consolidation.py index 95c79ca3b..872ed8f2c 100644 --- a/watcher/tests/decision_engine/strategy/strategies/test_vm_workload_consolidation.py +++ b/watcher/tests/decision_engine/strategy/strategies/test_vm_workload_consolidation.py @@ -293,3 +293,18 @@ class TestVMWorkloadConsolidation(base.TestCase): del expected[3] del expected[1] self.assertEqual(expected, self.strategy.solution.actions) + + def test_periods(self): + model = self.fake_cluster.generate_scenario_1() + self.m_model.return_value = model + p_ceilometer = mock.patch.object( + strategies.VMWorkloadConsolidation, "ceilometer") + m_ceilometer = p_ceilometer.start() + self.addCleanup(p_ceilometer.stop) + m_ceilometer.return_value = mock.Mock( + statistic_aggregation=self.fake_metrics.mock_get_statistics) + instance0 = model.get_instance_by_uuid("INSTANCE_0") + self.strategy.get_instance_utilization(instance0) + m_ceilometer.statistic_aggregation.assert_any_call( + aggregate='avg', meter_name='disk.root.size', + period=3600, resource_id=instance0.uuid)