Generalize exceptions & structure of strategies

Many strategies execute very similar statements especially in
pre_execute and some might raise errors that others might not. This
same pattern of many similar statements can also be observed in
strategies their tests.

This patch addresses these issues, firstly; the BaseStrategy class gets
1 additional method _pre_execute which allows for general logic that
most strategies perform at that stage. This method can be executed
before the similarly named method of the superclass. A notable change
is that _pre_execute now handles common exception handling for
ClusterStateStale & ClusterStateNotDefined exceptions.

A similar pattern is applied to the test classes of the strategies
each of these classes now inherits from the TestBaseStrategy class.
This class provides the common attributes almost every test class for
the strategies requires such as: The mocked compute_model, mocked
audit_scope and an instance of FakerModelCollector.

Finally, some minor changes were required in test_strategy_context
& test_audit_handlers and exceptions around 0 nodes in cluster or
storage are removed.

Change-Id: Ia7154376b2448aac65cf17999cc8c3e1c8309b5b
This commit is contained in:
Dantali0n
2019-02-26 17:41:57 +01:00
parent c7fe13e9e3
commit b24bd7a3bb
35 changed files with 413 additions and 794 deletions

View File

@@ -376,18 +376,6 @@ class KeystoneFailure(WatcherException):
msg_fmt = _("Keystone API endpoint is missing") msg_fmt = _("Keystone API endpoint is missing")
class ClusterEmpty(WatcherException):
msg_fmt = _("The list of compute node(s) in the cluster is empty")
class ComputeClusterEmpty(WatcherException):
msg_fmt = _("The list of compute node(s) in the cluster is empty")
class StorageClusterEmpty(WatcherException):
msg_fmt = _("The list of storage node(s) in the cluster is empty")
class MetricCollectorNotDefined(WatcherException): class MetricCollectorNotDefined(WatcherException):
msg_fmt = _("The metrics resource collector is not defined") msg_fmt = _("The metrics resource collector is not defined")

View File

@@ -15,6 +15,7 @@
# limitations under the License. # limitations under the License.
from watcher.decision_engine.strategy.strategies import actuation from watcher.decision_engine.strategy.strategies import actuation
from watcher.decision_engine.strategy.strategies import base
from watcher.decision_engine.strategy.strategies import basic_consolidation from watcher.decision_engine.strategy.strategies import basic_consolidation
from watcher.decision_engine.strategy.strategies import dummy_strategy from watcher.decision_engine.strategy.strategies import dummy_strategy
from watcher.decision_engine.strategy.strategies import dummy_with_scorer from watcher.decision_engine.strategy.strategies import dummy_with_scorer
@@ -33,6 +34,7 @@ from watcher.decision_engine.strategy.strategies import zone_migration
Actuator = actuation.Actuator Actuator = actuation.Actuator
BaseStrategy = base.BaseStrategy
BasicConsolidation = basic_consolidation.BasicConsolidation BasicConsolidation = basic_consolidation.BasicConsolidation
OutletTempControl = outlet_temp_control.OutletTempControl OutletTempControl = outlet_temp_control.OutletTempControl
DummyStrategy = dummy_strategy.DummyStrategy DummyStrategy = dummy_strategy.DummyStrategy
@@ -47,8 +49,9 @@ NoisyNeighbor = noisy_neighbor.NoisyNeighbor
ZoneMigration = zone_migration.ZoneMigration ZoneMigration = zone_migration.ZoneMigration
HostMaintenance = host_maintenance.HostMaintenance HostMaintenance = host_maintenance.HostMaintenance
__all__ = ("Actuator", "BasicConsolidation", "OutletTempControl", __all__ = ("Actuator", "BaseStrategy", "BasicConsolidation",
"DummyStrategy", "DummyWithScorer", "VMWorkloadConsolidation", "OutletTempControl", "DummyStrategy", "DummyWithScorer",
"WorkloadBalance", "WorkloadStabilization", "UniformAirflow", "VMWorkloadConsolidation", "WorkloadBalance",
"NoisyNeighbor", "SavingEnergy", "StorageCapacityBalance", "WorkloadStabilization", "UniformAirflow", "NoisyNeighbor",
"ZoneMigration", "HostMaintenance") "SavingEnergy", "StorageCapacityBalance", "ZoneMigration",
"HostMaintenance")

View File

@@ -15,13 +15,9 @@
# limitations under the License. # limitations under the License.
# #
from oslo_log import log
from watcher._i18n import _ from watcher._i18n import _
from watcher.decision_engine.strategy.strategies import base from watcher.decision_engine.strategy.strategies import base
LOG = log.getLogger(__name__)
class Actuator(base.UnclassifiedStrategy): class Actuator(base.UnclassifiedStrategy):
"""Actuator """Actuator
@@ -89,7 +85,7 @@ class Actuator(base.UnclassifiedStrategy):
return self.input_parameters.get('actions', []) return self.input_parameters.get('actions', [])
def pre_execute(self): def pre_execute(self):
LOG.info("Preparing Actuator strategy...") self._pre_execute()
def do_execute(self): def do_execute(self):
for action in self.actions: for action in self.actions:

View File

@@ -39,6 +39,8 @@ which are dynamically loaded by Watcher at launch time.
import abc import abc
import six import six
from oslo_config import cfg
from oslo_log import log
from oslo_utils import strutils from oslo_utils import strutils
from watcher.common import clients from watcher.common import clients
@@ -52,6 +54,9 @@ from watcher.decision_engine.model.collector import manager
from watcher.decision_engine.solution import default from watcher.decision_engine.solution import default
from watcher.decision_engine.strategy.common import level from watcher.decision_engine.strategy.common import level
LOG = log.getLogger(__name__)
CONF = cfg.CONF
class StrategyEndpoint(object): class StrategyEndpoint(object):
def __init__(self, messaging): def __init__(self, messaging):
@@ -218,6 +223,23 @@ class BaseStrategy(loadable.Loadable):
""" """
raise NotImplementedError() raise NotImplementedError()
def _pre_execute(self):
"""Base Pre-execution phase
This will perform basic pre execution operations most strategies
should perform.
"""
LOG.info("Initializing " + self.get_display_name() + " Strategy")
if not self.compute_model:
raise exception.ClusterStateNotDefined()
if self.compute_model.stale:
raise exception.ClusterStateStale()
LOG.debug(self.compute_model.to_string())
def execute(self): def execute(self):
"""Execute a strategy """Execute a strategy

View File

@@ -21,7 +21,6 @@ from oslo_config import cfg
from oslo_log import log from oslo_log import log
from watcher._i18n import _ from watcher._i18n import _
from watcher.common import exception
from watcher.decision_engine.model import element from watcher.decision_engine.model import element
from watcher.decision_engine.strategy.strategies import base from watcher.decision_engine.strategy.strategies import base
@@ -429,18 +428,7 @@ class BasicConsolidation(base.ServerConsolidationBaseStrategy):
return unsuccessful_migration + 1 return unsuccessful_migration + 1
def pre_execute(self): def pre_execute(self):
LOG.info("Initializing Server Consolidation") self._pre_execute()
if not self.compute_model:
raise exception.ClusterStateNotDefined()
if len(self.get_available_compute_nodes()) == 0:
raise exception.ClusterEmpty()
if self.compute_model.stale:
raise exception.ClusterStateStale()
LOG.debug(self.compute_model.to_string())
def do_execute(self): def do_execute(self):
unsuccessful_migration = 0 unsuccessful_migration = 0

View File

@@ -49,7 +49,7 @@ class DummyStrategy(base.DummyBaseStrategy):
SLEEP = "sleep" SLEEP = "sleep"
def pre_execute(self): def pre_execute(self):
pass self._pre_execute()
def do_execute(self): def do_execute(self):
para1 = self.input_parameters.para1 para1 = self.input_parameters.para1

View File

@@ -46,7 +46,7 @@ class DummyWithResize(base.DummyBaseStrategy):
SLEEP = "sleep" SLEEP = "sleep"
def pre_execute(self): def pre_execute(self):
pass self._pre_execute()
def do_execute(self): def do_execute(self):
para1 = self.input_parameters.para1 para1 = self.input_parameters.para1

View File

@@ -76,7 +76,7 @@ class DummyWithScorer(base.DummyBaseStrategy):
metainfo['workloads'])} metainfo['workloads'])}
def pre_execute(self): def pre_execute(self):
pass self._pre_execute()
def do_execute(self): def do_execute(self):
# Simple "hello world" from strategy # Simple "hello world" from strategy

View File

@@ -21,7 +21,7 @@ from oslo_log import log
import six import six
from watcher._i18n import _ from watcher._i18n import _
from watcher.common import exception as wexc from watcher.common import exception
from watcher.decision_engine.model import element from watcher.decision_engine.model import element
from watcher.decision_engine.strategy.strategies import base from watcher.decision_engine.strategy.strategies import base
@@ -112,7 +112,7 @@ class HostMaintenance(base.HostMaintenanceBaseStrategy):
'state=%(state)s, state_type=%(st)s.', 'state=%(state)s, state_type=%(st)s.',
dict(state=instance.state, dict(state=instance.state,
st=type(instance.state))) st=type(instance.state)))
raise wexc.WatcherException raise exception.WatcherException
def get_node_status_str(self, node): def get_node_status_str(self, node):
"""Get node status in string format""" """Get node status in string format"""
@@ -125,7 +125,7 @@ class HostMaintenance(base.HostMaintenanceBaseStrategy):
'status=%(status)s, status_type=%(st)s.', 'status=%(status)s, status_type=%(st)s.',
dict(status=node.status, dict(status=node.status,
st=type(node.status))) st=type(node.status)))
raise wexc.WatcherException raise exception.WatcherException
def get_node_capacity(self, node): def get_node_capacity(self, node):
"""Collect cpu, ram and disk capacity of a node. """Collect cpu, ram and disk capacity of a node.
@@ -292,13 +292,7 @@ class HostMaintenance(base.HostMaintenanceBaseStrategy):
self.instance_migration(instance, maintenance_node) self.instance_migration(instance, maintenance_node)
def pre_execute(self): def pre_execute(self):
LOG.debug(self.compute_model.to_string()) self._pre_execute()
if not self.compute_model:
raise wexc.ClusterStateNotDefined()
if self.compute_model.stale:
raise wexc.ClusterStateStale()
def do_execute(self): def do_execute(self):
LOG.info(_('Executing Host Maintenance Migration Strategy')) LOG.info(_('Executing Host Maintenance Migration Strategy'))

View File

@@ -20,7 +20,6 @@ from oslo_config import cfg
from oslo_log import log from oslo_log import log
from watcher._i18n import _ from watcher._i18n import _
from watcher.common import exception as wexc
from watcher.decision_engine.strategy.strategies import base from watcher.decision_engine.strategy.strategies import base
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)
@@ -156,12 +155,7 @@ class NoisyNeighbor(base.NoisyNeighborBaseStrategy):
return None return None
def group_hosts(self): def group_hosts(self):
nodes = self.compute_model.get_all_compute_nodes() nodes = self.compute_model.get_all_compute_nodes()
size_cluster = len(nodes)
if size_cluster == 0:
raise wexc.ClusterEmpty()
hosts_need_release = {} hosts_need_release = {}
hosts_target = [] hosts_target = []
@@ -259,15 +253,7 @@ class NoisyNeighbor(base.NoisyNeighborBaseStrategy):
return dest_servers return dest_servers
def pre_execute(self): def pre_execute(self):
LOG.debug("Initializing Noisy Neighbor strategy") self._pre_execute()
if not self.compute_model:
raise wexc.ClusterStateNotDefined()
if self.compute_model.stale:
raise wexc.ClusterStateStale()
LOG.debug(self.compute_model.to_string())
def do_execute(self): def do_execute(self):
self.cache_threshold = self.input_parameters.cache_threshold self.cache_threshold = self.input_parameters.cache_threshold

View File

@@ -36,7 +36,7 @@ from oslo_config import cfg
from oslo_log import log from oslo_log import log
from watcher._i18n import _ from watcher._i18n import _
from watcher.common import exception as wexc from watcher.common import exception
from watcher.decision_engine.model import element from watcher.decision_engine.model import element
from watcher.decision_engine.strategy.strategies import base from watcher.decision_engine.strategy.strategies import base
@@ -177,10 +177,6 @@ class OutletTempControl(base.ThermalOptimizationBaseStrategy):
def group_hosts_by_outlet_temp(self): def group_hosts_by_outlet_temp(self):
"""Group hosts based on outlet temp meters""" """Group hosts based on outlet temp meters"""
nodes = self.get_available_compute_nodes() nodes = self.get_available_compute_nodes()
size_cluster = len(nodes)
if size_cluster == 0:
raise wexc.ClusterEmpty()
hosts_need_release = [] hosts_need_release = []
hosts_target = [] hosts_target = []
metric_name = self.METRIC_NAMES[ metric_name = self.METRIC_NAMES[
@@ -231,7 +227,7 @@ class OutletTempControl(base.ThermalOptimizationBaseStrategy):
instance.uuid) instance.uuid)
continue continue
return mig_source_node, instance return mig_source_node, instance
except wexc.InstanceNotFound as e: except exception.InstanceNotFound as e:
LOG.exception(e) LOG.exception(e)
LOG.info("Instance not found") LOG.info("Instance not found")
@@ -260,22 +256,14 @@ class OutletTempControl(base.ThermalOptimizationBaseStrategy):
return dest_servers return dest_servers
def pre_execute(self): def pre_execute(self):
LOG.debug("Initializing Outlet temperature strategy") self._pre_execute()
if not self.compute_model:
raise wexc.ClusterStateNotDefined()
if self.compute_model.stale:
raise wexc.ClusterStateStale()
LOG.debug(self.compute_model.to_string())
def do_execute(self):
# the migration plan will be triggered when the outlet temperature # the migration plan will be triggered when the outlet temperature
# reaches threshold # reaches threshold
self.threshold = self.input_parameters.threshold self.threshold = self.input_parameters.threshold
LOG.debug("Initializing Outlet temperature strategy with threshold=%d", LOG.info("Outlet temperature strategy threshold=%d",
self.threshold) self.threshold)
def do_execute(self):
hosts_need_release, hosts_target = self.group_hosts_by_outlet_temp() hosts_need_release, hosts_target = self.group_hosts_by_outlet_temp()
if len(hosts_need_release) == 0: if len(hosts_need_release) == 0:

View File

@@ -22,7 +22,7 @@ import random
from oslo_log import log from oslo_log import log
from watcher._i18n import _ from watcher._i18n import _
from watcher.common import exception as wexc from watcher.common import exception
from watcher.decision_engine.strategy.strategies import base from watcher.decision_engine.strategy.strategies import base
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)
@@ -179,7 +179,7 @@ class SavingEnergy(base.SavingEnergyBaseStrategy):
host_uuid = compute_service.get('host') host_uuid = compute_service.get('host')
try: try:
self.compute_model.get_node_by_uuid(host_uuid) self.compute_model.get_node_by_uuid(host_uuid)
except wexc.ComputeNodeNotFound: except exception.ComputeNodeNotFound:
continue continue
if not (hypervisor_node.get('state') == 'up'): if not (hypervisor_node.get('state') == 'up'):
@@ -214,28 +214,15 @@ class SavingEnergy(base.SavingEnergyBaseStrategy):
LOG.debug("power on %s", node) LOG.debug("power on %s", node)
def pre_execute(self): def pre_execute(self):
"""Pre-execution phase self._pre_execute()
self.free_used_percent = self.input_parameters.free_used_percent
This can be used to fetch some pre-requisites or data. self.min_free_hosts_num = self.input_parameters.min_free_hosts_num
"""
LOG.info("Initializing Saving Energy Strategy")
if not self.compute_model:
raise wexc.ClusterStateNotDefined()
if self.compute_model.stale:
raise wexc.ClusterStateStale()
LOG.debug(self.compute_model.to_string())
def do_execute(self): def do_execute(self):
"""Strategy execution phase """Strategy execution phase
This phase is where you should put the main logic of your strategy. This phase is where you should put the main logic of your strategy.
""" """
self.free_used_percent = self.input_parameters.free_used_percent
self.min_free_hosts_num = self.input_parameters.min_free_hosts_num
self.get_hosts_pool() self.get_hosts_pool()
self.save_energy() self.save_energy()

View File

@@ -349,11 +349,7 @@ class StorageCapacityBalance(base.WorkloadStabilizationBaseStrategy):
return retype_dicts, migrate_dicts return retype_dicts, migrate_dicts
def pre_execute(self): def pre_execute(self):
"""Pre-execution phase LOG.info("Initializing " + self.get_display_name() + " Strategy")
This can be used to fetch some pre-requisites or data.
"""
LOG.info("Initializing Storage Capacity Balance Strategy")
self.volume_threshold = self.input_parameters.volume_threshold self.volume_threshold = self.input_parameters.volume_threshold
def do_execute(self, audit=None): def do_execute(self, audit=None):

