Tidy up - Watcher Decision Engine package

Some Python class and packages need to be renamed
for a better compliance with the shared terminology
which provides a better understanding of Watcher
objects and components by every contributor.

This patchset is there to change the code structure by adding the folder
"strategies" and "loading".

Partially implements: blueprint glossary-related-refactoring

Change-Id: I56fb24ee6762b3186eccde5983233e17bb227cc1
This commit is contained in:
Jean-Emile DARTOIS 2015-12-10 09:34:38 +01:00
parent 92940ba9e2
commit 62570525ad
30 changed files with 153 additions and 160 deletions

View File

@ -42,8 +42,8 @@ watcher.database.migration_backend =
sqlalchemy = watcher.db.sqlalchemy.migration sqlalchemy = watcher.db.sqlalchemy.migration
watcher_strategies = watcher_strategies =
dummy = watcher.decision_engine.strategy.dummy_strategy:DummyStrategy dummy = watcher.decision_engine.strategy.strategies.dummy_strategy:DummyStrategy
basic = watcher.decision_engine.strategy.basic_consolidation:BasicConsolidation basic = watcher.decision_engine.strategy.strategies.basic_consolidation:BasicConsolidation
[build_sphinx] [build_sphinx]
source-dir = doc/source source-dir = doc/source

View File

@ -22,7 +22,7 @@ import pecan
from watcher.api import acl from watcher.api import acl
from watcher.api import config as api_config from watcher.api import config as api_config
from watcher.api import middleware from watcher.api import middleware
from watcher.decision_engine.strategy.selector import default \ from watcher.decision_engine.strategy.selection import default \
as strategy_selector as strategy_selector
# Register options for the service # Register options for the service

View File

@ -17,9 +17,9 @@
# limitations under the License. # limitations under the License.
# #
import abc import abc
import six
from watcher.decision_engine.strategy.level import StrategyLevel import six
from watcher.decision_engine.strategy.common.level import StrategyLevel
@six.add_metaclass(abc.ABCMeta) @six.add_metaclass(abc.ABCMeta)

View File

@ -17,7 +17,7 @@ from oslo_log import log
from watcher.decision_engine.planner.default import DefaultPlanner from watcher.decision_engine.planner.default import DefaultPlanner
from watcher.decision_engine.strategy.context.base import BaseStrategyContext from watcher.decision_engine.strategy.context.base import BaseStrategyContext
from watcher.decision_engine.strategy.selector.default import StrategySelector from watcher.decision_engine.strategy.selection.default import StrategySelector
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)

View File

@ -0,0 +1,43 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
#
# 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 abc
from oslo_log import log
import six
LOG = log.getLogger(__name__)
@six.add_metaclass(abc.ABCMeta)
class BaseStrategyLoader(object):
@abc.abstractmethod
def load_available_strategies(self):
raise NotImplementedError() # pragma:no cover
def load(self, strategy_to_load=None):
strategy_selected = None
try:
available_strategies = self.load_available_strategies()
strategy_cls = available_strategies.get(
strategy_to_load, self.default_strategy_cls
)
strategy_selected = strategy_cls()
except Exception as exc:
LOG.exception(exc)
return strategy_selected

View File

@ -21,32 +21,21 @@ from __future__ import unicode_literals
from oslo_log import log from oslo_log import log
from stevedore import ExtensionManager from stevedore import ExtensionManager
from watcher.decision_engine.strategy.basic_consolidation import \
from watcher.decision_engine.strategy.loading.base import BaseStrategyLoader
from watcher.decision_engine.strategy.strategies.basic_consolidation import \
BasicConsolidation BasicConsolidation
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)
class StrategyLoader(object): class DefaultStrategyLoader(BaseStrategyLoader):
default_strategy_cls = BasicConsolidation default_strategy_cls = BasicConsolidation
def load_strategies(self): def load_available_strategies(self):
extension_manager = ExtensionManager( extension_manager = ExtensionManager(
namespace='watcher_strategies', namespace='watcher_strategies',
invoke_on_load=True, invoke_on_load=True,
) )
return {ext.name: ext.plugin for ext in extension_manager.extensions} return {ext.name: ext.plugin for ext in extension_manager.extensions}
def load(self, model):
strategy = None
try:
available_strategies = self.load_strategies()
strategy_cls = available_strategies.get(
model, self.default_strategy_cls
)
strategy = strategy_cls()
except Exception as exc:
LOG.exception(exc)
return strategy

