Code refactoring - Watcher Decision Engine package
This patchset is there to change the code structure. The objective is to flatten the project file tree by merging 'api/' and 'framework/' into a single package. This also contains some tidy ups in package naming (like using only singular nouns). This should only affect file/folder names and their subsequent import paths wherever they were used. Change-Id: Ie903ba20ca5cf03b0b42efa60131d1b919b0c2c9
This commit is contained in:
0
watcher/decision_engine/planner/__init__.py
Normal file
0
watcher/decision_engine/planner/__init__.py
Normal file
37
watcher/decision_engine/planner/base.py
Normal file
37
watcher/decision_engine/planner/base.py
Normal file
@@ -0,0 +1,37 @@
|
||||
# -*- 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
|
||||
import six
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class Planner(object):
|
||||
@abc.abstractmethod
|
||||
def schedule(self, context, audit_uuid, solution):
|
||||
"""The planner receives a solution to schedule
|
||||
|
||||
:param solution: the solution given by the strategy to
|
||||
:param audit_uuid: the audit uuid
|
||||
:return: ActionPlan ordered sequence of change requests
|
||||
such that all security, dependency,
|
||||
and performance requirements are met.
|
||||
"""
|
||||
# example: directed acyclic graph
|
||||
raise NotImplementedError(
|
||||
"Should have implemented this") # pragma:no cover
|
||||
180
watcher/decision_engine/planner/default.py
Normal file
180
watcher/decision_engine/planner/default.py
Normal file
@@ -0,0 +1,180 @@
|
||||
# -*- 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.
|
||||
#
|
||||
from oslo_log import log
|
||||
|
||||
from enum import Enum
|
||||
from watcher.common.exception import MetaActionNotFound
|
||||
from watcher.common import utils
|
||||
from watcher.decision_engine.planner.base import Planner
|
||||
|
||||
from watcher import objects
|
||||
|
||||
from watcher.decision_engine.meta_action.hypervisor_state import \
|
||||
ChangeHypervisorState
|
||||
from watcher.decision_engine.meta_action.migrate import Migrate
|
||||
from watcher.decision_engine.meta_action.nop import Nop
|
||||
from watcher.decision_engine.meta_action.power_state import ChangePowerState
|
||||
from watcher.objects.action import Status as AStatus
|
||||
from watcher.objects.action_plan import Status as APStatus
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
# TODO(jed) The default planner is a very simple planner
|
||||
# https://wiki.openstack.org/wiki/NovaOrchestration/WorkflowEngines
|
||||
|
||||
|
||||
class Primitives(Enum):
|
||||
LIVE_MIGRATE = 'MIGRATE'
|
||||
COLD_MIGRATE = 'MIGRATE'
|
||||
POWER_STATE = 'POWERSTATE'
|
||||
HYPERVISOR_STATE = 'HYPERVISOR_STATE'
|
||||
NOP = 'NOP'
|
||||
|
||||
|
||||
priority_primitives = {
|
||||
Primitives.HYPERVISOR_STATE.value: 0,
|
||||
Primitives.LIVE_MIGRATE.value: 1,
|
||||
Primitives.COLD_MIGRATE.value: 2,
|
||||
Primitives.POWER_STATE.value: 3
|
||||
}
|
||||
|
||||
|
||||
class DefaultPlanner(Planner):
|
||||
def create_action(self, action_plan_id, action_type, applies_to=None,
|
||||
src=None,
|
||||
dst=None,
|
||||
parameter=None,
|
||||
description=None):
|
||||
uuid = utils.generate_uuid()
|
||||
|
||||
action = {
|
||||
'uuid': uuid,
|
||||
'action_plan_id': int(action_plan_id),
|
||||
'action_type': action_type,
|
||||
'applies_to': applies_to,
|
||||
'src': src,
|
||||
'dst': dst,
|
||||
'parameter': parameter,
|
||||
'description': description,
|
||||
'state': AStatus.PENDING,
|
||||
'alarm': None,
|
||||
'next': None,
|
||||
}
|
||||
return action
|
||||
|
||||
def schedule(self, context, audit_id, solution):
|
||||
LOG.debug('Create an action plan for the audit uuid')
|
||||
action_plan = self._create_action_plan(context, audit_id)
|
||||
|
||||
actions = list(solution.meta_actions)
|
||||
to_schedule = []
|
||||
|
||||
for action in actions:
|
||||
if isinstance(action, Migrate):
|
||||
# TODO(jed) type
|
||||
primitive = self.create_action(action_plan.id,
|
||||
Primitives.LIVE_MIGRATE.value,
|
||||
action.get_vm().uuid,
|
||||
action.get_source_hypervisor().
|
||||
uuid,
|
||||
action.get_dest_hypervisor().
|
||||
uuid,
|
||||
description="{0}".format(
|
||||
action)
|
||||
)
|
||||
|
||||
elif isinstance(action, ChangePowerState):
|
||||
primitive = self.create_action(action_plan_id=action_plan.id,
|
||||
action_type=Primitives.
|
||||
POWER_STATE.value,
|
||||
applies_to=action.target.uuid,
|
||||
parameter=action.
|
||||
powerstate.
|
||||
value,
|
||||
description="{0}".format(
|
||||
action))
|
||||
elif isinstance(action, ChangeHypervisorState):
|
||||
primitive = self.create_action(action_plan_id=action_plan.id,
|
||||
action_type=Primitives.
|
||||
HYPERVISOR_STATE.value,
|
||||
applies_to=action.target.uuid,
|
||||
parameter=action.state.
|
||||
value,
|
||||
description="{0}".format(
|
||||
action))
|
||||
elif isinstance(action, Nop):
|
||||
primitive = self.create_action(action_plan_id=action_plan.id,
|
||||
action_type=Primitives.
|
||||
NOP.value,
|
||||
description="{0}".format(
|
||||
action))
|
||||
else:
|
||||
raise MetaActionNotFound()
|
||||
priority = priority_primitives[primitive['action_type']]
|
||||
to_schedule.append((priority, primitive))
|
||||
|
||||
# scheduling
|
||||
scheduled = sorted(to_schedule, reverse=False, key=lambda x: (x[0]))
|
||||
if len(scheduled) == 0:
|
||||
LOG.warning("The ActionPlan is empty")
|
||||
action_plan.first_action_id = None
|
||||
action_plan.save()
|
||||
else:
|
||||
parent_action = self._create_action(context,
|
||||
scheduled[0][1],
|
||||
None)
|
||||
scheduled.pop(0)
|
||||
|
||||
action_plan.first_action_id = parent_action.id
|
||||
action_plan.save()
|
||||
|
||||
for s_action in scheduled:
|
||||
action = self._create_action(context, s_action[1],
|
||||
parent_action)
|
||||
parent_action = action
|
||||
return action_plan
|
||||
|
||||
def _create_action_plan(self, context, audit_id):
|
||||
action_plan_dict = {
|
||||
'uuid': utils.generate_uuid(),
|
||||
'audit_id': audit_id,
|
||||
'first_action_id': None,
|
||||
'state': APStatus.RECOMMENDED
|
||||
}
|
||||
|
||||
new_action_plan = objects.ActionPlan(context, **action_plan_dict)
|
||||
new_action_plan.create(context)
|
||||
new_action_plan.save()
|
||||
return new_action_plan
|
||||
|
||||
def _create_action(self, context, _action, parent_action):
|
||||
action_description = str(_action)
|
||||
LOG.debug("Create a action for the following resquest : %s"
|
||||
% action_description)
|
||||
|
||||
new_action = objects.Action(context, **_action)
|
||||
new_action.create(context)
|
||||
new_action.save()
|
||||
|
||||
if parent_action:
|
||||
parent_action.next = new_action.id
|
||||
parent_action.save()
|
||||
|
||||
return new_action
|
||||
Reference in New Issue
Block a user