Files
watcher/watcher/decision_engine/framework/default_planner.py
Jean-Emile DARTOIS 74160c5e78 consolidation of watcher
Change-Id: I9c82ef4d8a81af98afdfc34f5ad496bcade4af6a
2015-10-22 17:04:14 +02:00

171 lines
6.3 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- 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 enum import Enum
from watcher.common.exception import MetaActionNotFound
from watcher.common import utils
from watcher.decision_engine.api.planner.planner import Planner
from watcher import objects
from watcher.decision_engine.framework.meta_actions.hypervisor_state import \
ChangeHypervisorState
from watcher.decision_engine.framework.meta_actions.migrate import Migrate
from watcher.decision_engine.framework.meta_actions.power_state import \
ChangePowerState
from watcher.objects.action import Status as AStatus
from watcher.objects.action_plan import Status as APStatus
from watcher.openstack.common import log
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=str(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=str(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=str(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