View File

@ -16,9 +16,12 @@
from oslo_config import cfg from oslo_config import cfg
from oslo_log import log from oslo_log import log
from watcher.common.exception import WatcherException from watcher.common.exception import WatcherException
from watcher.decision_engine.strategy.loader import StrategyLoader from watcher.decision_engine.strategy.loading.default import \
from watcher.decision_engine.strategy.selector.base import BaseSelector DefaultStrategyLoader
from watcher.decision_engine.strategy.selection.base import BaseSelector
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)
CONF = cfg.CONF CONF = cfg.CONF
@ -41,7 +44,7 @@ CONF.register_opts(WATCHER_GOALS_OPTS, goals_opt_group)
class StrategySelector(BaseSelector): class StrategySelector(BaseSelector):
def __init__(self): def __init__(self):
self.strategy_loader = StrategyLoader() self.strategy_loader = DefaultStrategyLoader()
def define_from_goal(self, goal_name): def define_from_goal(self, goal_name):
strategy_to_load = None strategy_to_load = None

View File

@ -16,12 +16,12 @@
import abc import abc
from oslo_log import log from oslo_log import log
import six import six
from watcher.decision_engine.solution.default import DefaultSolution
from watcher.decision_engine.strategy.level import StrategyLevel
from watcher.decision_engine.solution.default import DefaultSolution
from watcher.decision_engine.strategy.common.level import StrategyLevel
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)

View File