View File

@@ -21,7 +21,6 @@ from oslo_config import cfg
from oslo_log import log from oslo_log import log
from watcher._i18n import _ from watcher._i18n import _
from watcher.common import exception as wexc
from watcher.decision_engine.model import element from watcher.decision_engine.model import element
from watcher.decision_engine.strategy.strategies import base from watcher.decision_engine.strategy.strategies import base
@@ -276,8 +275,6 @@ class UniformAirflow(base.BaseStrategy):
"""Group hosts based on airflow meters""" """Group hosts based on airflow meters"""
nodes = self.get_available_compute_nodes() nodes = self.get_available_compute_nodes()
if not nodes:
raise wexc.ClusterEmpty()
overload_hosts = [] overload_hosts = []
nonoverload_hosts = [] nonoverload_hosts = []
for node_id in nodes: for node_id in nodes:
@@ -306,14 +303,7 @@ class UniformAirflow(base.BaseStrategy):
return overload_hosts, nonoverload_hosts return overload_hosts, nonoverload_hosts
def pre_execute(self): def pre_execute(self):
LOG.debug("Initializing Uniform Airflow Strategy") self._pre_execute()
if not self.compute_model:
raise wexc.ClusterStateNotDefined()
if self.compute_model.stale:
raise wexc.ClusterStateStale()
self.meter_name_airflow = self.METRIC_NAMES[ self.meter_name_airflow = self.METRIC_NAMES[
self.datasource_backend.NAME]['host_airflow'] self.datasource_backend.NAME]['host_airflow']
self.meter_name_inlet_t = self.METRIC_NAMES[ self.meter_name_inlet_t = self.METRIC_NAMES[
@@ -321,13 +311,12 @@ class UniformAirflow(base.BaseStrategy):
self.meter_name_power = self.METRIC_NAMES[ self.meter_name_power = self.METRIC_NAMES[
self.datasource_backend.NAME]['host_power'] self.datasource_backend.NAME]['host_power']
LOG.debug(self.compute_model.to_string())
def do_execute(self):
self.threshold_airflow = self.input_parameters.threshold_airflow self.threshold_airflow = self.input_parameters.threshold_airflow
self.threshold_inlet_t = self.input_parameters.threshold_inlet_t self.threshold_inlet_t = self.input_parameters.threshold_inlet_t
self.threshold_power = self.input_parameters.threshold_power self.threshold_power = self.input_parameters.threshold_power
self._period = self.input_parameters.period self._period = self.input_parameters.period
def do_execute(self):
source_nodes, target_nodes = self.group_hosts_by_airflow() source_nodes, target_nodes = self.group_hosts_by_airflow()
if not source_nodes: if not source_nodes:

View File

@@ -154,8 +154,9 @@ class VMWorkloadConsolidation(base.ServerConsolidationBaseStrategy):
def get_available_compute_nodes(self): def get_available_compute_nodes(self):
default_node_scope = [element.ServiceState.ENABLED.value, default_node_scope = [element.ServiceState.ENABLED.value,
element.ServiceState.DISABLED.value] element.ServiceState.DISABLED.value]
nodes = self.compute_model.get_all_compute_nodes().items()
return {uuid: cn for uuid, cn in return {uuid: cn for uuid, cn in
self.compute_model.get_all_compute_nodes().items() nodes
if cn.state == element.ServiceState.ONLINE.value and if cn.state == element.ServiceState.ONLINE.value and
cn.status in default_node_scope} cn.status in default_node_scope}
@@ -554,13 +555,7 @@ class VMWorkloadConsolidation(base.ServerConsolidationBaseStrategy):
asc += 1 asc += 1
def pre_execute(self): def pre_execute(self):
if not self.compute_model: self._pre_execute()
raise exception.ClusterStateNotDefined()
if self.compute_model.stale:
raise exception.ClusterStateStale()
LOG.debug(self.compute_model.to_string())
def do_execute(self): def do_execute(self):
"""Execute strategy. """Execute strategy.

View File

@@ -23,7 +23,7 @@ from oslo_config import cfg
from oslo_log import log from oslo_log import log
from watcher._i18n import _ from watcher._i18n import _
from watcher.common import exception as wexc from watcher.common import exception
from watcher.decision_engine.model import element from watcher.decision_engine.model import element
from watcher.decision_engine.strategy.strategies import base from watcher.decision_engine.strategy.strategies import base
@@ -196,7 +196,7 @@ class WorkloadBalance(base.WorkloadStabilizationBaseStrategy):
if 0 <= current_delta < min_delta: if 0 <= current_delta < min_delta:
min_delta = current_delta min_delta = current_delta
instance_id = instance.uuid instance_id = instance.uuid
except wexc.InstanceNotFound: except exception.InstanceNotFound:
LOG.error("Instance not found; error: %s", LOG.error("Instance not found; error: %s",
instance_id) instance_id)
if instance_id: if instance_id:
@@ -251,8 +251,6 @@ class WorkloadBalance(base.WorkloadStabilizationBaseStrategy):
nodes = self.get_available_compute_nodes() nodes = self.get_available_compute_nodes()
cluster_size = len(nodes) cluster_size = len(nodes)
if not nodes:
raise wexc.ClusterEmpty()
overload_hosts = [] overload_hosts = []
nonoverload_hosts = [] nonoverload_hosts = []
# total workload of cluster # total workload of cluster
@@ -303,34 +301,24 @@ class WorkloadBalance(base.WorkloadStabilizationBaseStrategy):
else: else:
nonoverload_hosts.append(instance_data) nonoverload_hosts.append(instance_data)
avg_workload = cluster_workload / cluster_size avg_workload = 0
if cluster_size != 0:
avg_workload = cluster_workload / cluster_size
return overload_hosts, nonoverload_hosts, avg_workload, workload_cache return overload_hosts, nonoverload_hosts, avg_workload, workload_cache
def pre_execute(self): def pre_execute(self):
"""Pre-execution phase self._pre_execute()
self.threshold = self.input_parameters.threshold
This can be used to fetch some pre-requisites or data. self._period = self.input_parameters.period
""" self._meter = self.input_parameters.metrics
LOG.info("Initializing Workload Balance Strategy") self._granularity = self.input_parameters.granularity
if not self.compute_model:
raise wexc.ClusterStateNotDefined()
if self.compute_model.stale:
raise wexc.ClusterStateStale()
LOG.debug(self.compute_model.to_string())
def do_execute(self): def do_execute(self):
"""Strategy execution phase """Strategy execution phase
This phase is where you should put the main logic of your strategy. 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
self._meter = self.input_parameters.metrics
self._granularity = self.input_parameters.granularity
source_nodes, target_nodes, avg_workload, workload_cache = ( source_nodes, target_nodes, avg_workload, workload_cache = (
self.group_hosts_by_cpu_or_ram_util()) self.group_hosts_by_cpu_or_ram_util())

View File

@@ -290,8 +290,8 @@ class WorkloadStabilization(base.WorkloadStabilizationBaseStrategy):
return normalized_hosts return normalized_hosts
def get_available_nodes(self): def get_available_nodes(self):
return {node_uuid: node for node_uuid, node in nodes = self.compute_model.get_all_compute_nodes().items()
self.compute_model.get_all_compute_nodes().items() return {node_uuid: node for node_uuid, node in nodes
if node.state == element.ServiceState.ONLINE.value and if node.state == element.ServiceState.ONLINE.value and
node.status == element.ServiceState.ENABLED.value} node.status == element.ServiceState.ENABLED.value}
@@ -506,14 +506,7 @@ class WorkloadStabilization(base.WorkloadStabilizationBaseStrategy):
return self.solution return self.solution
def pre_execute(self): def pre_execute(self):
LOG.info("Initializing Workload Stabilization") self._pre_execute()
if not self.compute_model:
raise exception.ClusterStateNotDefined()
if self.compute_model.stale:
raise exception.ClusterStateStale()
self.weights = self.input_parameters.weights self.weights = self.input_parameters.weights
self.metrics = self.input_parameters.metrics self.metrics = self.input_parameters.metrics
self.thresholds = self.input_parameters.thresholds self.thresholds = self.input_parameters.thresholds

View File

@@ -21,7 +21,6 @@ from cinderclient.v2.volumes import Volume
from novaclient.v2.servers import Server from novaclient.v2.servers import Server
from watcher._i18n import _ from watcher._i18n import _
from watcher.common import cinder_helper from watcher.common import cinder_helper
from watcher.common import exception as wexc
from watcher.common import nova_helper from watcher.common import nova_helper
from watcher.decision_engine.model import element from watcher.decision_engine.model import element
from watcher.decision_engine.strategy.strategies import base from watcher.decision_engine.strategy.strategies import base
@@ -267,19 +266,7 @@ class ZoneMigration(base.ZoneMigrationBaseStrategy):
cn.status in default_node_scope} cn.status in default_node_scope}
def pre_execute(self): def pre_execute(self):
"""Pre-execution phase self._pre_execute()
This can be used to fetch some pre-requisites or data.
"""
LOG.info("Initializing zone migration Strategy")
if len(self.get_available_compute_nodes()) == 0:
raise wexc.ComputeClusterEmpty()
if len(self.get_available_storage_nodes()) == 0:
raise wexc.StorageClusterEmpty()
LOG.debug(self.compute_model.to_string())
LOG.debug(self.storage_model.to_string()) LOG.debug(self.storage_model.to_string())
def do_execute(self): def do_execute(self):

View File

@@ -29,6 +29,7 @@ from watcher.db.sqlalchemy import api as sq_api
from watcher.decision_engine.audit import continuous from watcher.decision_engine.audit import continuous
from watcher.decision_engine.audit import oneshot from watcher.decision_engine.audit import oneshot
from watcher.decision_engine.model.collector import manager from watcher.decision_engine.model.collector import manager
from watcher.decision_engine.strategy.strategies import base as base_strategy
from watcher.decision_engine.strategy.strategies import dummy_strategy from watcher.decision_engine.strategy.strategies import dummy_strategy
from watcher import notifications from watcher import notifications
from watcher import objects from watcher import objects
@@ -62,6 +63,8 @@ class TestOneShotAuditHandler(base.DbTestCase):
goal=self.goal) goal=self.goal)
@mock.patch.object(manager.CollectorManager, "get_cluster_model_collector") @mock.patch.object(manager.CollectorManager, "get_cluster_model_collector")
@mock.patch.object(base_strategy.BaseStrategy, "compute_model",
mock.Mock(stale=False))
def test_trigger_audit_without_errors(self, m_collector): def test_trigger_audit_without_errors(self, m_collector):
m_collector.return_value = faker.FakerModelCollector() m_collector.return_value = faker.FakerModelCollector()
audit_handler = oneshot.OneShotAuditHandler() audit_handler = oneshot.OneShotAuditHandler()
@@ -85,7 +88,7 @@ class TestOneShotAuditHandler(base.DbTestCase):
expected_calls, expected_calls,
self.m_audit_notifications.send_action_notification.call_args_list) self.m_audit_notifications.send_action_notification.call_args_list)
@mock.patch.object(dummy_strategy.DummyStrategy, "do_execute") @mock.patch.object(base_strategy.BaseStrategy, "do_execute")
@mock.patch.object(manager.CollectorManager, "get_cluster_model_collector") @mock.patch.object(manager.CollectorManager, "get_cluster_model_collector")
def test_trigger_audit_with_error(self, m_collector, m_do_execute): def test_trigger_audit_with_error(self, m_collector, m_do_execute):
m_collector.return_value = faker.FakerModelCollector() m_collector.return_value = faker.FakerModelCollector()
@@ -107,6 +110,8 @@ class TestOneShotAuditHandler(base.DbTestCase):
self.m_audit_notifications.send_action_notification.call_args_list) self.m_audit_notifications.send_action_notification.call_args_list)
@mock.patch.object(manager.CollectorManager, "get_cluster_model_collector") @mock.patch.object(manager.CollectorManager, "get_cluster_model_collector")
@mock.patch.object(base_strategy.BaseStrategy, "compute_model",
mock.Mock(stale=False))
def test_trigger_audit_state_succeeded(self, m_collector): def test_trigger_audit_state_succeeded(self, m_collector):
m_collector.return_value = faker.FakerModelCollector() m_collector.return_value = faker.FakerModelCollector()
audit_handler = oneshot.OneShotAuditHandler() audit_handler = oneshot.OneShotAuditHandler()
@@ -133,6 +138,8 @@ class TestOneShotAuditHandler(base.DbTestCase):
self.m_audit_notifications.send_action_notification.call_args_list) self.m_audit_notifications.send_action_notification.call_args_list)
@mock.patch.object(manager.CollectorManager, "get_cluster_model_collector") @mock.patch.object(manager.CollectorManager, "get_cluster_model_collector")
@mock.patch.object(base_strategy.BaseStrategy, "compute_model",
mock.Mock(stale=False))
def test_trigger_audit_send_notification(self, m_collector): def test_trigger_audit_send_notification(self, m_collector):
m_collector.return_value = faker.FakerModelCollector() m_collector.return_value = faker.FakerModelCollector()
audit_handler = oneshot.OneShotAuditHandler() audit_handler = oneshot.OneShotAuditHandler()
@@ -425,23 +432,25 @@ class TestContinuousAuditHandler(base.DbTestCase):
audit_handler.launch_audits_periodically() audit_handler.launch_audits_periodically()
m_remove_job.assert_called() m_remove_job.assert_called()
@mock.patch.object(continuous.ContinuousAuditHandler, 'planner') @mock.patch.object(continuous.ContinuousAuditHandler, 'planner',
def test_execute_audit(self, m_planner): mock.Mock())
@mock.patch.object(base_strategy.BaseStrategy, "compute_model",
mock.Mock(stale=False))
def test_execute_audit(self):
audit_handler = continuous.ContinuousAuditHandler() audit_handler = continuous.ContinuousAuditHandler()
audit = self.audits[0] audit_handler.execute_audit(self.audits[0], self.context)
audit_handler.execute_audit(audit, self.context)
expected_calls = [ expected_calls = [
mock.call(self.context, audit, mock.call(self.context, self.audits[0],
action=objects.fields.NotificationAction.STRATEGY, action=objects.fields.NotificationAction.STRATEGY,
phase=objects.fields.NotificationPhase.START), phase=objects.fields.NotificationPhase.START),
mock.call(self.context, audit, mock.call(self.context, self.audits[0],
action=objects.fields.NotificationAction.STRATEGY, action=objects.fields.NotificationAction.STRATEGY,
phase=objects.fields.NotificationPhase.END), phase=objects.fields.NotificationPhase.END),
mock.call(self.context, audit, mock.call(self.context, self.audits[0],
action=objects.fields.NotificationAction.PLANNER, action=objects.fields.NotificationAction.PLANNER,
phase=objects.fields.NotificationPhase.START), phase=objects.fields.NotificationPhase.START),
mock.call(self.context, audit, mock.call(self.context, self.audits[0],
action=objects.fields.NotificationAction.PLANNER, action=objects.fields.NotificationAction.PLANNER,
phase=objects.fields.NotificationPhase.END)] phase=objects.fields.NotificationPhase.END)]

View File

