Merge "Watcher Planner Selector"
This commit is contained in:
commit
62020cac30
@ -26,7 +26,7 @@ from oslo_log import log
|
|||||||
from watcher.applier import rpcapi
|
from watcher.applier import rpcapi
|
||||||
from watcher.common import exception
|
from watcher.common import exception
|
||||||
from watcher.common import service
|
from watcher.common import service
|
||||||
from watcher.decision_engine.planner import manager as planner_manager
|
from watcher.decision_engine.loading import default as loader
|
||||||
from watcher.decision_engine.strategy.context import default as default_context
|
from watcher.decision_engine.strategy.context import default as default_context
|
||||||
from watcher import notifications
|
from watcher import notifications
|
||||||
from watcher import objects
|
from watcher import objects
|
||||||
@ -41,11 +41,11 @@ LOG = log.getLogger(__name__)
|
|||||||
class BaseAuditHandler(object):
|
class BaseAuditHandler(object):
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def execute(self, audit_uuid, request_context):
|
def execute(self, audit, request_context):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def pre_execute(self, audit_uuid, request_context):
|
def pre_execute(self, audit, request_context):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
@ -63,15 +63,18 @@ class AuditHandler(BaseAuditHandler):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(AuditHandler, self).__init__()
|
super(AuditHandler, self).__init__()
|
||||||
self._strategy_context = default_context.DefaultStrategyContext()
|
self._strategy_context = default_context.DefaultStrategyContext()
|
||||||
self._planner_manager = planner_manager.PlannerManager()
|
self._planner_loader = loader.DefaultPlannerLoader()
|
||||||
self._planner = None
|
|
||||||
self.applier_client = rpcapi.ApplierAPI()
|
self.applier_client = rpcapi.ApplierAPI()
|
||||||
|
|
||||||
@property
|
def get_planner(self, audit, request_context):
|
||||||
def planner(self):
|
# because AuditHandler is a singletone we need to avoid race condition.
|
||||||
if self._planner is None:
|
# thus we need to load planner every time
|
||||||
self._planner = self._planner_manager.load()
|
strategy = self.strategy_context.select_strategy(
|
||||||
return self._planner
|
audit, request_context)
|
||||||
|
planner_name = strategy.planner
|
||||||
|
LOG.debug("Loading %s", planner_name)
|
||||||
|
planner = self._planner_loader.load(name=planner_name)
|
||||||
|
return planner
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def strategy_context(self):
|
def strategy_context(self):
|
||||||
@ -90,8 +93,8 @@ class AuditHandler(BaseAuditHandler):
|
|||||||
request_context, audit,
|
request_context, audit,
|
||||||
action=fields.NotificationAction.PLANNER,
|
action=fields.NotificationAction.PLANNER,
|
||||||
phase=fields.NotificationPhase.START)
|
phase=fields.NotificationPhase.START)
|
||||||
action_plan = self.planner.schedule(request_context, audit.id,
|
planner = self.get_planner(audit, request_context)
|
||||||
solution)
|
action_plan = planner.schedule(request_context, audit.id, solution)
|
||||||
notifications.audit.send_action_notification(
|
notifications.audit.send_action_notification(
|
||||||
request_context, audit,
|
request_context, audit,
|
||||||
action=fields.NotificationAction.PLANNER,
|
action=fields.NotificationAction.PLANNER,
|
||||||
@ -105,13 +108,15 @@ class AuditHandler(BaseAuditHandler):
|
|||||||
phase=fields.NotificationPhase.ERROR)
|
phase=fields.NotificationPhase.ERROR)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def update_audit_state(self, audit, state):
|
@staticmethod
|
||||||
|
def update_audit_state(audit, state):
|
||||||
if audit.state != state:
|
if audit.state != state:
|
||||||
LOG.debug("Update audit state: %s", state)
|
LOG.debug("Update audit state: %s", state)
|
||||||
audit.state = state
|
audit.state = state
|
||||||
audit.save()
|
audit.save()
|
||||||
|
|
||||||
def check_ongoing_action_plans(self, request_context):
|
@staticmethod
|
||||||
|
def check_ongoing_action_plans(request_context):
|
||||||
a_plan_filters = {'state': objects.action_plan.State.ONGOING}
|
a_plan_filters = {'state': objects.action_plan.State.ONGOING}
|
||||||
ongoing_action_plans = objects.ActionPlan.list(
|
ongoing_action_plans = objects.ActionPlan.list(
|
||||||
request_context, filters=a_plan_filters)
|
request_context, filters=a_plan_filters)
|
||||||
|
@ -94,7 +94,8 @@ class ContinuousAuditHandler(base.AuditHandler):
|
|||||||
plan.save()
|
plan.save()
|
||||||
return solution
|
return solution
|
||||||
|
|
||||||
def _next_cron_time(self, audit):
|
@staticmethod
|
||||||
|
def _next_cron_time(audit):
|
||||||
if utils.is_cron_like(audit.interval):
|
if utils.is_cron_like(audit.interval):
|
||||||
return croniter(audit.interval, datetime.datetime.utcnow()
|
return croniter(audit.interval, datetime.datetime.utcnow()
|
||||||
).get_next(datetime.datetime)
|
).get_next(datetime.datetime)
|
||||||
|
@ -19,10 +19,7 @@ from oslo_log import log
|
|||||||
|
|
||||||
from watcher.decision_engine.loading import default as loader
|
from watcher.decision_engine.loading import default as loader
|
||||||
|
|
||||||
from watcher import conf
|
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
CONF = conf.CONF
|
|
||||||
|
|
||||||
|
|
||||||
class PlannerManager(object):
|
class PlannerManager(object):
|
||||||
@ -33,7 +30,6 @@ class PlannerManager(object):
|
|||||||
def loader(self):
|
def loader(self):
|
||||||
return self._loader
|
return self._loader
|
||||||
|
|
||||||
def load(self):
|
def load(self, planner_name):
|
||||||
selected_planner = CONF.watcher_planner.planner
|
LOG.debug("Loading %s", planner_name)
|
||||||
LOG.debug("Loading %s", selected_planner)
|
return self.loader.load(name=planner_name)
|
||||||
return self.loader.load(name=selected_planner)
|
|
||||||
|
@ -30,7 +30,8 @@ class DefaultStrategyContext(base.StrategyContext):
|
|||||||
super(DefaultStrategyContext, self).__init__()
|
super(DefaultStrategyContext, self).__init__()
|
||||||
LOG.debug("Initializing Strategy Context")
|
LOG.debug("Initializing Strategy Context")
|
||||||
|
|
||||||
def do_execute_strategy(self, audit, request_context):
|
@staticmethod
|
||||||
|
def select_strategy(audit, request_context):
|
||||||
osc = clients.OpenStackClients()
|
osc = clients.OpenStackClients()
|
||||||
# todo(jed) retrieve in audit parameters (threshold,...)
|
# todo(jed) retrieve in audit parameters (threshold,...)
|
||||||
# todo(jed) create ActionPlan
|
# todo(jed) create ActionPlan
|
||||||
@ -50,9 +51,10 @@ class DefaultStrategyContext(base.StrategyContext):
|
|||||||
goal_name=goal.name,
|
goal_name=goal.name,
|
||||||
strategy_name=strategy_name,
|
strategy_name=strategy_name,
|
||||||
osc=osc)
|
osc=osc)
|
||||||
|
return strategy_selector.select()
|
||||||
|
|
||||||
selected_strategy = strategy_selector.select()
|
def do_execute_strategy(self, audit, request_context):
|
||||||
|
selected_strategy = self.select_strategy(audit, request_context)
|
||||||
selected_strategy.audit_scope = audit.scope
|
selected_strategy.audit_scope = audit.scope
|
||||||
|
|
||||||
schema = selected_strategy.get_schema()
|
schema = selected_strategy.get_schema()
|
||||||
|
@ -161,6 +161,7 @@ class BaseStrategy(loadable.Loadable):
|
|||||||
self._input_parameters = utils.Struct()
|
self._input_parameters = utils.Struct()
|
||||||
self._audit_scope = None
|
self._audit_scope = None
|
||||||
self._datasource_backend = None
|
self._datasource_backend = None
|
||||||
|
self._planner = 'weight'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
@ -432,6 +433,14 @@ class BaseStrategy(loadable.Loadable):
|
|||||||
def state_collector(self, s):
|
def state_collector(self, s):
|
||||||
self._cluster_state_collector = s
|
self._cluster_state_collector = s
|
||||||
|
|
||||||
|
@property
|
||||||
|
def planner(self):
|
||||||
|
return self._planner
|
||||||
|
|
||||||
|
@planner.setter
|
||||||
|
def planner(self, s):
|
||||||
|
self._planner = s
|
||||||
|
|
||||||
def filter_instances_by_audit_tag(self, instances):
|
def filter_instances_by_audit_tag(self, instances):
|
||||||
if not self.config.check_optimize_metadata:
|
if not self.config.check_optimize_metadata:
|
||||||
return instances
|
return instances
|
||||||
@ -512,6 +521,11 @@ class ThermalOptimizationBaseStrategy(BaseStrategy):
|
|||||||
@six.add_metaclass(abc.ABCMeta)
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
class WorkloadStabilizationBaseStrategy(BaseStrategy):
|
class WorkloadStabilizationBaseStrategy(BaseStrategy):
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(WorkloadStabilizationBaseStrategy, self
|
||||||
|
).__init__(*args, **kwargs)
|
||||||
|
self._planner = 'workload_stabilization'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_goal_name(cls):
|
def get_goal_name(cls):
|
||||||
return "workload_balancing"
|
return "workload_balancing"
|
||||||
|
@ -439,7 +439,7 @@ 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, 'get_planner',
|
||||||
mock.Mock())
|
mock.Mock())
|
||||||
@mock.patch.object(base_strategy.BaseStrategy, "compute_model",
|
@mock.patch.object(base_strategy.BaseStrategy, "compute_model",
|
||||||
mock.Mock(stale=False))
|
mock.Mock(stale=False))
|
||||||
|
@ -25,4 +25,6 @@ class TestPlannerManager(base.TestCase):
|
|||||||
def test_load(self):
|
def test_load(self):
|
||||||
cfg.CONF.set_override('planner', "weight", group='watcher_planner')
|
cfg.CONF.set_override('planner', "weight", group='watcher_planner')
|
||||||
manager = planner.PlannerManager()
|
manager = planner.PlannerManager()
|
||||||
self.assertIsInstance(manager.load(), weight.WeightPlanner)
|
selected_planner = cfg.CONF.watcher_planner.planner
|
||||||
|
self.assertIsInstance(manager.load(selected_planner),
|
||||||
|
weight.WeightPlanner)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user