@ -28,8 +28,8 @@ from watcher.decision_engine.model.hypervisor_state import HypervisorState
from watcher.decision_engine.model.power_state import PowerState from watcher.decision_engine.model.power_state import PowerState
from watcher.decision_engine.model.resource import ResourceType from watcher.decision_engine.model.resource import ResourceType
from watcher.decision_engine.model.vm_state import VMState from watcher.decision_engine.model.vm_state import VMState
from watcher.decision_engine.strategy.base import BaseStrategy from watcher.decision_engine.strategy.common.level import StrategyLevel
from watcher.decision_engine.strategy.level import StrategyLevel from watcher.decision_engine.strategy.strategies.base import BaseStrategy
from watcher.metrics_engine.cluster_history.ceilometer import \ from watcher.metrics_engine.cluster_history.ceilometer import \
CeilometerClusterHistory CeilometerClusterHistory
@ -53,12 +53,12 @@ class BasicConsolidation(BaseStrategy):
and often tend to migrate from one physical machine to another. and often tend to migrate from one physical machine to another.
Hence, the traditional and offline heuristics such as bin packing Hence, the traditional and offline heuristics such as bin packing
are not applicable for the placement VM in cloud computing. are not applicable for the placement VM in cloud computing.
So, the decision Engine optimizer provide placement strategy considering So, the decision Engine optimizer provides placement strategy considering
not only the performance effects but also the workload characteristics of not only the performance effects but also the workload characteristics of
VMs and others metrics like the power consumption and VMs and others metrics like the power consumption and
the tenants constraints (SLAs). the tenants constraints (SLAs).
The watcher optimizer use an online VM placement technique The watcher optimizer uses an online VM placement technique
based on machine learning and meta-heuristics that must handle : based on machine learning and meta-heuristics that must handle :
- multi-objectives - multi-objectives
- Contradictory objectives - Contradictory objectives
@ -121,8 +121,8 @@ class BasicConsolidation(BaseStrategy):
vm_to_mig): vm_to_mig):
'''check if the migration is possible '''check if the migration is possible
:param model: current state of the cluster :param model: the current state of the cluster
:param src_hypervisor: the current of the virtual machine :param src_hypervisor: the current node of the virtual machine
:param dest_hypervisor: the destination of the virtual machine :param dest_hypervisor: the destination of the virtual machine
:param vm_to_mig: the virtual machine :param vm_to_mig: the virtual machine
:return: True if the there is enough place otherwise false :return: True if the there is enough place otherwise false
@ -167,7 +167,7 @@ class BasicConsolidation(BaseStrategy):
"""Check threshold """Check threshold
check the threshold value defined by the ratio of check the threshold value defined by the ratio of
aggregated CPU capacity of VMS on one node to CPU capacity aggregated CPU capacity of VMs on one node to CPU capacity
of this node must not exceed the threshold value. of this node must not exceed the threshold value.
:param dest_hypervisor: :param dest_hypervisor:
:param total_cores :param total_cores
@ -213,7 +213,7 @@ class BasicConsolidation(BaseStrategy):
def calculate_weight(self, model, element, total_cores_used, def calculate_weight(self, model, element, total_cores_used,
total_disk_used, total_memory_used): total_disk_used, total_memory_used):
"""Calculate weight of every """Calculate weight of every resource
:param model: :param model:
:param element: :param element:
@ -248,7 +248,7 @@ class BasicConsolidation(BaseStrategy):
return (score_cores + score_disk + score_memory) / 3 return (score_cores + score_disk + score_memory) / 3
def calculate_score_node(self, hypervisor, model): def calculate_score_node(self, hypervisor, model):
"""calculate the score that reprensent the utilization level """calculate the score that represent the utilization level
:param hypervisor: :param hypervisor:
:param model: :param model:
@ -331,7 +331,7 @@ class BasicConsolidation(BaseStrategy):
model))) model)))
def execute(self, orign_model): def execute(self, orign_model):
LOG.debug("initialize Sercon Consolidation") LOG.debug("Initialize Sercon Consolidation")
if orign_model is None: if orign_model is None:
raise ClusterStateNotDefined() raise ClusterStateNotDefined()
@ -411,7 +411,7 @@ class BasicConsolidation(BaseStrategy):
vm_score.append( vm_score.append(
(vm_id, self.calculate_score_vm(vm, current_model))) (vm_id, self.calculate_score_vm(vm, current_model)))
''' sort VM's by Score ''' ''' sort VMs by Score '''
v = sorted(vm_score, reverse=True, key=lambda x: (x[1])) v = sorted(vm_score, reverse=True, key=lambda x: (x[1]))
LOG.debug("VM(s) BFD {0}".format(v)) LOG.debug("VM(s) BFD {0}".format(v))

View File

@ -17,9 +17,9 @@
# limitations under the License. # limitations under the License.
# #
from oslo_log import log from oslo_log import log
from watcher.decision_engine.strategy.strategies.base import BaseStrategy
from watcher.decision_engine.actions.nop import Nop from watcher.decision_engine.actions.nop import Nop
from watcher.decision_engine.strategy.base import BaseStrategy
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)

View File

@ -18,7 +18,7 @@
import watcher.api.app import watcher.api.app
from watcher.applier import manager_applier from watcher.applier import manager_applier
from watcher.decision_engine import manager from watcher.decision_engine import manager
from watcher.decision_engine.strategy.selector import default \ from watcher.decision_engine.strategy.selection import default \
as strategy_selector as strategy_selector

View File

@ -13,7 +13,6 @@
# implied. # implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from mock import call from mock import call
from mock import MagicMock from mock import MagicMock
from watcher.decision_engine.command.audit import TriggerAuditCommand from watcher.decision_engine.command.audit import TriggerAuditCommand
@ -21,8 +20,8 @@ from watcher.decision_engine.messaging.events import Events
from watcher.objects.audit import Audit from watcher.objects.audit import Audit
from watcher.objects.audit import AuditStatus from watcher.objects.audit import AuditStatus
from watcher.tests.db.base import DbTestCase from watcher.tests.db.base import DbTestCase
from watcher.tests.decision_engine.faker_cluster_state import \ from watcher.tests.decision_engine.strategy.strategies.faker_cluster_state \
FakerModelCollector import FakerModelCollector
from watcher.tests.objects import utils as obj_utils from watcher.tests.objects import utils as obj_utils