@@ -23,6 +23,7 @@ from watcher.decision_engine.strategy.context import default as d_strategy_ctx
from watcher.decision_engine.strategy.selection import default as d_selector from watcher.decision_engine.strategy.selection import default as d_selector
from watcher.decision_engine.strategy import strategies from watcher.decision_engine.strategy import strategies
from watcher.tests.db import base from watcher.tests.db import base
from watcher.tests.decision_engine.model import faker_cluster_state
from watcher.tests.objects import utils as obj_utils from watcher.tests.objects import utils as obj_utils
@@ -35,14 +36,20 @@ class TestStrategyContext(base.DbTestCase):
self.context, uuid=utils.generate_uuid()) self.context, uuid=utils.generate_uuid())
self.audit = obj_utils.create_test_audit( self.audit = obj_utils.create_test_audit(
self.context, audit_template_id=audit_template.id) self.context, audit_template_id=audit_template.id)
self.fake_cluster = faker_cluster_state.FakerModelCollector()
p_model = mock.patch.object(
strategies.DummyStrategy, "compute_model",
new_callable=mock.PropertyMock)
self.m_model = p_model.start()
self.addCleanup(p_model.stop)
self.m_model.return_value = self.fake_cluster.build_scenario_1()
strategy_context = d_strategy_ctx.DefaultStrategyContext() strategy_context = d_strategy_ctx.DefaultStrategyContext()
@mock.patch.object(strategies.DummyStrategy, 'compute_model',
new_callable=mock.PropertyMock)
@mock.patch.object(d_selector.DefaultStrategySelector, 'select') @mock.patch.object(d_selector.DefaultStrategySelector, 'select')
def test_execute_strategy(self, mock_call, m_model): def test_execute_strategy(self, mock_call):
m_model.return_value = mock.Mock()
mock_call.return_value = strategies.DummyStrategy( mock_call.return_value = strategies.DummyStrategy(
config=mock.Mock()) config=mock.Mock())
solution = self.strategy_context.execute_strategy( solution = self.strategy_context.execute_strategy(

View File

@@ -18,14 +18,14 @@ import mock
from watcher.common import utils from watcher.common import utils
from watcher.decision_engine.strategy import strategies from watcher.decision_engine.strategy import strategies
from watcher.tests import base from watcher.tests.decision_engine.strategy.strategies.test_base \
import TestBaseStrategy
class TestActuator(base.TestCase): class TestActuator(TestBaseStrategy):
def setUp(self): def setUp(self):
super(TestActuator, self).setUp() super(TestActuator, self).setUp()
# fake cluster
self.strategy = strategies.Actuator(config=mock.Mock()) self.strategy = strategies.Actuator(config=mock.Mock())
def test_actuator_strategy(self): def test_actuator_strategy(self):

View File

@@ -0,0 +1,70 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2019 European Organization for Nuclear Research (CERN)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import mock
from watcher.common import exception
from watcher.decision_engine.model import model_root
from watcher.decision_engine.strategy import strategies
from watcher.tests import base
from watcher.tests.decision_engine.model import faker_cluster_state
class TestBaseStrategy(base.TestCase):
def setUp(self):
super(TestBaseStrategy, self).setUp()
# fake cluster
self.fake_c_cluster = faker_cluster_state.FakerModelCollector()
p_c_model = mock.patch.object(
strategies.BaseStrategy, "compute_model",
new_callable=mock.PropertyMock)
self.m_c_model = p_c_model.start()
self.addCleanup(p_c_model.stop)
p_audit_scope = mock.patch.object(
strategies.BaseStrategy, "audit_scope",
new_callable=mock.PropertyMock)
self.m_audit_scope = p_audit_scope.start()
self.addCleanup(p_audit_scope.stop)
self.m_audit_scope.return_value = mock.Mock()
self.m_c_model.return_value = model_root.ModelRoot()
self.strategy = strategies.DummyStrategy(config=mock.Mock())
class TestBaseStrategyException(TestBaseStrategy):
def setUp(self):
super(TestBaseStrategyException, self).setUp()
def test_exception_model(self):
self.m_c_model.return_value = None
self.assertRaises(
exception.ClusterStateNotDefined, self.strategy.execute)
def test_exception_stale_cdm(self):
self.fake_c_cluster.set_cluster_data_model_as_stale()
self.m_c_model.return_value = self.fake_c_cluster.cluster_data_model
self.assertRaises(
# TODO(Dantali0n) This should return ClusterStale,
# improve set_cluster_data_model_as_stale().
exception.ClusterStateNotDefined,
self.strategy.execute)

View File

@@ -22,17 +22,16 @@ import mock
from watcher.applier.loading import default from watcher.applier.loading import default
from watcher.common import clients from watcher.common import clients
from watcher.common import exception
from watcher.decision_engine.model import model_root from watcher.decision_engine.model import model_root
from watcher.decision_engine.strategy import strategies from watcher.decision_engine.strategy import strategies
from watcher.tests import base
from watcher.tests.decision_engine.model import ceilometer_metrics from watcher.tests.decision_engine.model import ceilometer_metrics
from watcher.tests.decision_engine.model import faker_cluster_state
from watcher.tests.decision_engine.model import gnocchi_metrics from watcher.tests.decision_engine.model import gnocchi_metrics
from watcher.tests.decision_engine.model import monasca_metrics from watcher.tests.decision_engine.model import monasca_metrics
from watcher.tests.decision_engine.strategy.strategies.test_base \
import TestBaseStrategy
class TestBasicConsolidation(base.TestCase): class TestBasicConsolidation(TestBaseStrategy):
scenarios = [ scenarios = [
("Ceilometer", ("Ceilometer",
@@ -50,36 +49,18 @@ class TestBasicConsolidation(base.TestCase):
super(TestBasicConsolidation, self).setUp() super(TestBasicConsolidation, self).setUp()
# fake metrics # fake metrics
self.fake_metrics = self.fake_datasource_cls() self.fake_metrics = self.fake_datasource_cls()
# fake cluster
self.fake_cluster = faker_cluster_state.FakerModelCollector()
p_osc = mock.patch.object( p_osc = mock.patch.object(
clients, "OpenStackClients") clients, "OpenStackClients")
self.m_osc = p_osc.start() self.m_osc = p_osc.start()
self.addCleanup(p_osc.stop) self.addCleanup(p_osc.stop)
p_model = mock.patch.object(
strategies.BasicConsolidation, "compute_model",
new_callable=mock.PropertyMock)
self.m_model = p_model.start()
self.addCleanup(p_model.stop)
p_datasource = mock.patch.object( p_datasource = mock.patch.object(
strategies.BasicConsolidation, 'datasource_backend', strategies.BasicConsolidation, 'datasource_backend',
new_callable=mock.PropertyMock) new_callable=mock.PropertyMock)
self.m_datasource = p_datasource.start() self.m_datasource = p_datasource.start()
self.addCleanup(p_datasource.stop) self.addCleanup(p_datasource.stop)
p_audit_scope = mock.patch.object(
strategies.BasicConsolidation, "audit_scope",
new_callable=mock.PropertyMock
)
self.m_audit_scope = p_audit_scope.start()
self.addCleanup(p_audit_scope.stop)
self.m_audit_scope.return_value = mock.Mock()
self.m_model.return_value = model_root.ModelRoot()
self.m_datasource.return_value = mock.Mock( self.m_datasource.return_value = mock.Mock(
get_host_cpu_usage=self.fake_metrics.get_usage_node_cpu, get_host_cpu_usage=self.fake_metrics.get_usage_node_cpu,
get_instance_cpu_usage=self.fake_metrics. get_instance_cpu_usage=self.fake_metrics.
@@ -90,13 +71,13 @@ class TestBasicConsolidation(base.TestCase):
def test_cluster_size(self): def test_cluster_size(self):
size_cluster = len( size_cluster = len(
self.fake_cluster.generate_scenario_1().get_all_compute_nodes()) self.fake_c_cluster.generate_scenario_1().get_all_compute_nodes())
size_cluster_assert = 5 size_cluster_assert = 5
self.assertEqual(size_cluster_assert, size_cluster) self.assertEqual(size_cluster_assert, size_cluster)
def test_basic_consolidation_score_node(self): def test_basic_consolidation_score_node(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
node_1_score = 0.023333333333333317 node_1_score = 0.023333333333333317
self.assertEqual(node_1_score, self.strategy.calculate_score_node( self.assertEqual(node_1_score, self.strategy.calculate_score_node(
model.get_node_by_uuid("Node_1"))) model.get_node_by_uuid("Node_1")))
@@ -108,8 +89,8 @@ class TestBasicConsolidation(base.TestCase):
model.get_node_by_uuid("Node_0"))) model.get_node_by_uuid("Node_0")))
def test_basic_consolidation_score_instance(self): def test_basic_consolidation_score_instance(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
instance_0 = model.get_instance_by_uuid("INSTANCE_0") instance_0 = model.get_instance_by_uuid("INSTANCE_0")
instance_0_score = 0.023333333333333317 instance_0_score = 0.023333333333333317
self.assertEqual( self.assertEqual(
@@ -138,8 +119,8 @@ class TestBasicConsolidation(base.TestCase):
self.strategy.calculate_score_instance(instance_7)) self.strategy.calculate_score_instance(instance_7))
def test_basic_consolidation_score_instance_disk(self): def test_basic_consolidation_score_instance_disk(self):
model = self.fake_cluster.generate_scenario_5_with_instance_disk_0() model = self.fake_c_cluster.generate_scenario_5_with_instance_disk_0()
self.m_model.return_value = model self.m_c_model.return_value = model
instance_0 = model.get_instance_by_uuid("INSTANCE_0") instance_0 = model.get_instance_by_uuid("INSTANCE_0")
instance_0_score = 0.023333333333333355 instance_0_score = 0.023333333333333355
self.assertEqual( self.assertEqual(
@@ -147,8 +128,8 @@ class TestBasicConsolidation(base.TestCase):
self.strategy.calculate_score_instance(instance_0)) self.strategy.calculate_score_instance(instance_0))
def test_basic_consolidation_weight(self): def test_basic_consolidation_weight(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
instance_0 = model.get_instance_by_uuid("INSTANCE_0") instance_0 = model.get_instance_by_uuid("INSTANCE_0")
cores = 16 cores = 16
# 80 Go # 80 Go
@@ -160,19 +141,9 @@ class TestBasicConsolidation(base.TestCase):
instance_0_weight_assert, instance_0_weight_assert,
self.strategy.calculate_weight(instance_0, cores, disk, mem)) self.strategy.calculate_weight(instance_0, cores, disk, mem))
def test_exception_model(self):
self.m_model.return_value = None
self.assertRaises(
exception.ClusterStateNotDefined, self.strategy.execute)
def test_exception_cluster_empty(self):
model = model_root.ModelRoot()
self.m_model.return_value = model
self.assertRaises(exception.ClusterEmpty, self.strategy.execute)
def test_check_migration(self): def test_check_migration(self):
model = self.fake_cluster.generate_scenario_3_with_2_nodes() model = self.fake_c_cluster.generate_scenario_3_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
all_instances = model.get_all_instances() all_instances = model.get_all_instances()
all_nodes = model.get_all_compute_nodes() all_nodes = model.get_all_compute_nodes()
@@ -182,8 +153,8 @@ class TestBasicConsolidation(base.TestCase):
self.strategy.check_migration(node0, node0, instance0) self.strategy.check_migration(node0, node0, instance0)
def test_threshold(self): def test_threshold(self):
model = self.fake_cluster.generate_scenario_3_with_2_nodes() model = self.fake_c_cluster.generate_scenario_3_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
all_nodes = model.get_all_compute_nodes() all_nodes = model.get_all_compute_nodes()
node0 = all_nodes[list(all_nodes.keys())[0]] node0 = all_nodes[list(all_nodes.keys())[0]]
@@ -192,16 +163,16 @@ class TestBasicConsolidation(base.TestCase):
node0, 1000, 1000, 1000)) node0, 1000, 1000, 1000))
def test_basic_consolidation_works_on_model_copy(self): def test_basic_consolidation_works_on_model_copy(self):
model = self.fake_cluster.generate_scenario_3_with_2_nodes() model = self.fake_c_cluster.generate_scenario_3_with_2_nodes()
self.m_model.return_value = copy.deepcopy(model) self.m_c_model.return_value = copy.deepcopy(model)
self.assertTrue(model_root.ModelRoot.is_isomorphic( self.assertTrue(model_root.ModelRoot.is_isomorphic(
model, self.strategy.compute_model)) model, self.strategy.compute_model))
self.assertIsNot(model, self.strategy.compute_model) self.assertIsNot(model, self.strategy.compute_model)
def test_basic_consolidation_migration(self): def test_basic_consolidation_migration(self):
model = self.fake_cluster.generate_scenario_3_with_2_nodes() model = self.fake_c_cluster.generate_scenario_3_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
solution = self.strategy.execute() solution = self.strategy.execute()
@@ -218,8 +189,8 @@ class TestBasicConsolidation(base.TestCase):
self.assertEqual(expected_power_state, num_node_state_change) self.assertEqual(expected_power_state, num_node_state_change)
def test_basic_consolidation_execute_scenario_8_with_4_nodes(self): def test_basic_consolidation_execute_scenario_8_with_4_nodes(self):
model = self.fake_cluster.generate_scenario_8_with_4_nodes() model = self.fake_c_cluster.generate_scenario_8_with_4_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
solution = self.strategy.execute() solution = self.strategy.execute()
@@ -240,20 +211,12 @@ class TestBasicConsolidation(base.TestCase):
self.assertEqual(expected_power_state, num_node_state_change) self.assertEqual(expected_power_state, num_node_state_change)
self.assertEqual(expected_global_efficacy, global_efficacy_value) self.assertEqual(expected_global_efficacy, global_efficacy_value)
def test_exception_stale_cdm(self):
self.fake_cluster.set_cluster_data_model_as_stale()
self.m_model.return_value = self.fake_cluster.cluster_data_model
self.assertRaises(
exception.ClusterStateNotDefined,
self.strategy.execute)
# calculate_weight # calculate_weight
def test_execute_no_workload(self): def test_execute_no_workload(self):
model = ( model = (
self.fake_cluster self.fake_c_cluster
.generate_scenario_4_with_1_node_no_instance()) .generate_scenario_4_with_1_node_no_instance())
self.m_model.return_value = model self.m_c_model.return_value = model
with mock.patch.object( with mock.patch.object(
strategies.BasicConsolidation, 'calculate_weight' strategies.BasicConsolidation, 'calculate_weight'
@@ -265,8 +228,8 @@ class TestBasicConsolidation(base.TestCase):
solution.efficacy.global_efficacy[0].get('value')) solution.efficacy.global_efficacy[0].get('value'))
def test_check_parameters(self): def test_check_parameters(self):
model = self.fake_cluster.generate_scenario_3_with_2_nodes() model = self.fake_c_cluster.generate_scenario_3_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
solution = self.strategy.execute() solution = self.strategy.execute()
loader = default.DefaultActionLoader() loader = default.DefaultActionLoader()
for action in solution.actions: for action in solution.actions:
@@ -275,8 +238,8 @@ class TestBasicConsolidation(base.TestCase):
loaded_action.validate_parameters() loaded_action.validate_parameters()
"""def test_periods(self): """def test_periods(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
node_1 = model.get_node_by_uuid("Node_1") node_1 = model.get_node_by_uuid("Node_1")
p_ceilometer = mock.patch.object( p_ceilometer = mock.patch.object(
strategies.BasicConsolidation, "ceilometer") strategies.BasicConsolidation, "ceilometer")

View File

@@ -18,38 +18,15 @@ import mock
from watcher.applier.loading import default from watcher.applier.loading import default
from watcher.common import utils from watcher.common import utils
from watcher.decision_engine.model import model_root
from watcher.decision_engine.strategy import strategies from watcher.decision_engine.strategy import strategies
from watcher.tests import base from watcher.tests.decision_engine.strategy.strategies.test_base \
from watcher.tests.decision_engine.model import faker_cluster_state import TestBaseStrategy
class TestDummyStrategy(base.TestCase): class TestDummyStrategy(TestBaseStrategy):
def setUp(self): def setUp(self):
super(TestDummyStrategy, self).setUp() super(TestDummyStrategy, self).setUp()
# fake cluster
self.fake_cluster = faker_cluster_state.FakerModelCollector()
p_model = mock.patch.object(
strategies.DummyStrategy, "compute_model",
new_callable=mock.PropertyMock)
self.m_model = p_model.start()
self.addCleanup(p_model.stop)
p_audit_scope = mock.patch.object(
strategies.DummyStrategy, "audit_scope",
new_callable=mock.PropertyMock
)
self.m_audit_scope = p_audit_scope.start()
self.addCleanup(p_audit_scope.stop)
self.m_audit_scope.return_value = mock.Mock()
self.m_model.return_value = model_root.ModelRoot()
self.strategy = strategies.DummyStrategy(config=mock.Mock())
self.m_model.return_value = model_root.ModelRoot()
self.strategy = strategies.DummyStrategy(config=mock.Mock()) self.strategy = strategies.DummyStrategy(config=mock.Mock())
def test_dummy_strategy(self): def test_dummy_strategy(self):
@@ -60,8 +37,8 @@ class TestDummyStrategy(base.TestCase):
self.assertEqual(3, len(solution.actions)) self.assertEqual(3, len(solution.actions))
def test_check_parameters(self): def test_check_parameters(self):
model = self.fake_cluster.generate_scenario_3_with_2_nodes() model = self.fake_c_cluster.generate_scenario_3_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
self.strategy.input_parameters = utils.Struct() self.strategy.input_parameters = utils.Struct()
self.strategy.input_parameters.update({'para1': 4.0, 'para2': 'Hi'}) self.strategy.input_parameters.update({'para1': 4.0, 'para2': 'Hi'})
solution = self.strategy.execute() solution = self.strategy.execute()

View File

@@ -18,26 +18,15 @@ import mock
from watcher.applier.loading import default from watcher.applier.loading import default
from watcher.common import utils from watcher.common import utils
from watcher.decision_engine.model import model_root
from watcher.decision_engine.strategy import strategies from watcher.decision_engine.strategy import strategies
from watcher.tests import base from watcher.tests.decision_engine.strategy.strategies.test_base \
from watcher.tests.decision_engine.model import faker_cluster_state import TestBaseStrategy
class TestDummyWithScorer(base.TestCase): class TestDummyWithScorer(TestBaseStrategy):
def setUp(self): def setUp(self):
super(TestDummyWithScorer, self).setUp() super(TestDummyWithScorer, self).setUp()
# fake cluster
self.fake_cluster = faker_cluster_state.FakerModelCollector()
p_model = mock.patch.object(
strategies.DummyWithScorer, "compute_model",
new_callable=mock.PropertyMock)
self.m_model = p_model.start()
self.addCleanup(p_model.stop)
self.m_model.return_value = model_root.ModelRoot()
self.strategy = strategies.DummyWithScorer(config=mock.Mock()) self.strategy = strategies.DummyWithScorer(config=mock.Mock())
def test_dummy_with_scorer(self): def test_dummy_with_scorer(self):
@@ -48,8 +37,8 @@ class TestDummyWithScorer(base.TestCase):
self.assertEqual(4, len(solution.actions)) self.assertEqual(4, len(solution.actions))
def test_check_parameters(self): def test_check_parameters(self):
model = self.fake_cluster.generate_scenario_3_with_2_nodes() model = self.fake_c_cluster.generate_scenario_3_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
self.strategy.input_parameters = utils.Struct() self.strategy.input_parameters = utils.Struct()
self.strategy.input_parameters.update({'param1': 4.0, 'param2': 'Hi'}) self.strategy.input_parameters.update({'param1': 4.0, 'param2': 'Hi'})
solution = self.strategy.execute() solution = self.strategy.execute()

View File

@@ -21,46 +21,17 @@ import mock
from watcher.common import exception from watcher.common import exception
from watcher.decision_engine.model import element from watcher.decision_engine.model import element
from watcher.decision_engine.model import model_root
from watcher.decision_engine.strategy import strategies from watcher.decision_engine.strategy import strategies
from watcher.tests import base from watcher.tests.decision_engine.strategy.strategies.test_base \
from watcher.tests.decision_engine.model import faker_cluster_state import TestBaseStrategy
class TestHostMaintenance(base.TestCase): class TestHostMaintenance(TestBaseStrategy):
def setUp(self): def setUp(self):
super(TestHostMaintenance, self).setUp() super(TestHostMaintenance, self).setUp()
# fake cluster
self.fake_cluster = faker_cluster_state.FakerModelCollector()
p_model = mock.patch.object(
strategies.HostMaintenance, "compute_model",
new_callable=mock.PropertyMock)
self.m_model = p_model.start()
self.addCleanup(p_model.stop)
p_audit_scope = mock.patch.object(
strategies.HostMaintenance, "audit_scope",
new_callable=mock.PropertyMock
)
self.m_audit_scope = p_audit_scope.start()
self.addCleanup(p_audit_scope.stop)
self.m_audit_scope.return_value = mock.Mock()
self.m_model.return_value = model_root.ModelRoot()
self.strategy = strategies.HostMaintenance(config=mock.Mock()) self.strategy = strategies.HostMaintenance(config=mock.Mock())
def test_exception_stale_cdm(self):
self.fake_cluster.set_cluster_data_model_as_stale()
self.m_model.return_value = self.fake_cluster.cluster_data_model
self.assertRaises(
exception.ClusterStateNotDefined,
self.strategy.execute)
def test_get_instance_state_str(self): def test_get_instance_state_str(self):
mock_instance = mock.MagicMock(state="active") mock_instance = mock.MagicMock(state="active")
self.assertEqual("active", self.assertEqual("active",
@@ -92,39 +63,39 @@ class TestHostMaintenance(base.TestCase):
mock_node) mock_node)
def test_get_node_capacity(self): def test_get_node_capacity(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
node_0 = model.get_node_by_uuid("Node_0") node_0 = model.get_node_by_uuid("Node_0")
node_capacity = dict(cpu=40, ram=132, disk=250) node_capacity = dict(cpu=40, ram=132, disk=250)
self.assertEqual(node_capacity, self.assertEqual(node_capacity,
self.strategy.get_node_capacity(node_0)) self.strategy.get_node_capacity(node_0))
def test_get_node_used(self): def test_get_node_used(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
node_0 = model.get_node_by_uuid("Node_0") node_0 = model.get_node_by_uuid("Node_0")
node_used = dict(cpu=20, ram=4, disk=40) node_used = dict(cpu=20, ram=4, disk=40)
self.assertEqual(node_used, self.assertEqual(node_used,
self.strategy.get_node_used(node_0)) self.strategy.get_node_used(node_0))
def test_get_node_free(self): def test_get_node_free(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
node_0 = model.get_node_by_uuid("Node_0") node_0 = model.get_node_by_uuid("Node_0")
node_free = dict(cpu=20, ram=128, disk=210) node_free = dict(cpu=20, ram=128, disk=210)
self.assertEqual(node_free, self.assertEqual(node_free,
self.strategy.get_node_free(node_0)) self.strategy.get_node_free(node_0))
def test_host_fits(self): def test_host_fits(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
node_0 = model.get_node_by_uuid("Node_0") node_0 = model.get_node_by_uuid("Node_0")
node_1 = model.get_node_by_uuid("Node_1") node_1 = model.get_node_by_uuid("Node_1")
self.assertTrue(self.strategy.host_fits(node_0, node_1)) self.assertTrue(self.strategy.host_fits(node_0, node_1))
def test_add_action_enable_compute_node(self): def test_add_action_enable_compute_node(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
node_0 = model.get_node_by_uuid('Node_0') node_0 = model.get_node_by_uuid('Node_0')
self.strategy.add_action_enable_compute_node(node_0) self.strategy.add_action_enable_compute_node(node_0)
expected = [{'action_type': 'change_nova_service_state', expected = [{'action_type': 'change_nova_service_state',
@@ -134,8 +105,8 @@ class TestHostMaintenance(base.TestCase):
self.assertEqual(expected, self.strategy.solution.actions) self.assertEqual(expected, self.strategy.solution.actions)
def test_add_action_maintain_compute_node(self): def test_add_action_maintain_compute_node(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
node_0 = model.get_node_by_uuid('Node_0') node_0 = model.get_node_by_uuid('Node_0')
self.strategy.add_action_maintain_compute_node(node_0) self.strategy.add_action_maintain_compute_node(node_0)
expected = [{'action_type': 'change_nova_service_state', expected = [{'action_type': 'change_nova_service_state',
@@ -146,8 +117,8 @@ class TestHostMaintenance(base.TestCase):
self.assertEqual(expected, self.strategy.solution.actions) self.assertEqual(expected, self.strategy.solution.actions)
def test_instance_migration(self): def test_instance_migration(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
node_0 = model.get_node_by_uuid('Node_0') node_0 = model.get_node_by_uuid('Node_0')
node_1 = model.get_node_by_uuid('Node_1') node_1 = model.get_node_by_uuid('Node_1')
instance_0 = model.get_instance_by_uuid("INSTANCE_0") instance_0 = model.get_instance_by_uuid("INSTANCE_0")
@@ -161,8 +132,8 @@ class TestHostMaintenance(base.TestCase):
self.assertEqual(expected, self.strategy.solution.actions) self.assertEqual(expected, self.strategy.solution.actions)
def test_instance_migration_without_dest_node(self): def test_instance_migration_without_dest_node(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
node_0 = model.get_node_by_uuid('Node_0') node_0 = model.get_node_by_uuid('Node_0')
instance_0 = model.get_instance_by_uuid("INSTANCE_0") instance_0 = model.get_instance_by_uuid("INSTANCE_0")
self.strategy.instance_migration(instance_0, node_0) self.strategy.instance_migration(instance_0, node_0)
@@ -174,8 +145,8 @@ class TestHostMaintenance(base.TestCase):
self.assertEqual(expected, self.strategy.solution.actions) self.assertEqual(expected, self.strategy.solution.actions)
def test_host_migration(self): def test_host_migration(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
node_0 = model.get_node_by_uuid('Node_0') node_0 = model.get_node_by_uuid('Node_0')
node_1 = model.get_node_by_uuid('Node_1') node_1 = model.get_node_by_uuid('Node_1')
instance_0 = model.get_instance_by_uuid("INSTANCE_0") instance_0 = model.get_instance_by_uuid("INSTANCE_0")
@@ -196,29 +167,34 @@ class TestHostMaintenance(base.TestCase):
self.assertIn(expected[1], self.strategy.solution.actions) self.assertIn(expected[1], self.strategy.solution.actions)
def test_safe_maintain(self): def test_safe_maintain(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
node_0 = model.get_node_by_uuid('Node_0') node_0 = model.get_node_by_uuid('Node_0')
node_1 = model.get_node_by_uuid('Node_1') node_1 = model.get_node_by_uuid('Node_1')
self.assertFalse(self.strategy.safe_maintain(node_0)) self.assertFalse(self.strategy.safe_maintain(node_0))
self.assertFalse(self.strategy.safe_maintain(node_1)) self.assertFalse(self.strategy.safe_maintain(node_1))
model = self.fake_cluster.generate_scenario_1_with_all_nodes_disable() model = self.fake_c_cluster.\
self.m_model.return_value = model generate_scenario_1_with_all_nodes_disable()
self.m_c_model.return_value = model
node_0 = model.get_node_by_uuid('Node_0') node_0 = model.get_node_by_uuid('Node_0')
self.assertTrue(self.strategy.safe_maintain(node_0)) self.assertTrue(self.strategy.safe_maintain(node_0))
def test_try_maintain(self): def test_try_maintain(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
node_1 = model.get_node_by_uuid('Node_1') node_1 = model.get_node_by_uuid('Node_1')
self.strategy.try_maintain(node_1) self.strategy.try_maintain(node_1)
self.assertEqual(2, len(self.strategy.solution.actions)) self.assertEqual(2, len(self.strategy.solution.actions))
def test_exception_compute_node_not_found(self):
self.m_c_model.return_value = self.fake_c_cluster.build_scenario_1()
self.assertRaises(exception.ComputeNodeNotFound, self.strategy.execute)
def test_strategy(self): def test_strategy(self):
model = self.fake_cluster. \ model = self.fake_c_cluster. \
generate_scenario_9_with_3_active_plus_1_disabled_nodes() generate_scenario_9_with_3_active_plus_1_disabled_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
node_2 = model.get_node_by_uuid('Node_2') node_2 = model.get_node_by_uuid('Node_2')
node_3 = model.get_node_by_uuid('Node_3') node_3 = model.get_node_by_uuid('Node_3')
instance_4 = model.get_instance_by_uuid("INSTANCE_4") instance_4 = model.get_instance_by_uuid("INSTANCE_4")

View File

@@ -20,17 +20,15 @@ import collections
import mock import mock
from watcher.applier.loading import default from watcher.applier.loading import default
from watcher.common import exception
from watcher.common import utils from watcher.common import utils
from watcher.decision_engine.model import model_root
from watcher.decision_engine.strategy import strategies from watcher.decision_engine.strategy import strategies
from watcher.tests import base
from watcher.tests.decision_engine.model import ceilometer_metrics from watcher.tests.decision_engine.model import ceilometer_metrics
from watcher.tests.decision_engine.model import faker_cluster_state
from watcher.tests.decision_engine.model import gnocchi_metrics from watcher.tests.decision_engine.model import gnocchi_metrics
from watcher.tests.decision_engine.strategy.strategies.test_base \
import TestBaseStrategy
class TestNoisyNeighbor(base.TestCase): class TestNoisyNeighbor(TestBaseStrategy):
scenarios = [ scenarios = [
("Ceilometer", ("Ceilometer",
@@ -45,14 +43,6 @@ class TestNoisyNeighbor(base.TestCase):
super(TestNoisyNeighbor, self).setUp() super(TestNoisyNeighbor, self).setUp()
# fake metrics # fake metrics
self.f_metrics = self.fake_datasource_cls() self.f_metrics = self.fake_datasource_cls()
# fake cluster
self.fake_cluster = faker_cluster_state.FakerModelCollector()
p_model = mock.patch.object(
strategies.NoisyNeighbor, "compute_model",
new_callable=mock.PropertyMock)
self.m_model = p_model.start()
self.addCleanup(p_model.stop)
p_datasource = mock.patch.object( p_datasource = mock.patch.object(
strategies.NoisyNeighbor, "datasource_backend", strategies.NoisyNeighbor, "datasource_backend",
@@ -60,16 +50,6 @@ class TestNoisyNeighbor(base.TestCase):
self.m_datasource = p_datasource.start() self.m_datasource = p_datasource.start()
self.addCleanup(p_datasource.stop) self.addCleanup(p_datasource.stop)
p_audit_scope = mock.patch.object(
strategies.NoisyNeighbor, "audit_scope",
new_callable=mock.PropertyMock
)
self.m_audit_scope = p_audit_scope.start()
self.addCleanup(p_audit_scope.stop)
self.m_audit_scope.return_value = mock.Mock()
self.m_model.return_value = model_root.ModelRoot()
self.m_datasource.return_value = mock.Mock( self.m_datasource.return_value = mock.Mock(
get_instance_l3_cache_usage=self.f_metrics.mock_get_statistics_nn) get_instance_l3_cache_usage=self.f_metrics.mock_get_statistics_nn)
self.strategy = strategies.NoisyNeighbor(config=mock.Mock()) self.strategy = strategies.NoisyNeighbor(config=mock.Mock())
@@ -81,8 +61,8 @@ class TestNoisyNeighbor(base.TestCase):
self.strategy.threshold = 100 self.strategy.threshold = 100
def test_calc_used_resource(self): def test_calc_used_resource(self):
model = self.fake_cluster.generate_scenario_3_with_2_nodes() model = self.fake_c_cluster.generate_scenario_3_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
node = model.get_node_by_uuid('Node_0') node = model.get_node_by_uuid('Node_0')
cores_used, mem_used, disk_used = self.strategy.calc_used_resource( cores_used, mem_used, disk_used = self.strategy.calc_used_resource(
node) node)
@@ -92,8 +72,8 @@ class TestNoisyNeighbor(base.TestCase):
def test_group_hosts(self): def test_group_hosts(self):
self.strategy.cache_threshold = 35 self.strategy.cache_threshold = 35
self.strategy.period = 100 self.strategy.period = 100
model = self.fake_cluster.generate_scenario_7_with_2_nodes() model = self.fake_c_cluster.generate_scenario_7_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
node_uuid = 'Node_1' node_uuid = 'Node_1'
n1, n2 = self.strategy.group_hosts() n1, n2 = self.strategy.group_hosts()
self.assertTrue(node_uuid in n1) self.assertTrue(node_uuid in n1)
@@ -104,8 +84,8 @@ class TestNoisyNeighbor(base.TestCase):
def test_find_priority_instance(self): def test_find_priority_instance(self):
self.strategy.cache_threshold = 35 self.strategy.cache_threshold = 35
self.strategy.period = 100 self.strategy.period = 100
model = self.fake_cluster.generate_scenario_7_with_2_nodes() model = self.fake_c_cluster.generate_scenario_7_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
potential_prio_inst = model.get_instance_by_uuid('INSTANCE_3') potential_prio_inst = model.get_instance_by_uuid('INSTANCE_3')
inst_res = self.strategy.find_priority_instance(potential_prio_inst) inst_res = self.strategy.find_priority_instance(potential_prio_inst)
self.assertEqual('INSTANCE_3', inst_res.uuid) self.assertEqual('INSTANCE_3', inst_res.uuid)
@@ -113,15 +93,15 @@ class TestNoisyNeighbor(base.TestCase):
def test_find_noisy_instance(self): def test_find_noisy_instance(self):
self.strategy.cache_threshold = 35 self.strategy.cache_threshold = 35
self.strategy.period = 100 self.strategy.period = 100
model = self.fake_cluster.generate_scenario_7_with_2_nodes() model = self.fake_c_cluster.generate_scenario_7_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
potential_noisy_inst = model.get_instance_by_uuid('INSTANCE_4') potential_noisy_inst = model.get_instance_by_uuid('INSTANCE_4')
inst_res = self.strategy.find_noisy_instance(potential_noisy_inst) inst_res = self.strategy.find_noisy_instance(potential_noisy_inst)
self.assertEqual('INSTANCE_4', inst_res.uuid) self.assertEqual('INSTANCE_4', inst_res.uuid)
def test_filter_destination_hosts(self): def test_filter_destination_hosts(self):
model = self.fake_cluster.generate_scenario_7_with_2_nodes() model = self.fake_c_cluster.generate_scenario_7_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
self.strategy.cache_threshold = 35 self.strategy.cache_threshold = 35
self.strategy.period = 100 self.strategy.period = 100
n1, n2 = self.strategy.group_hosts() n1, n2 = self.strategy.group_hosts()
@@ -134,34 +114,12 @@ class TestNoisyNeighbor(base.TestCase):
self.assertEqual(1, len(dest_hosts)) self.assertEqual(1, len(dest_hosts))
self.assertEqual('Node_0', dest_hosts[0].uuid) self.assertEqual('Node_0', dest_hosts[0].uuid)
def test_exception_model(self):
self.m_model.return_value = None
self.assertRaises(
exception.ClusterStateNotDefined, self.strategy.execute)
def test_exception_cluster_empty(self):
model = model_root.ModelRoot()
self.m_model.return_value = model
self.assertRaises(exception.ClusterEmpty, self.strategy.execute)
def test_exception_stale_cdm(self):
self.fake_cluster.set_cluster_data_model_as_stale()
self.m_model.return_value = self.fake_cluster.cluster_data_model
self.assertRaises(
exception.ClusterStateNotDefined,
self.strategy.execute)
def test_execute_cluster_empty(self):
model = model_root.ModelRoot()
self.m_model.return_value = model
self.assertRaises(exception.ClusterEmpty, self.strategy.execute)
def test_execute_no_workload(self): def test_execute_no_workload(self):
self.strategy.cache_threshold = 35 self.strategy.cache_threshold = 35
self.strategy.period = 100 self.strategy.period = 100
model = self.fake_cluster.generate_scenario_4_with_1_node_no_instance() model = self.fake_c_cluster.\
self.m_model.return_value = model generate_scenario_4_with_1_node_no_instance()
self.m_c_model.return_value = model
solution = self.strategy.execute() solution = self.strategy.execute()
self.assertEqual([], solution.actions) self.assertEqual([], solution.actions)
@@ -169,8 +127,8 @@ class TestNoisyNeighbor(base.TestCase):
def test_execute(self): def test_execute(self):
self.strategy.cache_threshold = 35 self.strategy.cache_threshold = 35
self.strategy.period = 100 self.strategy.period = 100
model = self.fake_cluster.generate_scenario_7_with_2_nodes() model = self.fake_c_cluster.generate_scenario_7_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
solution = self.strategy.execute() solution = self.strategy.execute()
actions_counter = collections.Counter( actions_counter = collections.Counter(
[action.get('action_type') for action in solution.actions]) [action.get('action_type') for action in solution.actions])
@@ -179,8 +137,8 @@ class TestNoisyNeighbor(base.TestCase):
self.assertEqual(1, num_migrations) self.assertEqual(1, num_migrations)
def test_check_parameters(self): def test_check_parameters(self):
model = self.fake_cluster.generate_scenario_3_with_2_nodes() model = self.fake_c_cluster.generate_scenario_3_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
solution = self.strategy.execute() solution = self.strategy.execute()
loader = default.DefaultActionLoader() loader = default.DefaultActionLoader()
for action in solution.actions: for action in solution.actions:

View File

@@ -20,17 +20,15 @@ import collections
import mock import mock
from watcher.applier.loading import default from watcher.applier.loading import default
from watcher.common import exception
from watcher.common import utils from watcher.common import utils
from watcher.decision_engine.model import model_root
from watcher.decision_engine.strategy import strategies from watcher.decision_engine.strategy import strategies
from watcher.tests import base
from watcher.tests.decision_engine.model import ceilometer_metrics from watcher.tests.decision_engine.model import ceilometer_metrics
from watcher.tests.decision_engine.model import faker_cluster_state
from watcher.tests.decision_engine.model import gnocchi_metrics from watcher.tests.decision_engine.model import gnocchi_metrics
from watcher.tests.decision_engine.strategy.strategies.test_base \
import TestBaseStrategy
class TestOutletTempControl(base.TestCase): class TestOutletTempControl(TestBaseStrategy):
scenarios = [ scenarios = [
("Ceilometer", ("Ceilometer",
@@ -46,31 +44,12 @@ class TestOutletTempControl(base.TestCase):
# fake metrics # fake metrics
self.fake_metrics = self.fake_datasource_cls() self.fake_metrics = self.fake_datasource_cls()
# fake cluster
self.fake_cluster = faker_cluster_state.FakerModelCollector()
p_model = mock.patch.object(
strategies.OutletTempControl, "compute_model",
new_callable=mock.PropertyMock)
self.m_model = p_model.start()
self.addCleanup(p_model.stop)
p_datasource = mock.patch.object( p_datasource = mock.patch.object(
strategies.OutletTempControl, 'datasource_backend', strategies.OutletTempControl, 'datasource_backend',
new_callable=mock.PropertyMock) new_callable=mock.PropertyMock)
self.m_datasource = p_datasource.start() self.m_datasource = p_datasource.start()
self.addCleanup(p_datasource.stop) self.addCleanup(p_datasource.stop)
p_audit_scope = mock.patch.object(
strategies.OutletTempControl, "audit_scope",
new_callable=mock.PropertyMock
)
self.m_audit_scope = p_audit_scope.start()
self.addCleanup(p_audit_scope.stop)
self.m_audit_scope.return_value = mock.Mock()
self.m_model.return_value = model_root.ModelRoot()
self.m_datasource.return_value = mock.Mock( self.m_datasource.return_value = mock.Mock(
statistic_aggregation=self.fake_metrics.mock_get_statistics, statistic_aggregation=self.fake_metrics.mock_get_statistics,
NAME=self.fake_metrics.NAME) NAME=self.fake_metrics.NAME)
@@ -82,8 +61,8 @@ class TestOutletTempControl(base.TestCase):
self.strategy.threshold = 34.3 self.strategy.threshold = 34.3
def test_calc_used_resource(self): def test_calc_used_resource(self):
model = self.fake_cluster.generate_scenario_3_with_2_nodes() model = self.fake_c_cluster.generate_scenario_3_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
node = model.get_node_by_uuid('Node_0') node = model.get_node_by_uuid('Node_0')
cores_used, mem_used, disk_used = self.strategy.calc_used_resource( cores_used, mem_used, disk_used = self.strategy.calc_used_resource(
node) node)
@@ -91,15 +70,15 @@ class TestOutletTempControl(base.TestCase):
self.assertEqual((10, 2, 20), (cores_used, mem_used, disk_used)) self.assertEqual((10, 2, 20), (cores_used, mem_used, disk_used))
def test_group_hosts_by_outlet_temp(self): def test_group_hosts_by_outlet_temp(self):
model = self.fake_cluster.generate_scenario_3_with_2_nodes() model = self.fake_c_cluster.generate_scenario_3_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
n1, n2 = self.strategy.group_hosts_by_outlet_temp() n1, n2 = self.strategy.group_hosts_by_outlet_temp()
self.assertEqual('Node_1', n1[0]['node'].uuid) self.assertEqual('Node_1', n1[0]['node'].uuid)
self.assertEqual('Node_0', n2[0]['node'].uuid) self.assertEqual('Node_0', n2[0]['node'].uuid)
def test_choose_instance_to_migrate(self): def test_choose_instance_to_migrate(self):
model = self.fake_cluster.generate_scenario_3_with_2_nodes() model = self.fake_c_cluster.generate_scenario_3_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
n1, n2 = self.strategy.group_hosts_by_outlet_temp() n1, n2 = self.strategy.group_hosts_by_outlet_temp()
instance_to_mig = self.strategy.choose_instance_to_migrate(n1) instance_to_mig = self.strategy.choose_instance_to_migrate(n1)
self.assertEqual('Node_1', instance_to_mig[0].uuid) self.assertEqual('Node_1', instance_to_mig[0].uuid)
@@ -107,47 +86,25 @@ class TestOutletTempControl(base.TestCase):
instance_to_mig[1].uuid) instance_to_mig[1].uuid)
def test_filter_dest_servers(self): def test_filter_dest_servers(self):
model = self.fake_cluster.generate_scenario_3_with_2_nodes() model = self.fake_c_cluster.generate_scenario_3_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
n1, n2 = self.strategy.group_hosts_by_outlet_temp() n1, n2 = self.strategy.group_hosts_by_outlet_temp()
instance_to_mig = self.strategy.choose_instance_to_migrate(n1) instance_to_mig = self.strategy.choose_instance_to_migrate(n1)
dest_hosts = self.strategy.filter_dest_servers(n2, instance_to_mig[1]) dest_hosts = self.strategy.filter_dest_servers(n2, instance_to_mig[1])
self.assertEqual(1, len(dest_hosts)) self.assertEqual(1, len(dest_hosts))
self.assertEqual('Node_0', dest_hosts[0]['node'].uuid) self.assertEqual('Node_0', dest_hosts[0]['node'].uuid)
def test_exception_model(self):
self.m_model.return_value = None
self.assertRaises(
exception.ClusterStateNotDefined, self.strategy.execute)
def test_exception_cluster_empty(self):
model = model_root.ModelRoot()
self.m_model.return_value = model
self.assertRaises(exception.ClusterEmpty, self.strategy.execute)
def test_exception_stale_cdm(self):
self.fake_cluster.set_cluster_data_model_as_stale()
self.m_model.return_value = self.fake_cluster.cluster_data_model
self.assertRaises(
exception.ClusterStateNotDefined,
self.strategy.execute)
def test_execute_cluster_empty(self):
model = model_root.ModelRoot()
self.m_model.return_value = model
self.assertRaises(exception.ClusterEmpty, self.strategy.execute)
def test_execute_no_workload(self): def test_execute_no_workload(self):
model = self.fake_cluster.generate_scenario_4_with_1_node_no_instance() model = self.fake_c_cluster.\
self.m_model.return_value = model generate_scenario_4_with_1_node_no_instance()
self.m_c_model.return_value = model
solution = self.strategy.execute() solution = self.strategy.execute()
self.assertEqual([], solution.actions) self.assertEqual([], solution.actions)
def test_execute(self): def test_execute(self):
model = self.fake_cluster.generate_scenario_3_with_2_nodes() model = self.fake_c_cluster.generate_scenario_3_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
solution = self.strategy.execute() solution = self.strategy.execute()
actions_counter = collections.Counter( actions_counter = collections.Counter(
[action.get('action_type') for action in solution.actions]) [action.get('action_type') for action in solution.actions])
@@ -156,8 +113,8 @@ class TestOutletTempControl(base.TestCase):
self.assertEqual(1, num_migrations) self.assertEqual(1, num_migrations)
def test_check_parameters(self): def test_check_parameters(self):
model = self.fake_cluster.generate_scenario_3_with_2_nodes() model = self.fake_c_cluster.generate_scenario_3_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
solution = self.strategy.execute() solution = self.strategy.execute()
loader = default.DefaultActionLoader() loader = default.DefaultActionLoader()
for action in solution.actions: for action in solution.actions:

View File

@@ -20,11 +20,11 @@ import mock
from watcher.common import clients from watcher.common import clients
from watcher.common import utils from watcher.common import utils
from watcher.decision_engine.strategy import strategies from watcher.decision_engine.strategy import strategies
from watcher.tests import base from watcher.tests.decision_engine.strategy.strategies.test_base \
from watcher.tests.decision_engine.model import faker_cluster_and_metrics import TestBaseStrategy
class TestSavingEnergy(base.TestCase): class TestSavingEnergy(TestBaseStrategy):
def setUp(self): def setUp(self):
super(TestSavingEnergy, self).setUp() super(TestSavingEnergy, self).setUp()
@@ -37,15 +37,6 @@ class TestSavingEnergy(base.TestCase):
'uuid': '922d4762-0bc5-4b30-9cb9-48ab644dd862'} 'uuid': '922d4762-0bc5-4b30-9cb9-48ab644dd862'}
self.fake_nodes = [mock_node1, mock_node2] self.fake_nodes = [mock_node1, mock_node2]
# fake cluster
self.fake_cluster = faker_cluster_and_metrics.FakerModelCollector()
p_model = mock.patch.object(
strategies.SavingEnergy, "compute_model",
new_callable=mock.PropertyMock)
self.m_model = p_model.start()
self.addCleanup(p_model.stop)
p_ironic = mock.patch.object( p_ironic = mock.patch.object(
clients.OpenStackClients, 'ironic') clients.OpenStackClients, 'ironic')
self.m_ironic = p_ironic.start() self.m_ironic = p_ironic.start()
@@ -56,22 +47,10 @@ class TestSavingEnergy(base.TestCase):
self.m_nova = p_nova.start() self.m_nova = p_nova.start()
self.addCleanup(p_nova.stop) self.addCleanup(p_nova.stop)
p_model = mock.patch.object(
strategies.SavingEnergy, "compute_model",
new_callable=mock.PropertyMock)
self.m_model = p_model.start()
self.addCleanup(p_model.stop)
p_audit_scope = mock.patch.object(
strategies.SavingEnergy, "audit_scope",
new_callable=mock.PropertyMock
)
self.m_audit_scope = p_audit_scope.start()
self.addCleanup(p_audit_scope.stop)
self.m_audit_scope.return_value = mock.Mock()
self.m_ironic.node.list.return_value = self.fake_nodes self.m_ironic.node.list.return_value = self.fake_nodes
self.m_c_model.return_value = self.fake_c_cluster.generate_scenario_1()
self.strategy = strategies.SavingEnergy( self.strategy = strategies.SavingEnergy(
config=mock.Mock()) config=mock.Mock())
self.strategy.input_parameters = utils.Struct() self.strategy.input_parameters = utils.Struct()
@@ -102,8 +81,6 @@ class TestSavingEnergy(base.TestCase):
'running_vms': 2, 'service': {'host': 'Node_1'}, 'state': 'up'} 'running_vms': 2, 'service': {'host': 'Node_1'}, 'state': 'up'}
self.m_nova.hypervisors.get.side_effect = [mock_hyper1, mock_hyper2] self.m_nova.hypervisors.get.side_effect = [mock_hyper1, mock_hyper2]
model = self.fake_cluster.generate_scenario_1()
self.m_model.return_value = model
self.strategy.get_hosts_pool() self.strategy.get_hosts_pool()
self.assertEqual(len(self.strategy.with_vms_node_pool), 2) self.assertEqual(len(self.strategy.with_vms_node_pool), 2)
@@ -129,8 +106,6 @@ class TestSavingEnergy(base.TestCase):
'running_vms': 0, 'service': {'host': 'Node_1'}, 'state': 'up'} 'running_vms': 0, 'service': {'host': 'Node_1'}, 'state': 'up'}
self.m_nova.hypervisors.get.side_effect = [mock_hyper1, mock_hyper2] self.m_nova.hypervisors.get.side_effect = [mock_hyper1, mock_hyper2]
model = self.fake_cluster.generate_scenario_1()
self.m_model.return_value = model
self.strategy.get_hosts_pool() self.strategy.get_hosts_pool()
self.assertEqual(len(self.strategy.with_vms_node_pool), 0) self.assertEqual(len(self.strategy.with_vms_node_pool), 0)
@@ -156,8 +131,6 @@ class TestSavingEnergy(base.TestCase):
'running_vms': 0, 'service': {'host': 'Node_1'}, 'state': 'up'} 'running_vms': 0, 'service': {'host': 'Node_1'}, 'state': 'up'}
self.m_nova.hypervisors.get.side_effect = [mock_hyper1, mock_hyper2] self.m_nova.hypervisors.get.side_effect = [mock_hyper1, mock_hyper2]
model = self.fake_cluster.generate_scenario_1()
self.m_model.return_value = model
self.strategy.get_hosts_pool() self.strategy.get_hosts_pool()
self.assertEqual(len(self.strategy.with_vms_node_pool), 0) self.assertEqual(len(self.strategy.with_vms_node_pool), 0)
@@ -183,8 +156,6 @@ class TestSavingEnergy(base.TestCase):
'running_vms': 0, 'service': {'host': 'Node_10'}, 'state': 'up'} 'running_vms': 0, 'service': {'host': 'Node_10'}, 'state': 'up'}
self.m_nova.hypervisors.get.side_effect = [mock_hyper1, mock_hyper2] self.m_nova.hypervisors.get.side_effect = [mock_hyper1, mock_hyper2]
model = self.fake_cluster.generate_scenario_1()
self.m_model.return_value = model
self.strategy.get_hosts_pool() self.strategy.get_hosts_pool()
self.assertEqual(len(self.strategy.with_vms_node_pool), 0) self.assertEqual(len(self.strategy.with_vms_node_pool), 0)
@@ -230,8 +201,8 @@ class TestSavingEnergy(base.TestCase):
'running_vms': 0, 'service': {'host': 'Node_1'}, 'state': 'up'} 'running_vms': 0, 'service': {'host': 'Node_1'}, 'state': 'up'}
self.m_nova.hypervisors.get.side_effect = [mock_hyper1, mock_hyper2] self.m_nova.hypervisors.get.side_effect = [mock_hyper1, mock_hyper2]
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
solution = self.strategy.execute() solution = self.strategy.execute()
self.assertEqual(len(solution.actions), 1) self.assertEqual(len(solution.actions), 1)

View File

@@ -24,10 +24,12 @@ from watcher.common import cinder_helper
from watcher.common import clients from watcher.common import clients
from watcher.common import utils from watcher.common import utils
from watcher.decision_engine.strategy import strategies from watcher.decision_engine.strategy import strategies
from watcher.tests import base from watcher.tests.decision_engine.model import faker_cluster_state
from watcher.tests.decision_engine.strategy.strategies.test_base \
import TestBaseStrategy
class TestStorageCapacityBalance(base.TestCase): class TestStorageCapacityBalance(TestBaseStrategy):
def setUp(self): def setUp(self):
super(TestStorageCapacityBalance, self).setUp() super(TestStorageCapacityBalance, self).setUp()
@@ -115,6 +117,8 @@ class TestStorageCapacityBalance(base.TestCase):
'type2', {'volume_backend_name': 'pool2'}) 'type2', {'volume_backend_name': 'pool2'})
] ]
self.fake_c_cluster = faker_cluster_state.FakerStorageModelCollector()
osc = clients.OpenStackClients() osc = clients.OpenStackClients()
p_cinder = mock.patch.object(osc, 'cinder') p_cinder = mock.patch.object(osc, 'cinder')
@@ -122,20 +126,6 @@ class TestStorageCapacityBalance(base.TestCase):
self.addCleanup(p_cinder.stop) self.addCleanup(p_cinder.stop)
self.m_cinder = cinder_helper.CinderHelper(osc=osc) self.m_cinder = cinder_helper.CinderHelper(osc=osc)
p_model = mock.patch.object(
strategies.StorageCapacityBalance, "compute_model",
new_callable=mock.PropertyMock)
self.m_model = p_model.start()
self.addCleanup(p_model.stop)
p_audit_scope = mock.patch.object(
strategies.StorageCapacityBalance, "audit_scope",
new_callable=mock.PropertyMock
)
self.m_audit_scope = p_audit_scope.start()
self.addCleanup(p_audit_scope.stop)
self.m_audit_scope.return_value = mock.Mock()
self.m_cinder.get_storage_pool_list = mock.Mock( self.m_cinder.get_storage_pool_list = mock.Mock(
return_value=self.fake_pools) return_value=self.fake_pools)
self.m_cinder.get_volume_list = mock.Mock( self.m_cinder.get_volume_list = mock.Mock(
@@ -144,6 +134,10 @@ class TestStorageCapacityBalance(base.TestCase):
return_value=self.fake_snap) return_value=self.fake_snap)
self.m_cinder.get_volume_type_list = mock.Mock( self.m_cinder.get_volume_type_list = mock.Mock(
return_value=self.fake_types) return_value=self.fake_types)
model = self.fake_c_cluster.generate_scenario_1()
self.m_c_model.return_value = model
self.strategy = strategies.StorageCapacityBalance( self.strategy = strategies.StorageCapacityBalance(
config=mock.Mock(), osc=osc) config=mock.Mock(), osc=osc)
self.strategy._cinder = self.m_cinder self.strategy._cinder = self.m_cinder
@@ -241,5 +235,6 @@ class TestStorageCapacityBalance(base.TestCase):
setattr(self.fake_pool1, 'free_capacity_gb', '60') setattr(self.fake_pool1, 'free_capacity_gb', '60')
self.strategy.input_parameters.update( self.strategy.input_parameters.update(
{'volume_threshold': 60.0}) {'volume_threshold': 60.0})
solution = self.strategy.execute() solution = self.strategy.execute()
self.assertEqual(len(solution.actions), 3) self.assertEqual(len(solution.actions), 3)

View File

@@ -20,17 +20,15 @@ import collections
import mock import mock
from watcher.applier.loading import default from watcher.applier.loading import default
from watcher.common import exception
from watcher.common import utils from watcher.common import utils
from watcher.decision_engine.model import model_root
from watcher.decision_engine.strategy import strategies from watcher.decision_engine.strategy import strategies
from watcher.tests import base
from watcher.tests.decision_engine.model import ceilometer_metrics from watcher.tests.decision_engine.model import ceilometer_metrics
from watcher.tests.decision_engine.model import faker_cluster_state
from watcher.tests.decision_engine.model import gnocchi_metrics from watcher.tests.decision_engine.model import gnocchi_metrics
from watcher.tests.decision_engine.strategy.strategies.test_base \
import TestBaseStrategy
class TestUniformAirflow(base.TestCase): class TestUniformAirflow(TestBaseStrategy):
scenarios = [ scenarios = [
("Ceilometer", ("Ceilometer",
@@ -45,14 +43,6 @@ class TestUniformAirflow(base.TestCase):
super(TestUniformAirflow, self).setUp() super(TestUniformAirflow, self).setUp()
# fake metrics # fake metrics
self.fake_metrics = self.fake_datasource_cls() self.fake_metrics = self.fake_datasource_cls()
# fake cluster
self.fake_cluster = faker_cluster_state.FakerModelCollector()
p_model = mock.patch.object(
strategies.UniformAirflow, "compute_model",
new_callable=mock.PropertyMock)
self.m_model = p_model.start()
self.addCleanup(p_model.stop)
p_datasource = mock.patch.object( p_datasource = mock.patch.object(
strategies.UniformAirflow, 'datasource_backend', strategies.UniformAirflow, 'datasource_backend',
@@ -60,16 +50,6 @@ class TestUniformAirflow(base.TestCase):
self.m_datasource = p_datasource.start() self.m_datasource = p_datasource.start()
self.addCleanup(p_datasource.stop) self.addCleanup(p_datasource.stop)
p_audit_scope = mock.patch.object(
strategies.UniformAirflow, "audit_scope",
new_callable=mock.PropertyMock
)
self.m_audit_scope = p_audit_scope.start()
self.addCleanup(p_audit_scope.stop)
self.m_audit_scope.return_value = mock.Mock()
self.m_model.return_value = model_root.ModelRoot()
self.m_datasource.return_value = mock.Mock( self.m_datasource.return_value = mock.Mock(
statistic_aggregation=self.fake_metrics.mock_get_statistics, statistic_aggregation=self.fake_metrics.mock_get_statistics,
NAME=self.fake_metrics.NAME) NAME=self.fake_metrics.NAME)
@@ -87,16 +67,16 @@ class TestUniformAirflow(base.TestCase):
self.strategy.pre_execute() self.strategy.pre_execute()
def test_calc_used_resource(self): def test_calc_used_resource(self):
model = self.fake_cluster.generate_scenario_7_with_2_nodes() model = self.fake_c_cluster.generate_scenario_7_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
node = model.get_node_by_uuid('Node_0') node = model.get_node_by_uuid('Node_0')
cores_used, mem_used, disk_used = ( cores_used, mem_used, disk_used = (
self.strategy.calculate_used_resource(node)) self.strategy.calculate_used_resource(node))
self.assertEqual((cores_used, mem_used, disk_used), (25, 4, 40)) self.assertEqual((cores_used, mem_used, disk_used), (25, 4, 40))
def test_group_hosts_by_airflow(self): def test_group_hosts_by_airflow(self):
model = self.fake_cluster.generate_scenario_7_with_2_nodes() model = self.fake_c_cluster.generate_scenario_7_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
self.strategy.threshold_airflow = 300 self.strategy.threshold_airflow = 300
n1, n2 = self.strategy.group_hosts_by_airflow() n1, n2 = self.strategy.group_hosts_by_airflow()
# print n1, n2, avg, w_map # print n1, n2, avg, w_map
@@ -104,8 +84,8 @@ class TestUniformAirflow(base.TestCase):
self.assertEqual(n2[0]['node'].uuid, 'Node_1') self.assertEqual(n2[0]['node'].uuid, 'Node_1')
def test_choose_instance_to_migrate(self): def test_choose_instance_to_migrate(self):
model = self.fake_cluster.generate_scenario_7_with_2_nodes() model = self.fake_c_cluster.generate_scenario_7_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
self.strategy.threshold_airflow = 300 self.strategy.threshold_airflow = 300
self.strategy.threshold_inlet_t = 22 self.strategy.threshold_inlet_t = 22
n1, n2 = self.strategy.group_hosts_by_airflow() n1, n2 = self.strategy.group_hosts_by_airflow()
@@ -118,8 +98,8 @@ class TestUniformAirflow(base.TestCase):
'73b09e16-35b7-4922-804e-e8f5d9b740fc'}) '73b09e16-35b7-4922-804e-e8f5d9b740fc'})
def test_choose_instance_to_migrate_all(self): def test_choose_instance_to_migrate_all(self):
model = self.fake_cluster.generate_scenario_7_with_2_nodes() model = self.fake_c_cluster.generate_scenario_7_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
self.strategy.threshold_airflow = 300 self.strategy.threshold_airflow = 300
self.strategy.threshold_inlet_t = 25 self.strategy.threshold_inlet_t = 25
n1, n2 = self.strategy.group_hosts_by_airflow() n1, n2 = self.strategy.group_hosts_by_airflow()
@@ -132,8 +112,8 @@ class TestUniformAirflow(base.TestCase):
{inst.uuid for inst in instance_to_mig[1]}) {inst.uuid for inst in instance_to_mig[1]})
def test_choose_instance_notfound(self): def test_choose_instance_notfound(self):
model = self.fake_cluster.generate_scenario_7_with_2_nodes() model = self.fake_c_cluster.generate_scenario_7_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
self.strategy.threshold_airflow = 300 self.strategy.threshold_airflow = 300
self.strategy.threshold_inlet_t = 22 self.strategy.threshold_inlet_t = 22
n1, n2 = self.strategy.group_hosts_by_airflow() n1, n2 = self.strategy.group_hosts_by_airflow()
@@ -143,8 +123,8 @@ class TestUniformAirflow(base.TestCase):
self.assertIsNone(instance_to_mig) self.assertIsNone(instance_to_mig)
def test_filter_destination_hosts(self): def test_filter_destination_hosts(self):
model = self.fake_cluster.generate_scenario_7_with_2_nodes() model = self.fake_c_cluster.generate_scenario_7_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
self.strategy.threshold_airflow = 300 self.strategy.threshold_airflow = 300
self.strategy.threshold_inlet_t = 22 self.strategy.threshold_inlet_t = 22
n1, n2 = self.strategy.group_hosts_by_airflow() n1, n2 = self.strategy.group_hosts_by_airflow()
@@ -158,35 +138,13 @@ class TestUniformAirflow(base.TestCase):
{'cae81432-1631-4d4e-b29c-6f3acdcde906', {'cae81432-1631-4d4e-b29c-6f3acdcde906',
'73b09e16-35b7-4922-804e-e8f5d9b740fc'}) '73b09e16-35b7-4922-804e-e8f5d9b740fc'})
def test_exception_model(self):
self.m_model.return_value = None
self.assertRaises(
exception.ClusterStateNotDefined, self.strategy.execute)
def test_exception_cluster_empty(self):
model = model_root.ModelRoot()
self.m_model.return_value = model
self.assertRaises(exception.ClusterEmpty, self.strategy.execute)
def test_exception_stale_cdm(self):
self.fake_cluster.set_cluster_data_model_as_stale()
self.m_model.return_value = self.fake_cluster.cluster_data_model
self.assertRaises(
exception.ClusterStateNotDefined,
self.strategy.execute)
def test_execute_cluster_empty(self):
model = model_root.ModelRoot()
self.m_model.return_value = model
self.assertRaises(exception.ClusterEmpty, self.strategy.execute)
def test_execute_no_workload(self): def test_execute_no_workload(self):
self.strategy.threshold_airflow = 300 self.strategy.threshold_airflow = 300
self.strategy.threshold_inlet_t = 25 self.strategy.threshold_inlet_t = 25
self.strategy.threshold_power = 300 self.strategy.threshold_power = 300
model = self.fake_cluster.generate_scenario_4_with_1_node_no_instance() model = self.fake_c_cluster.\
self.m_model.return_value = model generate_scenario_4_with_1_node_no_instance()
self.m_c_model.return_value = model
solution = self.strategy.execute() solution = self.strategy.execute()
self.assertEqual([], solution.actions) self.assertEqual([], solution.actions)
@@ -194,8 +152,8 @@ class TestUniformAirflow(base.TestCase):
self.strategy.threshold_airflow = 300 self.strategy.threshold_airflow = 300
self.strategy.threshold_inlet_t = 25 self.strategy.threshold_inlet_t = 25
self.strategy.threshold_power = 300 self.strategy.threshold_power = 300
model = self.fake_cluster.generate_scenario_7_with_2_nodes() model = self.fake_c_cluster.generate_scenario_7_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
solution = self.strategy.execute() solution = self.strategy.execute()
actions_counter = collections.Counter( actions_counter = collections.Counter(
[action.get('action_type') for action in solution.actions]) [action.get('action_type') for action in solution.actions])
@@ -204,8 +162,8 @@ class TestUniformAirflow(base.TestCase):
self.assertEqual(num_migrations, 2) self.assertEqual(num_migrations, 2)
def test_check_parameters(self): def test_check_parameters(self):
model = self.fake_cluster.generate_scenario_7_with_2_nodes() model = self.fake_c_cluster.generate_scenario_7_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
solution = self.strategy.execute() solution = self.strategy.execute()
loader = default.DefaultActionLoader() loader = default.DefaultActionLoader()
for action in solution.actions: for action in solution.actions:

View File

@@ -20,16 +20,15 @@
import mock import mock
from watcher.common import exception
from watcher.decision_engine.model import element from watcher.decision_engine.model import element
from watcher.decision_engine.model import model_root
from watcher.decision_engine.solution.base import BaseSolution from watcher.decision_engine.solution.base import BaseSolution
from watcher.decision_engine.strategy import strategies from watcher.decision_engine.strategy import strategies
from watcher.tests import base
from watcher.tests.decision_engine.model import faker_cluster_and_metrics from watcher.tests.decision_engine.model import faker_cluster_and_metrics
from watcher.tests.decision_engine.strategy.strategies.test_base \
import TestBaseStrategy
class TestVMWorkloadConsolidation(base.TestCase): class TestVMWorkloadConsolidation(TestBaseStrategy):
scenarios = [ scenarios = [
("Ceilometer", ("Ceilometer",
@@ -46,13 +45,7 @@ class TestVMWorkloadConsolidation(base.TestCase):
super(TestVMWorkloadConsolidation, self).setUp() super(TestVMWorkloadConsolidation, self).setUp()
# fake cluster # fake cluster
self.fake_cluster = faker_cluster_and_metrics.FakerModelCollector() self.fake_c_cluster = faker_cluster_and_metrics.FakerModelCollector()
p_model = mock.patch.object(
strategies.VMWorkloadConsolidation, "compute_model",
new_callable=mock.PropertyMock)
self.m_model = p_model.start()
self.addCleanup(p_model.stop)
p_datasource = mock.patch.object( p_datasource = mock.patch.object(
strategies.VMWorkloadConsolidation, 'datasource_backend', strategies.VMWorkloadConsolidation, 'datasource_backend',
@@ -60,20 +53,10 @@ class TestVMWorkloadConsolidation(base.TestCase):
self.m_datasource = p_datasource.start() self.m_datasource = p_datasource.start()
self.addCleanup(p_datasource.stop) self.addCleanup(p_datasource.stop)
p_audit_scope = mock.patch.object(
strategies.VMWorkloadConsolidation, "audit_scope",
new_callable=mock.PropertyMock
)
self.m_audit_scope = p_audit_scope.start()
self.addCleanup(p_audit_scope.stop)
self.m_audit_scope.return_value = mock.Mock()
# fake metrics # fake metrics
self.fake_metrics = self.fake_datasource_cls( self.fake_metrics = self.fake_datasource_cls(
self.m_model.return_value) self.m_c_model.return_value)
self.m_model.return_value = model_root.ModelRoot()
self.m_datasource.return_value = mock.Mock( self.m_datasource.return_value = mock.Mock(
get_instance_cpu_usage=( get_instance_cpu_usage=(
self.fake_metrics.get_instance_cpu_util), self.fake_metrics.get_instance_cpu_util),
@@ -85,17 +68,9 @@ class TestVMWorkloadConsolidation(base.TestCase):
self.strategy = strategies.VMWorkloadConsolidation( self.strategy = strategies.VMWorkloadConsolidation(
config=mock.Mock(datasources=self.datasource)) config=mock.Mock(datasources=self.datasource))
def test_exception_stale_cdm(self):
self.fake_cluster.set_cluster_data_model_as_stale()
self.m_model.return_value = self.fake_cluster.cluster_data_model
self.assertRaises(
exception.ClusterStateNotDefined,
self.strategy.execute)
def test_get_instance_utilization(self): def test_get_instance_utilization(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
self.fake_metrics.model = model self.fake_metrics.model = model
instance_0 = model.get_instance_by_uuid("INSTANCE_0") instance_0 = model.get_instance_by_uuid("INSTANCE_0")
instance_util = dict(cpu=1.0, ram=1, disk=10) instance_util = dict(cpu=1.0, ram=1, disk=10)
@@ -104,8 +79,8 @@ class TestVMWorkloadConsolidation(base.TestCase):
self.strategy.get_instance_utilization(instance_0)) self.strategy.get_instance_utilization(instance_0))
def test_get_node_utilization(self): def test_get_node_utilization(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
self.fake_metrics.model = model self.fake_metrics.model = model
node_0 = model.get_node_by_uuid("Node_0") node_0 = model.get_node_by_uuid("Node_0")
node_util = dict(cpu=1.0, ram=1, disk=10) node_util = dict(cpu=1.0, ram=1, disk=10)
@@ -114,16 +89,16 @@ class TestVMWorkloadConsolidation(base.TestCase):
self.strategy.get_node_utilization(node_0)) self.strategy.get_node_utilization(node_0))
def test_get_node_capacity(self): def test_get_node_capacity(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
self.fake_metrics.model = model self.fake_metrics.model = model
node_0 = model.get_node_by_uuid("Node_0") node_0 = model.get_node_by_uuid("Node_0")
node_util = dict(cpu=40, ram=64, disk=250) node_util = dict(cpu=40, ram=64, disk=250)
self.assertEqual(node_util, self.strategy.get_node_capacity(node_0)) self.assertEqual(node_util, self.strategy.get_node_capacity(node_0))
def test_get_relative_node_utilization(self): def test_get_relative_node_utilization(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
self.fake_metrics.model = model self.fake_metrics.model = model
node = model.get_node_by_uuid('Node_0') node = model.get_node_by_uuid('Node_0')
rhu = self.strategy.get_relative_node_utilization(node) rhu = self.strategy.get_relative_node_utilization(node)
@@ -131,16 +106,16 @@ class TestVMWorkloadConsolidation(base.TestCase):
self.assertEqual(expected_rhu, rhu) self.assertEqual(expected_rhu, rhu)
def test_get_relative_cluster_utilization(self): def test_get_relative_cluster_utilization(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
self.fake_metrics.model = model self.fake_metrics.model = model
cru = self.strategy.get_relative_cluster_utilization() cru = self.strategy.get_relative_cluster_utilization()
expected_cru = {'cpu': 0.05, 'disk': 0.05, 'ram': 0.0234375} expected_cru = {'cpu': 0.05, 'disk': 0.05, 'ram': 0.0234375}
self.assertEqual(expected_cru, cru) self.assertEqual(expected_cru, cru)
def test_add_migration_with_active_state(self): def test_add_migration_with_active_state(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
self.fake_metrics.model = model self.fake_metrics.model = model
n1 = model.get_node_by_uuid('Node_0') n1 = model.get_node_by_uuid('Node_0')
n2 = model.get_node_by_uuid('Node_1') n2 = model.get_node_by_uuid('Node_1')
@@ -156,8 +131,8 @@ class TestVMWorkloadConsolidation(base.TestCase):
self.assertEqual(expected, self.strategy.solution.actions[0]) self.assertEqual(expected, self.strategy.solution.actions[0])
def test_add_migration_with_paused_state(self): def test_add_migration_with_paused_state(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
self.fake_metrics.model = model self.fake_metrics.model = model
n1 = model.get_node_by_uuid('Node_0') n1 = model.get_node_by_uuid('Node_0')
n2 = model.get_node_by_uuid('Node_1') n2 = model.get_node_by_uuid('Node_1')
@@ -178,8 +153,8 @@ class TestVMWorkloadConsolidation(base.TestCase):
self.assertEqual(expected, self.strategy.solution.actions[0]) self.assertEqual(expected, self.strategy.solution.actions[0])
def test_is_overloaded(self): def test_is_overloaded(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
self.fake_metrics.model = model self.fake_metrics.model = model
n1 = model.get_node_by_uuid('Node_0') n1 = model.get_node_by_uuid('Node_0')
cc = {'cpu': 1.0, 'ram': 1.0, 'disk': 1.0} cc = {'cpu': 1.0, 'ram': 1.0, 'disk': 1.0}
@@ -195,8 +170,8 @@ class TestVMWorkloadConsolidation(base.TestCase):
self.assertTrue(res) self.assertTrue(res)
def test_instance_fits(self): def test_instance_fits(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
self.fake_metrics.model = model self.fake_metrics.model = model
n = model.get_node_by_uuid('Node_1') n = model.get_node_by_uuid('Node_1')
instance0 = model.get_instance_by_uuid('INSTANCE_0') instance0 = model.get_instance_by_uuid('INSTANCE_0')
@@ -209,8 +184,8 @@ class TestVMWorkloadConsolidation(base.TestCase):
self.assertFalse(res) self.assertFalse(res)
def test_add_action_enable_compute_node(self): def test_add_action_enable_compute_node(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
self.fake_metrics.model = model self.fake_metrics.model = model
n = model.get_node_by_uuid('Node_0') n = model.get_node_by_uuid('Node_0')
self.strategy.add_action_enable_compute_node(n) self.strategy.add_action_enable_compute_node(n)
@@ -220,8 +195,8 @@ class TestVMWorkloadConsolidation(base.TestCase):
self.assertEqual(expected, self.strategy.solution.actions) self.assertEqual(expected, self.strategy.solution.actions)
def test_add_action_disable_node(self): def test_add_action_disable_node(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
self.fake_metrics.model = model self.fake_metrics.model = model
n = model.get_node_by_uuid('Node_0') n = model.get_node_by_uuid('Node_0')
self.strategy.add_action_disable_node(n) self.strategy.add_action_disable_node(n)
@@ -233,8 +208,8 @@ class TestVMWorkloadConsolidation(base.TestCase):
self.assertEqual(expected, self.strategy.solution.actions) self.assertEqual(expected, self.strategy.solution.actions)
def test_disable_unused_nodes(self): def test_disable_unused_nodes(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
self.fake_metrics.model = model self.fake_metrics.model = model
n1 = model.get_node_by_uuid('Node_0') n1 = model.get_node_by_uuid('Node_0')
n2 = model.get_node_by_uuid('Node_1') n2 = model.get_node_by_uuid('Node_1')
@@ -256,8 +231,8 @@ class TestVMWorkloadConsolidation(base.TestCase):
self.assertEqual(expected, self.strategy.solution.actions[1]) self.assertEqual(expected, self.strategy.solution.actions[1])
def test_offload_phase(self): def test_offload_phase(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
self.fake_metrics.model = model self.fake_metrics.model = model
cc = {'cpu': 1.0, 'ram': 1.0, 'disk': 1.0} cc = {'cpu': 1.0, 'ram': 1.0, 'disk': 1.0}
self.strategy.offload_phase(cc) self.strategy.offload_phase(cc)
@@ -265,8 +240,8 @@ class TestVMWorkloadConsolidation(base.TestCase):
self.assertEqual(expected, self.strategy.solution.actions) self.assertEqual(expected, self.strategy.solution.actions)
def test_consolidation_phase(self): def test_consolidation_phase(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
self.fake_metrics.model = model self.fake_metrics.model = model
n1 = model.get_node_by_uuid('Node_0') n1 = model.get_node_by_uuid('Node_0')
n2 = model.get_node_by_uuid('Node_1') n2 = model.get_node_by_uuid('Node_1')
@@ -281,8 +256,8 @@ class TestVMWorkloadConsolidation(base.TestCase):
self.assertEqual(expected, self.strategy.solution.actions) self.assertEqual(expected, self.strategy.solution.actions)
def test_strategy(self): def test_strategy(self):
model = self.fake_cluster.generate_scenario_2() model = self.fake_c_cluster.generate_scenario_2()
self.m_model.return_value = model self.m_c_model.return_value = model
self.fake_metrics.model = model self.fake_metrics.model = model
result = self.strategy.pre_execute() result = self.strategy.pre_execute()
@@ -333,8 +308,8 @@ class TestVMWorkloadConsolidation(base.TestCase):
) )
def test_strategy2(self): def test_strategy2(self):
model = self.fake_cluster.generate_scenario_3() model = self.fake_c_cluster.generate_scenario_3()
self.m_model.return_value = model self.m_c_model.return_value = model
self.fake_metrics.model = model self.fake_metrics.model = model
n1 = model.get_node_by_uuid('Node_0') n1 = model.get_node_by_uuid('Node_0')
n2 = model.get_node_by_uuid('Node_1') n2 = model.get_node_by_uuid('Node_1')

View File

@@ -20,17 +20,15 @@ import collections
import mock import mock
from watcher.applier.loading import default from watcher.applier.loading import default
from watcher.common import exception
from watcher.common import utils from watcher.common import utils
from watcher.decision_engine.model import model_root
from watcher.decision_engine.strategy import strategies from watcher.decision_engine.strategy import strategies
from watcher.tests import base
from watcher.tests.decision_engine.model import ceilometer_metrics from watcher.tests.decision_engine.model import ceilometer_metrics
from watcher.tests.decision_engine.model import faker_cluster_state
from watcher.tests.decision_engine.model import gnocchi_metrics from watcher.tests.decision_engine.model import gnocchi_metrics
from watcher.tests.decision_engine.strategy.strategies.test_base \
import TestBaseStrategy
class TestWorkloadBalance(base.TestCase): class TestWorkloadBalance(TestBaseStrategy):
scenarios = [ scenarios = [
("Ceilometer", ("Ceilometer",
@@ -45,14 +43,6 @@ class TestWorkloadBalance(base.TestCase):
super(TestWorkloadBalance, self).setUp() super(TestWorkloadBalance, self).setUp()
# fake metrics # fake metrics
self.fake_metrics = self.fake_datasource_cls() self.fake_metrics = self.fake_datasource_cls()
# fake cluster
self.fake_cluster = faker_cluster_state.FakerModelCollector()
p_model = mock.patch.object(
strategies.WorkloadBalance, "compute_model",
new_callable=mock.PropertyMock)
self.m_model = p_model.start()
self.addCleanup(p_model.stop)
p_datasource = mock.patch.object( p_datasource = mock.patch.object(
strategies.WorkloadBalance, "datasource_backend", strategies.WorkloadBalance, "datasource_backend",
@@ -60,14 +50,6 @@ class TestWorkloadBalance(base.TestCase):
self.m_datasource = p_datasource.start() self.m_datasource = p_datasource.start()
self.addCleanup(p_datasource.stop) self.addCleanup(p_datasource.stop)
p_audit_scope = mock.patch.object(
strategies.WorkloadBalance, "audit_scope",
new_callable=mock.PropertyMock
)
self.m_audit_scope = p_audit_scope.start()
self.addCleanup(p_audit_scope.stop)
self.m_audit_scope.return_value = mock.Mock()
self.m_datasource.return_value = mock.Mock( self.m_datasource.return_value = mock.Mock(
statistic_aggregation=self.fake_metrics.mock_get_statistics_wb) statistic_aggregation=self.fake_metrics.mock_get_statistics_wb)
self.strategy = strategies.WorkloadBalance( self.strategy = strategies.WorkloadBalance(
@@ -83,8 +65,8 @@ class TestWorkloadBalance(base.TestCase):
self.strategy._granularity = 300 self.strategy._granularity = 300
def test_calc_used_resource(self): def test_calc_used_resource(self):
model = self.fake_cluster.generate_scenario_6_with_2_nodes() model = self.fake_c_cluster.generate_scenario_6_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
node = model.get_node_by_uuid('Node_0') node = model.get_node_by_uuid('Node_0')
cores_used, mem_used, disk_used = ( cores_used, mem_used, disk_used = (
self.strategy.calculate_used_resource(node)) self.strategy.calculate_used_resource(node))
@@ -92,8 +74,8 @@ class TestWorkloadBalance(base.TestCase):
self.assertEqual((cores_used, mem_used, disk_used), (20, 64, 40)) self.assertEqual((cores_used, mem_used, disk_used), (20, 64, 40))
def test_group_hosts_by_cpu_util(self): def test_group_hosts_by_cpu_util(self):
model = self.fake_cluster.generate_scenario_6_with_2_nodes() model = self.fake_c_cluster.generate_scenario_6_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
self.strategy.threshold = 30 self.strategy.threshold = 30
n1, n2, avg, w_map = self.strategy.group_hosts_by_cpu_or_ram_util() n1, n2, avg, w_map = self.strategy.group_hosts_by_cpu_or_ram_util()
self.assertEqual(n1[0]['node'].uuid, 'Node_0') self.assertEqual(n1[0]['node'].uuid, 'Node_0')
@@ -101,8 +83,8 @@ class TestWorkloadBalance(base.TestCase):
self.assertEqual(avg, 8.0) self.assertEqual(avg, 8.0)
def test_group_hosts_by_ram_util(self): def test_group_hosts_by_ram_util(self):
model = self.fake_cluster.generate_scenario_6_with_2_nodes() model = self.fake_c_cluster.generate_scenario_6_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
self.strategy._meter = "memory.resident" self.strategy._meter = "memory.resident"
self.strategy.threshold = 30 self.strategy.threshold = 30
n1, n2, avg, w_map = self.strategy.group_hosts_by_cpu_or_ram_util() n1, n2, avg, w_map = self.strategy.group_hosts_by_cpu_or_ram_util()
@@ -111,8 +93,8 @@ class TestWorkloadBalance(base.TestCase):
self.assertEqual(avg, 33.0) self.assertEqual(avg, 33.0)
def test_choose_instance_to_migrate(self): def test_choose_instance_to_migrate(self):
model = self.fake_cluster.generate_scenario_6_with_2_nodes() model = self.fake_c_cluster.generate_scenario_6_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
n1, n2, avg, w_map = self.strategy.group_hosts_by_cpu_or_ram_util() n1, n2, avg, w_map = self.strategy.group_hosts_by_cpu_or_ram_util()
instance_to_mig = self.strategy.choose_instance_to_migrate( instance_to_mig = self.strategy.choose_instance_to_migrate(
n1, avg, w_map) n1, avg, w_map)
@@ -121,8 +103,8 @@ class TestWorkloadBalance(base.TestCase):
"73b09e16-35b7-4922-804e-e8f5d9b740fc") "73b09e16-35b7-4922-804e-e8f5d9b740fc")
def test_choose_instance_notfound(self): def test_choose_instance_notfound(self):
model = self.fake_cluster.generate_scenario_6_with_2_nodes() model = self.fake_c_cluster.generate_scenario_6_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
n1, n2, avg, w_map = self.strategy.group_hosts_by_cpu_or_ram_util() n1, n2, avg, w_map = self.strategy.group_hosts_by_cpu_or_ram_util()
instances = model.get_all_instances() instances = model.get_all_instances()
[model.remove_instance(inst) for inst in instances.values()] [model.remove_instance(inst) for inst in instances.values()]
@@ -131,8 +113,8 @@ class TestWorkloadBalance(base.TestCase):
self.assertIsNone(instance_to_mig) self.assertIsNone(instance_to_mig)
def test_filter_destination_hosts(self): def test_filter_destination_hosts(self):
model = self.fake_cluster.generate_scenario_6_with_2_nodes() model = self.fake_c_cluster.generate_scenario_6_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
self.strategy.datasource = mock.MagicMock( self.strategy.datasource = mock.MagicMock(
statistic_aggregation=self.fake_metrics.mock_get_statistics_wb) statistic_aggregation=self.fake_metrics.mock_get_statistics_wb)
n1, n2, avg, w_map = self.strategy.group_hosts_by_cpu_or_ram_util() n1, n2, avg, w_map = self.strategy.group_hosts_by_cpu_or_ram_util()
@@ -143,38 +125,16 @@ class TestWorkloadBalance(base.TestCase):
self.assertEqual(len(dest_hosts), 1) self.assertEqual(len(dest_hosts), 1)
self.assertEqual(dest_hosts[0]['node'].uuid, 'Node_1') self.assertEqual(dest_hosts[0]['node'].uuid, 'Node_1')
def test_exception_model(self):
self.m_model.return_value = None
self.assertRaises(
exception.ClusterStateNotDefined, self.strategy.execute)
def test_exception_cluster_empty(self):
model = model_root.ModelRoot()
self.m_model.return_value = model
self.assertRaises(exception.ClusterEmpty, self.strategy.execute)
def test_exception_stale_cdm(self):
self.fake_cluster.set_cluster_data_model_as_stale()
self.m_model.return_value = self.fake_cluster.cluster_data_model
self.assertRaises(
exception.ClusterStateNotDefined,
self.strategy.execute)
def test_execute_cluster_empty(self):
model = model_root.ModelRoot()
self.m_model.return_value = model
self.assertRaises(exception.ClusterEmpty, self.strategy.execute)
def test_execute_no_workload(self): def test_execute_no_workload(self):
model = self.fake_cluster.generate_scenario_4_with_1_node_no_instance() model = self.fake_c_cluster.\
self.m_model.return_value = model generate_scenario_4_with_1_node_no_instance()
self.m_c_model.return_value = model
solution = self.strategy.execute() solution = self.strategy.execute()
self.assertEqual([], solution.actions) self.assertEqual([], solution.actions)
def test_execute(self): def test_execute(self):
model = self.fake_cluster.generate_scenario_6_with_2_nodes() model = self.fake_c_cluster.generate_scenario_6_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
solution = self.strategy.execute() solution = self.strategy.execute()
actions_counter = collections.Counter( actions_counter = collections.Counter(
[action.get('action_type') for action in solution.actions]) [action.get('action_type') for action in solution.actions])
@@ -183,8 +143,8 @@ class TestWorkloadBalance(base.TestCase):
self.assertEqual(num_migrations, 1) self.assertEqual(num_migrations, 1)
def test_check_parameters(self): def test_check_parameters(self):
model = self.fake_cluster.generate_scenario_6_with_2_nodes() model = self.fake_c_cluster.generate_scenario_6_with_2_nodes()
self.m_model.return_value = model self.m_c_model.return_value = model
solution = self.strategy.execute() solution = self.strategy.execute()
loader = default.DefaultActionLoader() loader = default.DefaultActionLoader()
for action in solution.actions: for action in solution.actions:

View File

@@ -21,15 +21,14 @@ import mock
from watcher.common import clients from watcher.common import clients
from watcher.common import utils from watcher.common import utils
from watcher.decision_engine.model import model_root
from watcher.decision_engine.strategy import strategies from watcher.decision_engine.strategy import strategies
from watcher.tests import base
from watcher.tests.decision_engine.model import ceilometer_metrics from watcher.tests.decision_engine.model import ceilometer_metrics
from watcher.tests.decision_engine.model import faker_cluster_state
from watcher.tests.decision_engine.model import gnocchi_metrics from watcher.tests.decision_engine.model import gnocchi_metrics
from watcher.tests.decision_engine.strategy.strategies.test_base \
import TestBaseStrategy
class TestWorkloadStabilization(base.TestCase): class TestWorkloadStabilization(TestBaseStrategy):
scenarios = [ scenarios = [
("Ceilometer", ("Ceilometer",
@@ -46,9 +45,6 @@ class TestWorkloadStabilization(base.TestCase):
# fake metrics # fake metrics
self.fake_metrics = self.fake_datasource_cls() self.fake_metrics = self.fake_datasource_cls()
# fake cluster
self.fake_cluster = faker_cluster_state.FakerModelCollector()
self.hosts_load_assert = { self.hosts_load_assert = {
'Node_0': {'cpu_util': 0.07, 'memory.resident': 7.0, 'vcpus': 40}, 'Node_0': {'cpu_util': 0.07, 'memory.resident': 7.0, 'vcpus': 40},
'Node_1': {'cpu_util': 0.07, 'memory.resident': 5, 'vcpus': 40}, 'Node_1': {'cpu_util': 0.07, 'memory.resident': 5, 'vcpus': 40},
@@ -61,27 +57,12 @@ class TestWorkloadStabilization(base.TestCase):
self.m_osc = p_osc.start() self.m_osc = p_osc.start()
self.addCleanup(p_osc.stop) self.addCleanup(p_osc.stop)
p_model = mock.patch.object(
strategies.WorkloadStabilization, "compute_model",
new_callable=mock.PropertyMock)
self.m_model = p_model.start()
self.addCleanup(p_model.stop)
p_datasource = mock.patch.object( p_datasource = mock.patch.object(
strategies.WorkloadStabilization, "datasource_backend", strategies.WorkloadStabilization, "datasource_backend",
new_callable=mock.PropertyMock) new_callable=mock.PropertyMock)
self.m_datasource = p_datasource.start() self.m_datasource = p_datasource.start()
self.addCleanup(p_datasource.stop) self.addCleanup(p_datasource.stop)
p_audit_scope = mock.patch.object(
strategies.WorkloadStabilization, "audit_scope",
new_callable=mock.PropertyMock
)
self.m_audit_scope = p_audit_scope.start()
self.addCleanup(p_audit_scope.stop)
self.m_model.return_value = model_root.ModelRoot()
self.m_audit_scope.return_value = mock.Mock()
self.m_datasource.return_value = mock.Mock( self.m_datasource.return_value = mock.Mock(
statistic_aggregation=self.fake_metrics.mock_get_statistics) statistic_aggregation=self.fake_metrics.mock_get_statistics)
@@ -113,8 +94,8 @@ class TestWorkloadStabilization(base.TestCase):
self.strategy.aggregation_method = {"instance": "mean", "node": "mean"} self.strategy.aggregation_method = {"instance": "mean", "node": "mean"}
def test_get_instance_load(self): def test_get_instance_load(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
instance0 = model.get_instance_by_uuid("INSTANCE_0") instance0 = model.get_instance_by_uuid("INSTANCE_0")
instance_0_dict = { instance_0_dict = {
'uuid': 'INSTANCE_0', 'vcpus': 10, 'uuid': 'INSTANCE_0', 'vcpus': 10,
@@ -123,13 +104,14 @@ class TestWorkloadStabilization(base.TestCase):
instance_0_dict, self.strategy.get_instance_load(instance0)) instance_0_dict, self.strategy.get_instance_load(instance0))
def test_get_instance_load_with_no_metrics(self): def test_get_instance_load_with_no_metrics(self):
model = self.fake_cluster.generate_scenario_1_with_1_node_unavailable() model = self.fake_c_cluster.\
self.m_model.return_value = model generate_scenario_1_with_1_node_unavailable()
self.m_c_model.return_value = model
lost_instance = model.get_instance_by_uuid("LOST_INSTANCE") lost_instance = model.get_instance_by_uuid("LOST_INSTANCE")
self.assertIsNone(self.strategy.get_instance_load(lost_instance)) self.assertIsNone(self.strategy.get_instance_load(lost_instance))
def test_normalize_hosts_load(self): def test_normalize_hosts_load(self):
self.m_model.return_value = self.fake_cluster.generate_scenario_1() self.m_c_model.return_value = self.fake_c_cluster.generate_scenario_1()
fake_hosts = {'Node_0': {'cpu_util': 0.07, 'memory.resident': 7}, fake_hosts = {'Node_0': {'cpu_util': 0.07, 'memory.resident': 7},
'Node_1': {'cpu_util': 0.05, 'memory.resident': 5}} 'Node_1': {'cpu_util': 0.05, 'memory.resident': 5}}
normalized_hosts = {'Node_0': normalized_hosts = {'Node_0':
@@ -143,18 +125,20 @@ class TestWorkloadStabilization(base.TestCase):
self.strategy.normalize_hosts_load(fake_hosts)) self.strategy.normalize_hosts_load(fake_hosts))
def test_get_available_nodes(self): def test_get_available_nodes(self):
self.m_model.return_value = self.fake_cluster. \ self.m_c_model.return_value = self.fake_c_cluster. \
generate_scenario_9_with_3_active_plus_1_disabled_nodes() generate_scenario_9_with_3_active_plus_1_disabled_nodes()
self.assertEqual(3, len(self.strategy.get_available_nodes())) self.assertEqual(3, len(self.strategy.get_available_nodes()))
def test_get_hosts_load(self): def test_get_hosts_load(self):
self.m_model.return_value = self.fake_cluster.generate_scenario_1() self.m_c_model.return_value = self.fake_c_cluster.\
generate_scenario_1()
self.assertEqual(self.strategy.get_hosts_load(), self.assertEqual(self.strategy.get_hosts_load(),
self.hosts_load_assert) self.hosts_load_assert)
def test_get_hosts_load_with_node_missing(self): def test_get_hosts_load_with_node_missing(self):
self.m_model.return_value = \ self.m_c_model.return_value = \
self.fake_cluster.generate_scenario_1_with_1_node_unavailable() self.fake_c_cluster.\
generate_scenario_1_with_1_node_unavailable()
self.assertEqual(self.hosts_load_assert, self.assertEqual(self.hosts_load_assert,
self.strategy.get_hosts_load()) self.strategy.get_hosts_load())
@@ -175,8 +159,8 @@ class TestWorkloadStabilization(base.TestCase):
self.assertEqual(self.strategy.calculate_weighted_sd(sd_case), 1.25) self.assertEqual(self.strategy.calculate_weighted_sd(sd_case), 1.25)
def test_calculate_migration_case(self): def test_calculate_migration_case(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
instance = model.get_instance_by_uuid("INSTANCE_5") instance = model.get_instance_by_uuid("INSTANCE_5")
src_node = model.get_node_by_uuid("Node_2") src_node = model.get_node_by_uuid("Node_2")
dst_node = model.get_node_by_uuid("Node_1") dst_node = model.get_node_by_uuid("Node_1")
@@ -188,8 +172,8 @@ class TestWorkloadStabilization(base.TestCase):
'vcpus': 40}) 'vcpus': 40})
def test_simulate_migrations(self): def test_simulate_migrations(self):
model = self.fake_cluster.generate_scenario_1() model = self.fake_c_cluster.generate_scenario_1()
self.m_model.return_value = model self.m_c_model.return_value = model
self.strategy.host_choice = 'fullsearch' self.strategy.host_choice = 'fullsearch'
self.assertEqual( self.assertEqual(
10, 10,
@@ -197,21 +181,22 @@ class TestWorkloadStabilization(base.TestCase):
def test_simulate_migrations_with_all_instances_exclude(self): def test_simulate_migrations_with_all_instances_exclude(self):
model = \ model = \
self.fake_cluster.generate_scenario_1_with_all_instances_exclude() self.fake_c_cluster.\
self.m_model.return_value = model generate_scenario_1_with_all_instances_exclude()
self.m_c_model.return_value = model
self.strategy.host_choice = 'fullsearch' self.strategy.host_choice = 'fullsearch'
self.assertEqual( self.assertEqual(
0, 0,
len(self.strategy.simulate_migrations(self.hosts_load_assert))) len(self.strategy.simulate_migrations(self.hosts_load_assert)))
def test_check_threshold(self): def test_check_threshold(self):
self.m_model.return_value = self.fake_cluster.generate_scenario_1() self.m_c_model.return_value = self.fake_c_cluster.generate_scenario_1()
self.strategy.thresholds = {'cpu_util': 0.001, 'memory.resident': 0.2} self.strategy.thresholds = {'cpu_util': 0.001, 'memory.resident': 0.2}
self.strategy.simulate_migrations = mock.Mock(return_value=True) self.strategy.simulate_migrations = mock.Mock(return_value=True)
self.assertTrue(self.strategy.check_threshold()) self.assertTrue(self.strategy.check_threshold())
def test_execute_one_migration(self): def test_execute_one_migration(self):
self.m_model.return_value = self.fake_cluster.generate_scenario_1() self.m_c_model.return_value = self.fake_c_cluster.generate_scenario_1()
self.strategy.thresholds = {'cpu_util': 0.001, 'memory.resident': 0.2} self.strategy.thresholds = {'cpu_util': 0.001, 'memory.resident': 0.2}
self.strategy.simulate_migrations = mock.Mock( self.strategy.simulate_migrations = mock.Mock(
return_value=[ return_value=[
@@ -224,7 +209,7 @@ class TestWorkloadStabilization(base.TestCase):
'INSTANCE_4', 'Node_2', 'Node_1') 'INSTANCE_4', 'Node_2', 'Node_1')
def test_execute_multiply_migrations(self): def test_execute_multiply_migrations(self):
self.m_model.return_value = self.fake_cluster.generate_scenario_1() self.m_c_model.return_value = self.fake_c_cluster.generate_scenario_1()
self.strategy.thresholds = {'cpu_util': 0.00001, self.strategy.thresholds = {'cpu_util': 0.00001,
'memory.resident': 0.0001} 'memory.resident': 0.0001}
self.strategy.simulate_migrations = mock.Mock( self.strategy.simulate_migrations = mock.Mock(
@@ -239,7 +224,7 @@ class TestWorkloadStabilization(base.TestCase):
self.assertEqual(mock_migrate.call_count, 2) self.assertEqual(mock_migrate.call_count, 2)
def test_execute_nothing_to_migrate(self): def test_execute_nothing_to_migrate(self):
self.m_model.return_value = self.fake_cluster.generate_scenario_1() self.m_c_model.return_value = self.fake_c_cluster.generate_scenario_1()
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)

View File

@@ -18,34 +18,24 @@ import cinderclient
import novaclient import novaclient
from watcher.common import cinder_helper from watcher.common import cinder_helper
from watcher.common import clients from watcher.common import clients
from watcher.common import exception
from watcher.common import nova_helper from watcher.common import nova_helper
from watcher.common import utils from watcher.common import utils
from watcher.decision_engine.model import model_root
from watcher.decision_engine.strategy import strategies from watcher.decision_engine.strategy import strategies
from watcher.tests import base
from watcher.tests.decision_engine.model import faker_cluster_state from watcher.tests.decision_engine.model import faker_cluster_state
from watcher.tests.decision_engine.strategy.strategies.test_base \
import TestBaseStrategy
volume_uuid_mapping = faker_cluster_state.volume_uuid_mapping volume_uuid_mapping = faker_cluster_state.volume_uuid_mapping
class TestZoneMigration(base.TestCase): class TestZoneMigration(TestBaseStrategy):
def setUp(self): def setUp(self):
super(TestZoneMigration, self).setUp() super(TestZoneMigration, self).setUp()
# fake compute cluster
self.fake_c_cluster = faker_cluster_state.FakerModelCollector()
# fake storage cluster # fake storage cluster
self.fake_s_cluster = faker_cluster_state.FakerStorageModelCollector() self.fake_s_cluster = faker_cluster_state.FakerStorageModelCollector()
p_c_model = mock.patch.object(
strategies.ZoneMigration, "compute_model",
new_callable=mock.PropertyMock)
self.m_c_model = p_c_model.start()
self.addCleanup(p_c_model.stop)
p_s_model = mock.patch.object( p_s_model = mock.patch.object(
strategies.ZoneMigration, "storage_model", strategies.ZoneMigration, "storage_model",
new_callable=mock.PropertyMock) new_callable=mock.PropertyMock)
@@ -82,13 +72,6 @@ class TestZoneMigration(base.TestCase):
self.m_parallel_per_pool = p_parallel_per_pool.start() self.m_parallel_per_pool = p_parallel_per_pool.start()
self.addCleanup(p_parallel_per_pool.stop) self.addCleanup(p_parallel_per_pool.stop)
p_audit_scope = mock.patch.object(
strategies.ZoneMigration, "audit_scope",
new_callable=mock.PropertyMock
)
self.m_audit_scope = p_audit_scope.start()
self.addCleanup(p_audit_scope.stop)
p_priority = mock.patch.object( p_priority = mock.patch.object(
strategies.ZoneMigration, "priority", strategies.ZoneMigration, "priority",
new_callable=mock.PropertyMock new_callable=mock.PropertyMock
@@ -116,7 +99,6 @@ class TestZoneMigration(base.TestCase):
{"src_pool": "src2@back1#pool1", "dst_pool": "dst2@back2#pool1", {"src_pool": "src2@back1#pool1", "dst_pool": "dst2@back2#pool1",
"src_type": "type2", "dst_type": "type3"} "src_type": "type2", "dst_type": "type3"}
] ]
self.m_audit_scope.return_value = mock.Mock()
self.strategy = strategies.ZoneMigration( self.strategy = strategies.ZoneMigration(
config=mock.Mock()) config=mock.Mock())
@@ -145,19 +127,6 @@ class TestZoneMigration(base.TestCase):
m_cinder_helper.start() m_cinder_helper.start()
self.addCleanup(m_cinder_helper.stop) self.addCleanup(m_cinder_helper.stop)
def test_exception_empty_compute_model(self):
model = model_root.ModelRoot()
self.m_c_model.return_value = model
self.assertRaises(exception.ComputeClusterEmpty, self.strategy.execute)
def test_exception_empty_storage_model(self):
c_model = self.fake_c_cluster.generate_scenario_1()
self.m_c_model.return_value = c_model
s_model = model_root.StorageModelRoot()
self.m_s_model.return_value = s_model
self.assertRaises(exception.StorageClusterEmpty, self.strategy.execute)
@staticmethod @staticmethod
def fake_instance(**kwargs): def fake_instance(**kwargs):
instance = mock.MagicMock(spec=novaclient.v2.servers.Server) instance = mock.MagicMock(spec=novaclient.v2.servers.Server)