Merge "Add efficacy indicators for workload_stabilization strategy"
This commit is contained in:
@@ -72,7 +72,8 @@ class EfficacySpecification(object):
|
|||||||
}
|
}
|
||||||
for indicator in self.indicators_specs:
|
for indicator in self.indicators_specs:
|
||||||
schema["properties"][indicator.name] = indicator.schema
|
schema["properties"][indicator.name] = indicator.schema
|
||||||
schema["required"].append(indicator.name)
|
if indicator.required:
|
||||||
|
schema["required"].append(indicator.name)
|
||||||
return schema
|
return schema
|
||||||
|
|
||||||
def validate_efficacy_indicators(self, indicators_map):
|
def validate_efficacy_indicators(self, indicators_map):
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ class ComputeNodesCount(IndicatorSpecification):
|
|||||||
return {
|
return {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"minimum": 0
|
"minimum": 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ReleasedComputeNodesCount(IndicatorSpecification):
|
class ReleasedComputeNodesCount(IndicatorSpecification):
|
||||||
@@ -106,7 +106,25 @@ class ReleasedComputeNodesCount(IndicatorSpecification):
|
|||||||
return {
|
return {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"minimum": 0
|
"minimum": 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class InstancesCount(IndicatorSpecification):
|
||||||
|
def __init__(self):
|
||||||
|
super(InstancesCount, self).__init__(
|
||||||
|
name="instances_count",
|
||||||
|
description=_("The total number of audited instances in "
|
||||||
|
"strategy."),
|
||||||
|
unit=None,
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def schema(self):
|
||||||
|
return {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class InstanceMigrationsCount(IndicatorSpecification):
|
class InstanceMigrationsCount(IndicatorSpecification):
|
||||||
@@ -122,7 +140,7 @@ class InstanceMigrationsCount(IndicatorSpecification):
|
|||||||
return {
|
return {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"minimum": 0
|
"minimum": 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class LiveInstanceMigrateCount(IndicatorSpecification):
|
class LiveInstanceMigrateCount(IndicatorSpecification):
|
||||||
@@ -138,7 +156,7 @@ class LiveInstanceMigrateCount(IndicatorSpecification):
|
|||||||
return {
|
return {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"minimum": 0
|
"minimum": 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PlannedLiveInstanceMigrateCount(IndicatorSpecification):
|
class PlannedLiveInstanceMigrateCount(IndicatorSpecification):
|
||||||
@@ -154,7 +172,7 @@ class PlannedLiveInstanceMigrateCount(IndicatorSpecification):
|
|||||||
return {
|
return {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"minimum": 0
|
"minimum": 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ColdInstanceMigrateCount(IndicatorSpecification):
|
class ColdInstanceMigrateCount(IndicatorSpecification):
|
||||||
@@ -170,7 +188,7 @@ class ColdInstanceMigrateCount(IndicatorSpecification):
|
|||||||
return {
|
return {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"minimum": 0
|
"minimum": 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PlannedColdInstanceMigrateCount(IndicatorSpecification):
|
class PlannedColdInstanceMigrateCount(IndicatorSpecification):
|
||||||
@@ -186,7 +204,7 @@ class PlannedColdInstanceMigrateCount(IndicatorSpecification):
|
|||||||
return {
|
return {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"minimum": 0
|
"minimum": 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class VolumeMigrateCount(IndicatorSpecification):
|
class VolumeMigrateCount(IndicatorSpecification):
|
||||||
@@ -202,7 +220,7 @@ class VolumeMigrateCount(IndicatorSpecification):
|
|||||||
return {
|
return {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"minimum": 0
|
"minimum": 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PlannedVolumeMigrateCount(IndicatorSpecification):
|
class PlannedVolumeMigrateCount(IndicatorSpecification):
|
||||||
@@ -219,7 +237,7 @@ class PlannedVolumeMigrateCount(IndicatorSpecification):
|
|||||||
return {
|
return {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"minimum": 0
|
"minimum": 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class VolumeUpdateCount(IndicatorSpecification):
|
class VolumeUpdateCount(IndicatorSpecification):
|
||||||
@@ -236,7 +254,7 @@ class VolumeUpdateCount(IndicatorSpecification):
|
|||||||
return {
|
return {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"minimum": 0
|
"minimum": 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PlannedVolumeUpdateCount(IndicatorSpecification):
|
class PlannedVolumeUpdateCount(IndicatorSpecification):
|
||||||
@@ -253,4 +271,38 @@ class PlannedVolumeUpdateCount(IndicatorSpecification):
|
|||||||
return {
|
return {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"minimum": 0
|
"minimum": 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class StandardDeviationValue(IndicatorSpecification):
|
||||||
|
def __init__(self):
|
||||||
|
super(StandardDeviationValue, self).__init__(
|
||||||
|
name="standard_deviation_after_audit",
|
||||||
|
description=_("The value of resulted standard deviation."),
|
||||||
|
unit=None,
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def schema(self):
|
||||||
|
return {
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class OriginalStandardDeviationValue(IndicatorSpecification):
|
||||||
|
def __init__(self):
|
||||||
|
super(OriginalStandardDeviationValue, self).__init__(
|
||||||
|
name="standard_deviation_before_audit",
|
||||||
|
description=_("The value of original standard deviation."),
|
||||||
|
unit=None,
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def schema(self):
|
||||||
|
return {
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 0
|
||||||
|
}
|
||||||
|
|||||||
@@ -55,6 +55,32 @@ class ServerConsolidation(base.EfficacySpecification):
|
|||||||
return global_efficacy
|
return global_efficacy
|
||||||
|
|
||||||
|
|
||||||
|
class WorkloadBalancing(base.EfficacySpecification):
|
||||||
|
|
||||||
|
def get_indicators_specifications(self):
|
||||||
|
return [
|
||||||
|
indicators.InstanceMigrationsCount(),
|
||||||
|
indicators.InstancesCount(),
|
||||||
|
indicators.StandardDeviationValue(),
|
||||||
|
indicators.OriginalStandardDeviationValue()
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_global_efficacy_indicator(self, indicators_map=None):
|
||||||
|
gl_indicators = []
|
||||||
|
mig_value = 0
|
||||||
|
if indicators_map and indicators_map.instance_migrations_count > 0:
|
||||||
|
mig_value = (
|
||||||
|
indicators_map.instance_migrations_count /
|
||||||
|
float(indicators_map.instances_count) * 100)
|
||||||
|
gl_indicators.append(efficacy.Indicator(
|
||||||
|
name="live_migrations_count",
|
||||||
|
description=_("Ratio of migrated virtual machines to audited "
|
||||||
|
"virtual machines"),
|
||||||
|
unit='%',
|
||||||
|
value=mig_value))
|
||||||
|
return gl_indicators
|
||||||
|
|
||||||
|
|
||||||
class HardwareMaintenance(base.EfficacySpecification):
|
class HardwareMaintenance(base.EfficacySpecification):
|
||||||
|
|
||||||
def get_indicators_specifications(self):
|
def get_indicators_specifications(self):
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ class WorkloadBalancing(base.Goal):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def get_efficacy_specification(cls):
|
def get_efficacy_specification(cls):
|
||||||
"""The efficacy spec for the current goal"""
|
"""The efficacy spec for the current goal"""
|
||||||
return specs.Unclassified()
|
return specs.WorkloadBalancing()
|
||||||
|
|
||||||
|
|
||||||
class AirflowOptimization(base.Goal):
|
class AirflowOptimization(base.Goal):
|
||||||
|
|||||||
@@ -399,4 +399,7 @@ class StorageCapacityBalance(base.WorkloadStabilizationBaseStrategy):
|
|||||||
"""Post-execution phase
|
"""Post-execution phase
|
||||||
|
|
||||||
"""
|
"""
|
||||||
pass
|
self.solution.set_efficacy_indicators(
|
||||||
|
instance_migrations_count=0,
|
||||||
|
instances_count=0,
|
||||||
|
)
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ class WorkloadBalance(base.WorkloadStabilizationBaseStrategy):
|
|||||||
# the migration plan will be triggered when the CPU or RAM
|
# the migration plan will be triggered when the CPU or RAM
|
||||||
# utilization % reaches threshold
|
# utilization % reaches threshold
|
||||||
self._meter = None
|
self._meter = None
|
||||||
|
self.instance_migrations_count = 0
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_name(cls):
|
def get_name(cls):
|
||||||
@@ -377,6 +378,7 @@ class WorkloadBalance(base.WorkloadStabilizationBaseStrategy):
|
|||||||
self.solution.add_action(action_type=self.MIGRATION,
|
self.solution.add_action(action_type=self.MIGRATION,
|
||||||
resource_id=instance_src.uuid,
|
resource_id=instance_src.uuid,
|
||||||
input_parameters=parameters)
|
input_parameters=parameters)
|
||||||
|
self.instance_migrations_count += 1
|
||||||
|
|
||||||
def post_execute(self):
|
def post_execute(self):
|
||||||
"""Post-execution phase
|
"""Post-execution phase
|
||||||
@@ -384,5 +386,9 @@ class WorkloadBalance(base.WorkloadStabilizationBaseStrategy):
|
|||||||
This can be used to compute the global efficacy
|
This can be used to compute the global efficacy
|
||||||
"""
|
"""
|
||||||
self.solution.model = self.compute_model
|
self.solution.model = self.compute_model
|
||||||
|
self.solution.set_efficacy_indicators(
|
||||||
|
instance_migrations_count=self.instance_migrations_count,
|
||||||
|
instances_count=len(self.compute_model.get_all_instances())
|
||||||
|
)
|
||||||
|
|
||||||
LOG.debug(self.compute_model.to_string())
|
LOG.debug(self.compute_model.to_string())
|
||||||
|
|||||||
@@ -80,6 +80,10 @@ class WorkloadStabilization(base.WorkloadStabilizationBaseStrategy):
|
|||||||
self.retry_count = None
|
self.retry_count = None
|
||||||
self.periods = None
|
self.periods = None
|
||||||
self.aggregation_method = None
|
self.aggregation_method = None
|
||||||
|
self.sd_before_audit = 0
|
||||||
|
self.sd_after_audit = 0
|
||||||
|
self.instance_migrations_count = 0
|
||||||
|
self.instances_count = 0
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_name(cls):
|
def get_name(cls):
|
||||||
@@ -460,6 +464,7 @@ class WorkloadStabilization(base.WorkloadStabilizationBaseStrategy):
|
|||||||
'threshold': float(self.thresholds[metric]),
|
'threshold': float(self.thresholds[metric]),
|
||||||
'sd': metric_sd})
|
'sd': metric_sd})
|
||||||
LOG.info("Launching workload optimization...")
|
LOG.info("Launching workload optimization...")
|
||||||
|
self.sd_before_audit = metric_sd
|
||||||
return self.simulate_migrations(hosts_load)
|
return self.simulate_migrations(hosts_load)
|
||||||
|
|
||||||
def add_migration(self,
|
def add_migration(self,
|
||||||
@@ -482,6 +487,7 @@ class WorkloadStabilization(base.WorkloadStabilizationBaseStrategy):
|
|||||||
self.add_migration(mig_instance.uuid, 'live',
|
self.add_migration(mig_instance.uuid, 'live',
|
||||||
mig_source_node.uuid,
|
mig_source_node.uuid,
|
||||||
mig_destination_node.uuid)
|
mig_destination_node.uuid)
|
||||||
|
self.instance_migrations_count += 1
|
||||||
|
|
||||||
def migrate(self, instance_uuid, src_host, dst_host):
|
def migrate(self, instance_uuid, src_host, dst_host):
|
||||||
mig_instance = self.compute_model.get_instance_by_uuid(instance_uuid)
|
mig_instance = self.compute_model.get_instance_by_uuid(instance_uuid)
|
||||||
@@ -545,6 +551,7 @@ class WorkloadStabilization(base.WorkloadStabilizationBaseStrategy):
|
|||||||
self.migrate(instance_host['instance'],
|
self.migrate(instance_host['instance'],
|
||||||
instance_host['s_host'],
|
instance_host['s_host'],
|
||||||
instance_host['host'])
|
instance_host['host'])
|
||||||
|
self.sd_after_audit = min_sd
|
||||||
|
|
||||||
for metric, value in zip(self.metrics, instance_load[:-1]):
|
for metric, value in zip(self.metrics, instance_load[:-1]):
|
||||||
if value < float(self.thresholds[metric]):
|
if value < float(self.thresholds[metric]):
|
||||||
@@ -564,4 +571,11 @@ class WorkloadStabilization(base.WorkloadStabilizationBaseStrategy):
|
|||||||
"""
|
"""
|
||||||
self.fill_solution()
|
self.fill_solution()
|
||||||
|
|
||||||
|
self.solution.set_efficacy_indicators(
|
||||||
|
instance_migrations_count=self.instance_migrations_count,
|
||||||
|
standard_deviation_before_audit=self.sd_before_audit,
|
||||||
|
standard_deviation_after_audit=self.sd_after_audit,
|
||||||
|
instances_count=len(self.compute_model.get_all_instances()),
|
||||||
|
)
|
||||||
|
|
||||||
LOG.debug(self.compute_model.to_string())
|
LOG.debug(self.compute_model.to_string())
|
||||||
|
|||||||
@@ -243,6 +243,7 @@ class TestWorkloadStabilization(base.TestCase):
|
|||||||
self.strategy.thresholds = {'cpu_util': 0.042,
|
self.strategy.thresholds = {'cpu_util': 0.042,
|
||||||
'memory.resident': 0.0001}
|
'memory.resident': 0.0001}
|
||||||
self.strategy.simulate_migrations = mock.Mock(return_value=False)
|
self.strategy.simulate_migrations = mock.Mock(return_value=False)
|
||||||
|
self.strategy.instance_migrations_count = 0
|
||||||
with mock.patch.object(self.strategy, 'migrate') as mock_migrate:
|
with mock.patch.object(self.strategy, 'migrate') as mock_migrate:
|
||||||
self.strategy.execute()
|
self.strategy.execute()
|
||||||
mock_migrate.assert_not_called()
|
mock_migrate.assert_not_called()
|
||||||
|
|||||||
Reference in New Issue
Block a user