View File

@ -22,7 +22,7 @@ from watcher.decision_engine.messaging.audit_endpoint import AuditEndpoint
from watcher.metrics_engine.cluster_model_collector.manager import \ from watcher.metrics_engine.cluster_model_collector.manager import \
CollectorManager CollectorManager
from watcher.tests import base from watcher.tests import base
from watcher.tests.decision_engine.faker_cluster_state import \ from watcher.tests.decision_engine.strategy.strategies.faker_cluster_state import \
FakerModelCollector FakerModelCollector

View File

@ -17,17 +17,18 @@
# limitations under the License. # limitations under the License.
# #
import uuid import uuid
from watcher.decision_engine.model.hypervisor import Hypervisor from watcher.decision_engine.model.hypervisor import Hypervisor
from watcher.decision_engine.model.vm_state import VMState from watcher.decision_engine.model.vm_state import VMState
from watcher.tests import base from watcher.tests import base
from watcher.tests.decision_engine.faker_cluster_state import \ from watcher.tests.decision_engine.strategy.strategies.faker_cluster_state import \
FakerModelCollector FakerModelCollector
class TestMapping(base.BaseTestCase): class TestMapping(base.BaseTestCase):
def test_get_node_from_vm(self): def test_get_node_from_vm(self):
fake_cluster = FakerModelCollector() fake_cluster = FakerModelCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors() model = fake_cluster.generate_scenario_3_with_2_hypervisors()
vms = model.get_all_vms() vms = model.get_all_vms()
keys = list(vms.keys()) keys = list(vms.keys())
@ -39,14 +40,14 @@ class TestMapping(base.BaseTestCase):
def test_get_node_from_vm_id(self): def test_get_node_from_vm_id(self):
fake_cluster = FakerModelCollector() fake_cluster = FakerModelCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors() model = fake_cluster.generate_scenario_3_with_2_hypervisors()
hyps = model.mapping.get_node_vms_from_id("BLABLABLA") hyps = model.mapping.get_node_vms_from_id("BLABLABLA")
self.assertEqual(hyps.__len__(), 0) self.assertEqual(hyps.__len__(), 0)
def test_get_all_vms(self): def test_get_all_vms(self):
fake_cluster = FakerModelCollector() fake_cluster = FakerModelCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors() model = fake_cluster.generate_scenario_3_with_2_hypervisors()
vms = model.get_all_vms() vms = model.get_all_vms()
self.assertEqual(vms.__len__(), 2) self.assertEqual(vms.__len__(), 2)
@ -57,7 +58,7 @@ class TestMapping(base.BaseTestCase):
def test_get_mapping(self): def test_get_mapping(self):
fake_cluster = FakerModelCollector() fake_cluster = FakerModelCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors() model = fake_cluster.generate_scenario_3_with_2_hypervisors()
mapping_vm = model.mapping.get_mapping_vm() mapping_vm = model.mapping.get_mapping_vm()
self.assertEqual(mapping_vm.__len__(), 2) self.assertEqual(mapping_vm.__len__(), 2)
@ -66,7 +67,7 @@ class TestMapping(base.BaseTestCase):
def test_migrate_vm(self): def test_migrate_vm(self):
fake_cluster = FakerModelCollector() fake_cluster = FakerModelCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors() model = fake_cluster.generate_scenario_3_with_2_hypervisors()
vms = model.get_all_vms() vms = model.get_all_vms()
keys = list(vms.keys()) keys = list(vms.keys())
vm0 = vms[keys[0]] vm0 = vms[keys[0]]
@ -81,7 +82,7 @@ class TestMapping(base.BaseTestCase):
def test_unmap_from_id_log_warning(self): def test_unmap_from_id_log_warning(self):
fake_cluster = FakerModelCollector() fake_cluster = FakerModelCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors() model = fake_cluster.generate_scenario_3_with_2_hypervisors()
vms = model.get_all_vms() vms = model.get_all_vms()
keys = list(vms.keys()) keys = list(vms.keys())
vm0 = vms[keys[0]] vm0 = vms[keys[0]]
@ -95,7 +96,7 @@ class TestMapping(base.BaseTestCase):
def test_unmap_from_id(self): def test_unmap_from_id(self):
fake_cluster = FakerModelCollector() fake_cluster = FakerModelCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors() model = fake_cluster.generate_scenario_3_with_2_hypervisors()
vms = model.get_all_vms() vms = model.get_all_vms()
keys = list(vms.keys()) keys = list(vms.keys())
vm0 = vms[keys[0]] vm0 = vms[keys[0]]

