Merge "Added 'dummy' entrypoint within watcher_strategies"
This commit is contained in:
commit
44cfa11b0e
@ -454,8 +454,10 @@
|
|||||||
# From watcher
|
# From watcher
|
||||||
#
|
#
|
||||||
|
|
||||||
# Goals used for the optimization (dict value)
|
# Goals used for the optimization. Maps each goal to an associated
|
||||||
#goals = BALANCE_LOAD:basic,MINIMIZE_ENERGY_CONSUMPTION:basic,MINIMIZE_LICENSING_COST:basic,PREPARE_PLANNED_OPERATION:basic,SERVERS_CONSOLIDATION:basic
|
# strategy (for example: BASIC_CONSOLIDATION:basic,
|
||||||
|
# MY_GOAL:my_strategy_1) (dict value)
|
||||||
|
#goals = DUMMY:dummy
|
||||||
|
|
||||||
|
|
||||||
[watcher_messaging]
|
[watcher_messaging]
|
||||||
|
@ -44,8 +44,8 @@ watcher.database.migration_backend =
|
|||||||
sqlalchemy = watcher.db.sqlalchemy.migration
|
sqlalchemy = watcher.db.sqlalchemy.migration
|
||||||
|
|
||||||
watcher_strategies =
|
watcher_strategies =
|
||||||
basic = watcher.decision_engine.strategies.basic_consolidation:BasicConsolidation
|
dummy = watcher.decision_engine.strategy.dummy_strategy:DummyStrategy
|
||||||
|
basic = watcher.decision_engine.strategy.basic_consolidation:BasicConsolidation
|
||||||
|
|
||||||
[build_sphinx]
|
[build_sphinx]
|
||||||
source-dir = doc/source
|
source-dir = doc/source
|
||||||
|
@ -16,23 +16,21 @@
|
|||||||
|
|
||||||
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.decision_engine.strategy.loader import StrategyLoader
|
from watcher.decision_engine.strategy.loader import StrategyLoader
|
||||||
from watcher.decision_engine.strategy.selector.base import Selector
|
from watcher.decision_engine.strategy.selector.base import Selector
|
||||||
from watcher.objects.audit_template import Goal
|
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
|
||||||
goals = {
|
default_goals = {'DUMMY': 'dummy'}
|
||||||
'SERVERS_CONSOLIDATION': 'basic',
|
|
||||||
'MINIMIZE_ENERGY_CONSUMPTION': 'basic',
|
|
||||||
'BALANCE_LOAD': 'basic',
|
|
||||||
'MINIMIZE_LICENSING_COST': 'basic',
|
|
||||||
'PREPARE_PLANNED_OPERATION': 'basic'
|
|
||||||
}
|
|
||||||
WATCHER_GOALS_OPTS = [
|
WATCHER_GOALS_OPTS = [
|
||||||
cfg.DictOpt('goals',
|
cfg.DictOpt(
|
||||||
default=goals, help='Goals used for the optimization ')
|
'goals',
|
||||||
|
default=default_goals,
|
||||||
|
help='Goals used for the optimization. '
|
||||||
|
'Maps each goal to an associated strategy (for example: '
|
||||||
|
'BASIC_CONSOLIDATION:basic, MY_GOAL:my_strategy_1)'),
|
||||||
]
|
]
|
||||||
goals_opt_group = cfg.OptGroup(name='watcher_goals',
|
goals_opt_group = cfg.OptGroup(name='watcher_goals',
|
||||||
title='Goals available for the optimization')
|
title='Goals available for the optimization')
|
||||||
@ -46,8 +44,13 @@ class StrategySelector(Selector):
|
|||||||
self.strategy_loader = StrategyLoader()
|
self.strategy_loader = StrategyLoader()
|
||||||
|
|
||||||
def define_from_goal(self, goal_name):
|
def define_from_goal(self, goal_name):
|
||||||
if goal_name is None:
|
strategy_to_load = None
|
||||||
goal_name = Goal.SERVERS_CONSOLIDATION
|
try:
|
||||||
|
|
||||||
strategy_to_load = CONF.watcher_goals.goals[goal_name]
|
strategy_to_load = CONF.watcher_goals.goals[goal_name]
|
||||||
return self.strategy_loader.load(strategy_to_load)
|
return self.strategy_loader.load(strategy_to_load)
|
||||||
|
except KeyError as exc:
|
||||||
|
LOG.exception(exc)
|
||||||
|
raise WatcherException(
|
||||||
|
"Incorrect mapping: could not find "
|
||||||
|
"associated strategy for '%s'" % goal_name
|
||||||
|
)
|
||||||
|
@ -23,14 +23,6 @@ from watcher.objects import base
|
|||||||
from watcher.objects import utils as obj_utils
|
from watcher.objects import utils as obj_utils
|
||||||
|
|
||||||
|
|
||||||
class Goal(object):
|
|
||||||
SERVERS_CONSOLIDATION = 'SERVERS_CONSOLIDATION'
|
|
||||||
MINIMIZE_ENERGY_CONSUMPTION = 'MINIMIZE_ENERGY_CONSUMPTION'
|
|
||||||
BALANCE_LOAD = 'BALANCE_LOAD'
|
|
||||||
MINIMIZE_LICENSING_COST = 'MINIMIZE_LICENSING_COST'
|
|
||||||
PREPARE_PLANNED_OPERATION = 'PREPARE_PLANNED_OPERATION'
|
|
||||||
|
|
||||||
|
|
||||||
class AuditTemplate(base.WatcherObject):
|
class AuditTemplate(base.WatcherObject):
|
||||||
# Version 1.0: Initial version
|
# Version 1.0: Initial version
|
||||||
VERSION = '1.0'
|
VERSION = '1.0'
|
||||||
|
@ -379,7 +379,7 @@ class TestPost(api_base.FunctionalTest):
|
|||||||
wraps=self.dbapi.create_audit_template
|
wraps=self.dbapi.create_audit_template
|
||||||
) as cn_mock:
|
) as cn_mock:
|
||||||
audit_template_dict = api_utils.audit_template_post_data(
|
audit_template_dict = api_utils.audit_template_post_data(
|
||||||
goal='SERVERS_CONSOLIDATION')
|
goal='DUMMY')
|
||||||
response = self.post_json('/audit_templates', audit_template_dict)
|
response = self.post_json('/audit_templates', audit_template_dict)
|
||||||
self.assertEqual(audit_template_dict['goal'],
|
self.assertEqual(audit_template_dict['goal'],
|
||||||
response.json['goal'])
|
response.json['goal'])
|
||||||
|
@ -20,6 +20,13 @@ class TestListGoal(api_base.FunctionalTest):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestListGoal, self).setUp()
|
super(TestListGoal, self).setUp()
|
||||||
|
# Override the default to get enough goals to test limit on query
|
||||||
|
cfg.CONF.set_override(
|
||||||
|
"goals", {
|
||||||
|
"DUMMY_1": "dummy", "DUMMY_2": "dummy",
|
||||||
|
"DUMMY_3": "dummy", "DUMMY_4": "dummy",
|
||||||
|
},
|
||||||
|
group='watcher_goals')
|
||||||
|
|
||||||
def _assert_goal_fields(self, goal):
|
def _assert_goal_fields(self, goal):
|
||||||
goal_fields = ['name', 'strategy']
|
goal_fields = ['name', 'strategy']
|
||||||
@ -53,11 +60,11 @@ class TestListGoal(api_base.FunctionalTest):
|
|||||||
self.assertEqual(len(CONF.watcher_goals.goals),
|
self.assertEqual(len(CONF.watcher_goals.goals),
|
||||||
len(response['goals']))
|
len(response['goals']))
|
||||||
|
|
||||||
def test_collection_links(self):
|
def test_goals_collection_links(self):
|
||||||
response = self.get_json('/goals/?limit=2')
|
response = self.get_json('/goals/?limit=2')
|
||||||
self.assertEqual(2, len(response['goals']))
|
self.assertEqual(2, len(response['goals']))
|
||||||
|
|
||||||
def test_collection_links_default_limit(self):
|
def test_goals_collection_links_default_limit(self):
|
||||||
cfg.CONF.set_override('max_limit', 3, 'api')
|
cfg.CONF.set_override('max_limit', 3, 'api')
|
||||||
response = self.get_json('/goals')
|
response = self.get_json('/goals')
|
||||||
self.assertEqual(3, len(response['goals']))
|
self.assertEqual(3, len(response['goals']))
|
||||||
|
@ -21,7 +21,7 @@ def get_test_audit_template(**kwargs):
|
|||||||
return {
|
return {
|
||||||
'id': kwargs.get('id', 1),
|
'id': kwargs.get('id', 1),
|
||||||
'uuid': kwargs.get('uuid', 'e74c40e0-d825-11e2-a28f-0800200c9a66'),
|
'uuid': kwargs.get('uuid', 'e74c40e0-d825-11e2-a28f-0800200c9a66'),
|
||||||
'goal': kwargs.get('goal', 'SERVERS_CONSOLIDATION'),
|
'goal': kwargs.get('goal', 'DUMMY'),
|
||||||
'name': kwargs.get('name', 'My Audit Template'),
|
'name': kwargs.get('name', 'My Audit Template'),
|
||||||
'description': kwargs.get('description', 'Desc. Of My Audit Template'),
|
'description': kwargs.get('description', 'Desc. Of My Audit Template'),
|
||||||
'extra': kwargs.get('extra', {'automatic': False}),
|
'extra': kwargs.get('extra', {'automatic': False}),
|
||||||
|
@ -36,12 +36,9 @@ class TestTriggerAuditCommand(DbTestCase):
|
|||||||
audit_template_id=self.audit_template.id)
|
audit_template_id=self.audit_template.id)
|
||||||
|
|
||||||
def test_trigger_audit_without_errors(self):
|
def test_trigger_audit_without_errors(self):
|
||||||
try:
|
|
||||||
model_collector = FakerModelCollector()
|
model_collector = FakerModelCollector()
|
||||||
command = TriggerAuditCommand(MagicMock(), model_collector)
|
command = TriggerAuditCommand(MagicMock(), model_collector)
|
||||||
command.execute(self.audit.uuid, self.context)
|
command.execute(self.audit.uuid, self.context)
|
||||||
except Exception:
|
|
||||||
self.fail("The audit should be trigged without error")
|
|
||||||
|
|
||||||
def test_trigger_audit_state_success(self):
|
def test_trigger_audit_state_success(self):
|
||||||
model_collector = FakerModelCollector()
|
model_collector = FakerModelCollector()
|
||||||
|
@ -13,33 +13,37 @@
|
|||||||
# 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.
|
||||||
import mock
|
from mock import patch
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
from watcher.common.exception import WatcherException
|
||||||
from watcher.decision_engine.strategy.loader import StrategyLoader
|
from watcher.decision_engine.strategy.loader import StrategyLoader
|
||||||
from watcher.decision_engine.strategy.selector.default import StrategySelector
|
from watcher.decision_engine.strategy.selector.default import StrategySelector
|
||||||
from watcher.objects.audit_template import Goal
|
from watcher.tests.base import TestCase
|
||||||
from watcher.tests import base
|
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
class TestStrategySelector(base.BaseTestCase):
|
class TestStrategySelector(TestCase):
|
||||||
|
|
||||||
strategy_selector = StrategySelector()
|
strategy_selector = StrategySelector()
|
||||||
|
|
||||||
def test_define_from_with_empty(self):
|
@patch.object(StrategyLoader, 'load')
|
||||||
expected_goal = None
|
def test_define_from_goal(self, mock_call):
|
||||||
expected_strategy = \
|
cfg.CONF.set_override(
|
||||||
CONF.watcher_goals.goals[Goal.SERVERS_CONSOLIDATION]
|
'goals', {"DUMMY": "fake"}, group='watcher_goals'
|
||||||
with mock.patch.object(StrategyLoader, 'load') as \
|
)
|
||||||
mock_call:
|
expected_goal = 'DUMMY'
|
||||||
|
expected_strategy = CONF.watcher_goals.goals[expected_goal]
|
||||||
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)
|
||||||
|
|
||||||
def test_define_from_goal(self):
|
@patch.object(StrategyLoader, 'load')
|
||||||
expected_goal = Goal.BALANCE_LOAD
|
def test_define_from_goal_with_incorrect_mapping(self, mock_call):
|
||||||
expected_strategy = CONF.watcher_goals.goals[expected_goal]
|
cfg.CONF.set_override(
|
||||||
with mock.patch.object(StrategyLoader, 'load') as \
|
'goals', {}, group='watcher_goals'
|
||||||
mock_call:
|
)
|
||||||
self.strategy_selector.define_from_goal(expected_goal)
|
self.assertRaises(
|
||||||
mock_call.assert_called_once_with(expected_strategy)
|
WatcherException,
|
||||||
|
self.strategy_selector.define_from_goal,
|
||||||
|
"DUMMY"
|
||||||
|
)
|
||||||
|
self.assertEqual(mock_call.call_count, 0)
|
||||||
|
@ -21,14 +21,15 @@ 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.dummy_strategy import DummyStrategy
|
||||||
from watcher.decision_engine.strategy.loader import StrategyLoader
|
from watcher.decision_engine.strategy.loader import StrategyLoader
|
||||||
from watcher.tests import base
|
from watcher.tests.base import TestCase
|
||||||
|
|
||||||
|
|
||||||
class TestLoader(base.BaseTestCase):
|
class TestStrategyLoader(TestCase):
|
||||||
|
|
||||||
@patch("watcher.decision_engine.strategy.loader.ExtensionManager")
|
@patch("watcher.decision_engine.strategy.loader.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
|
||||||
m_extension_manager.return_value = ExtensionManager.make_test_instance(
|
m_extension_manager.return_value = ExtensionManager.make_test_instance(
|
||||||
extensions=[Extension(
|
extensions=[Extension(
|
||||||
name=dummy_strategy_name,
|
name=dummy_strategy_name,
|
||||||
@ -39,7 +40,13 @@ class TestLoader(base.BaseTestCase):
|
|||||||
)],
|
)],
|
||||||
namespace="watcher_strategies",
|
namespace="watcher_strategies",
|
||||||
)
|
)
|
||||||
# Set up the fake Stevedore extensions
|
strategy_loader = StrategyLoader()
|
||||||
|
loaded_strategy = strategy_loader.load("dummy")
|
||||||
|
|
||||||
|
self.assertEqual("dummy", loaded_strategy.name)
|
||||||
|
self.assertEqual("Dummy Strategy", loaded_strategy.description)
|
||||||
|
|
||||||
|
def test_load_dummy_strategy(self):
|
||||||
strategy_loader = StrategyLoader()
|
strategy_loader = StrategyLoader()
|
||||||
loaded_strategy = strategy_loader.load("dummy")
|
loaded_strategy = strategy_loader.load("dummy")
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user