View File

@ -17,15 +17,15 @@
# limitations under the License. # limitations under the License.
# #
import uuid import uuid
from watcher.common import exception from watcher.common import exception
from watcher.common.exception import IllegalArgumentException from watcher.common.exception import IllegalArgumentException
from watcher.decision_engine.model.hypervisor import Hypervisor from watcher.decision_engine.model.hypervisor import Hypervisor
from watcher.decision_engine.model.hypervisor_state import HypervisorState from watcher.decision_engine.model.hypervisor_state import HypervisorState
from watcher.decision_engine.model.model_root import ModelRoot from watcher.decision_engine.model.model_root import ModelRoot
from watcher.tests.decision_engine.faker_cluster_state import \
FakerModelCollector
from watcher.tests import base from watcher.tests import base
from watcher.tests.decision_engine.strategy.strategies.faker_cluster_state import \
FakerModelCollector
class TestModel(base.BaseTestCase): class TestModel(base.BaseTestCase):

View File

@ -13,20 +13,40 @@
# implied. # implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from __future__ import unicode_literals from __future__ import unicode_literals
from mock import patch from mock import patch
from stevedore.extension import Extension from stevedore.extension import Extension
from stevedore.extension import ExtensionManager from stevedore.extension import ExtensionManager
from watcher.decision_engine.strategy.dummy_strategy import DummyStrategy
from watcher.decision_engine.strategy.loader import StrategyLoader from watcher.decision_engine.strategy.loading.default import \
DefaultStrategyLoader
from watcher.decision_engine.strategy.strategies.base import BaseStrategy
from watcher.decision_engine.strategy.strategies.dummy_strategy import \
DummyStrategy
from watcher.tests.base import TestCase from watcher.tests.base import TestCase
class TestStrategyLoader(TestCase): class TestDefaultStrategyLoader(TestCase):
@patch("watcher.decision_engine.strategy.loader.ExtensionManager") strategy_loader = DefaultStrategyLoader()
def test_load_strategy_with_empty_model(self):
selected_strategy = self.strategy_loader.load(None)
self.assertIsNotNone(selected_strategy,
'The default strategy not be must none')
self.assertIsInstance(selected_strategy, BaseStrategy)
def test_load_strategy_is_basic(self):
exptected_strategy = 'basic'
selected_strategy = self.strategy_loader.load(exptected_strategy)
self.assertEqual(
selected_strategy.name,
exptected_strategy,
'The default strategy should be basic')
@patch(
"watcher.decision_engine.strategy.loading.default.ExtensionManager")
def test_strategy_loader(self, m_extension_manager): def test_strategy_loader(self, m_extension_manager):
dummy_strategy_name = "dummy" dummy_strategy_name = "dummy"
# Set up the fake Stevedore extensions # Set up the fake Stevedore extensions
@ -40,15 +60,13 @@ class TestStrategyLoader(TestCase):
)], )],
namespace="watcher_strategies", namespace="watcher_strategies",
) )
strategy_loader = StrategyLoader() strategy_loader = DefaultStrategyLoader()
loaded_strategy = strategy_loader.load("dummy") loaded_strategy = strategy_loader.load("dummy")
self.assertEqual("dummy", loaded_strategy.name) self.assertEqual("dummy", loaded_strategy.name)
self.assertEqual("Dummy Strategy", loaded_strategy.description) self.assertEqual("Dummy Strategy", loaded_strategy.description)
def test_load_dummy_strategy(self): def test_load_dummy_strategy(self):
strategy_loader = StrategyLoader() strategy_loader = DefaultStrategyLoader()
loaded_strategy = strategy_loader.load("dummy") loaded_strategy = strategy_loader.load("dummy")
self.assertIsInstance(loaded_strategy, DummyStrategy)
self.assertEqual("dummy", loaded_strategy.name)
self.assertEqual("Dummy Strategy", loaded_strategy.description)

View File

@ -15,10 +15,13 @@
# limitations under the License. # limitations under the License.
from mock import patch from mock import patch
from oslo_config import cfg from oslo_config import cfg
from watcher.common.exception import WatcherException from watcher.common.exception import WatcherException
from watcher.decision_engine.strategy.loader import StrategyLoader from watcher.decision_engine.strategy.loading.default import \
from watcher.decision_engine.strategy.selector.default import StrategySelector DefaultStrategyLoader
from watcher.decision_engine.strategy.selection.default import StrategySelector
from watcher.tests.base import TestCase from watcher.tests.base import TestCase
CONF = cfg.CONF CONF = cfg.CONF
@ -26,7 +29,7 @@ class TestStrategySelector(TestCase):
strategy_selector = StrategySelector() strategy_selector = StrategySelector()
@patch.object(StrategyLoader, 'load') @patch.object(DefaultStrategyLoader, 'load')
def test_define_from_goal(self, mock_call): def test_define_from_goal(self, mock_call):
cfg.CONF.set_override( cfg.CONF.set_override(
'goals', {"DUMMY": "fake"}, group='watcher_goals' 'goals', {"DUMMY": "fake"}, group='watcher_goals'
@ -36,7 +39,7 @@ class TestStrategySelector(TestCase):
self.strategy_selector.define_from_goal(expected_goal) self.strategy_selector.define_from_goal(expected_goal)
mock_call.assert_called_once_with(expected_strategy) mock_call.assert_called_once_with(expected_strategy)
@patch.object(StrategyLoader, 'load') @patch.object(DefaultStrategyLoader, 'load')
def test_define_from_goal_with_incorrect_mapping(self, mock_call): def test_define_from_goal_with_incorrect_mapping(self, mock_call):
cfg.CONF.set_override( cfg.CONF.set_override(
'goals', {}, group='watcher_goals' 'goals', {}, group='watcher_goals'

View File

@ -167,39 +167,12 @@ class FakerModelCollector(BaseClusterModelCollector):
return current_state_cluster return current_state_cluster
def generate_scenario_2(self):
current_state_cluster = ModelRoot()
# number of nodes
count_node = 5
# define ressouce ( CPU, MEM disk, ... )
mem = Resource(ResourceType.memory)
# 2199.954 Mhz
num_cores = Resource(ResourceType.cpu_cores)
disk = Resource(ResourceType.disk)
current_state_cluster.create_resource(mem)
current_state_cluster.create_resource(num_cores)
current_state_cluster.create_resource(disk)
for i in range(0, count_node):
node_uuid = "Node_{0}".format(i)
node = Hypervisor()
node.uuid = node_uuid
node.hostname = "hostname_{0}".format(i)
mem.set_capacity(node, 132)
disk.set_capacity(node, 250)
num_cores.set_capacity(node, 40)
# print("create "+str(node))
current_state_cluster.add_hypervisor(node)
return current_state_cluster
def map(self, model, h_id, vm_id): def map(self, model, h_id, vm_id):
model.get_mapping().map( model.get_mapping().map(
model.get_hypervisor_from_id(h_id), model.get_hypervisor_from_id(h_id),
model.get_vm_from_id(vm_id)) model.get_vm_from_id(vm_id))
def generate_scenario_3(self): def generate_scenario_2(self):
vms = [] vms = []
current_state_cluster = ModelRoot() current_state_cluster = ModelRoot()
@ -263,7 +236,7 @@ class FakerModelCollector(BaseClusterModelCollector):
return current_state_cluster return current_state_cluster
def generate_scenario_4_with_2_hypervisors(self): def generate_scenario_3_with_2_hypervisors(self):
vms = [] vms = []
current_state_cluster = ModelRoot() current_state_cluster = ModelRoot()
@ -317,7 +290,7 @@ class FakerModelCollector(BaseClusterModelCollector):
return current_state_cluster return current_state_cluster
def generate_scenario_5_with_1_hypervisor_no_vm(self): def generate_scenario_4_with_1_hypervisor_no_vm(self):
current_state_cluster = ModelRoot() current_state_cluster = ModelRoot()
# number of nodes # number of nodes
count_node = 1 count_node = 1

View File

@ -22,20 +22,18 @@ import mock
from mock import MagicMock from mock import MagicMock
from watcher.common import exception from watcher.common import exception
from watcher.decision_engine.actions.hypervisor_state import \ from watcher.decision_engine.actions.hypervisor_state import \
ChangeHypervisorState ChangeHypervisorState
from watcher.decision_engine.actions.power_state import ChangePowerState
from watcher.decision_engine.actions.migration import Migrate from watcher.decision_engine.actions.migration import Migrate
from watcher.decision_engine.actions.power_state import ChangePowerState
from watcher.decision_engine.model.model_root import ModelRoot from watcher.decision_engine.model.model_root import ModelRoot
from watcher.decision_engine.strategy.basic_consolidation import \ from watcher.decision_engine.strategy.strategies.basic_consolidation import \
BasicConsolidation BasicConsolidation
from watcher.tests import base from watcher.tests import base
from watcher.tests.decision_engine.faker_cluster_state import \ from watcher.tests.decision_engine.strategy.strategies.faker_cluster_state \
FakerModelCollector import FakerModelCollector
from watcher.tests.decision_engine.faker_metrics_collector import \ from watcher.tests.decision_engine.strategy.strategies.faker_metrics_collector\
FakerMetricsCollector import FakerMetricsCollector
class TestBasicConsolidation(base.BaseTestCase): class TestBasicConsolidation(base.BaseTestCase):
@ -154,7 +152,7 @@ class TestBasicConsolidation(base.BaseTestCase):
def test_check_migration(self): def test_check_migration(self):
sercon = BasicConsolidation() sercon = BasicConsolidation()
fake_cluster = FakerModelCollector() fake_cluster = FakerModelCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors() model = fake_cluster.generate_scenario_3_with_2_hypervisors()
all_vms = model.get_all_vms() all_vms = model.get_all_vms()
all_hyps = model.get_all_hypervisors() all_hyps = model.get_all_hypervisors()
@ -166,7 +164,7 @@ class TestBasicConsolidation(base.BaseTestCase):
def test_threshold(self): def test_threshold(self):
sercon = BasicConsolidation() sercon = BasicConsolidation()
fake_cluster = FakerModelCollector() fake_cluster = FakerModelCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors() model = fake_cluster.generate_scenario_3_with_2_hypervisors()
all_hyps = model.get_all_hypervisors() all_hyps = model.get_all_hypervisors()
hyp0 = all_hyps[list(all_hyps.keys())[0]] hyp0 = all_hyps[list(all_hyps.keys())[0]]
@ -188,7 +186,7 @@ class TestBasicConsolidation(base.BaseTestCase):
statistic_aggregation=self.fake_metrics.mock_get_statistics) statistic_aggregation=self.fake_metrics.mock_get_statistics)
solution = sercon.execute( solution = sercon.execute(
self.fake_cluster.generate_scenario_3()) self.fake_cluster.generate_scenario_2())
actions_counter = Counter( actions_counter = Counter(
[type(action) for action in solution.actions]) [type(action) for action in solution.actions])
@ -224,7 +222,7 @@ class TestBasicConsolidation(base.BaseTestCase):
current_state_cluster = FakerModelCollector() current_state_cluster = FakerModelCollector()
model = current_state_cluster. \ model = current_state_cluster. \
generate_scenario_5_with_1_hypervisor_no_vm() generate_scenario_4_with_1_hypervisor_no_vm()
with mock.patch.object(BasicConsolidation, 'calculate_weight') \ with mock.patch.object(BasicConsolidation, 'calculate_weight') \
as mock_score_call: as mock_score_call:

View File

@ -13,15 +13,16 @@
# implied. # implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from watcher.decision_engine.strategy.dummy_strategy import DummyStrategy from watcher.decision_engine.strategy.strategies.dummy_strategy import \
DummyStrategy
from watcher.tests import base from watcher.tests import base
from watcher.tests.decision_engine.faker_cluster_state import \ from watcher.tests.decision_engine.strategy.strategies.faker_cluster_state\
FakerModelCollector import FakerModelCollector
class TestDummyStrategy(base.TestCase): class TestDummyStrategy(base.TestCase):
def test_dummy_strategy(self): def test_dummy_strategy(self):
tactique = DummyStrategy("basic", "Basic offline consolidation") tactique = DummyStrategy("basic", "Basic offline consolidation")
fake_cluster = FakerModelCollector() fake_cluster = FakerModelCollector()
model = fake_cluster.generate_scenario_4_with_2_hypervisors() model = fake_cluster.generate_scenario_3_with_2_hypervisors()
tactique.execute(model) tactique.execute(model)

View File

@ -1,37 +0,0 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015 b<>com
#
# 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.
from watcher.decision_engine.strategy.base import BaseStrategy
from watcher.decision_engine.strategy.loader import StrategyLoader
from watcher.tests import base
class TestStrategySelector(base.BaseTestCase):
strategy_loader = StrategyLoader()
def test_load_strategy_with_empty_model(self):
selected_strategy = self.strategy_loader.load(None)
self.assertIsNotNone(selected_strategy,
'The default strategy be must not none')
self.assertIsInstance(selected_strategy, BaseStrategy)
def test_load_strategy_is_basic(self):
exptected_strategy = 'basic'
selected_strategy = self.strategy_loader.load(exptected_strategy)
self.assertEqual(
selected_strategy.name,
exptected_strategy,
'The default strategy should be basic')

View File

@ -16,20 +16,22 @@
import mock import mock
from mock import MagicMock from mock import MagicMock
from watcher.common.exception import MetaActionNotFound from watcher.common.exception import MetaActionNotFound
from watcher.common import utils from watcher.common import utils
from watcher.db import api as db_api from watcher.db import api as db_api
from watcher.decision_engine.actions.base import BaseAction from watcher.decision_engine.actions.base import BaseAction
from watcher.decision_engine.planner.default import DefaultPlanner from watcher.decision_engine.planner.default import DefaultPlanner
from watcher.decision_engine.solution.default import DefaultSolution from watcher.decision_engine.solution.default import DefaultSolution
from watcher.decision_engine.strategy.basic_consolidation import \ from watcher.decision_engine.strategy.strategies.basic_consolidation import \
BasicConsolidation BasicConsolidation
from watcher.tests.db import base from watcher.tests.db import base
from watcher.tests.db import utils as db_utils from watcher.tests.db import utils as db_utils
from watcher.tests.decision_engine.faker_cluster_state import \ from watcher.tests.decision_engine.strategy.strategies.faker_cluster_state\
FakerModelCollector import FakerModelCollector
from watcher.tests.decision_engine.faker_metrics_collector import \ from watcher.tests.decision_engine.strategy.strategies.faker_metrics_collector\
FakerMetricsCollector import FakerMetricsCollector
from watcher.tests.objects import utils as obj_utils from watcher.tests.objects import utils as obj_utils
@ -54,7 +56,7 @@ class SolutionFakerSingleHyp(object):
get_statistics=metrics.mock_get_statistics) get_statistics=metrics.mock_get_statistics)
return sercon.execute( return sercon.execute(
current_state_cluster.generate_scenario_4_with_2_hypervisors()) current_state_cluster.generate_scenario_3_with_2_hypervisors())
class TestActionScheduling(base.DbTestCase): class TestActionScheduling(base.DbTestCase):