Move schedule task out of create instance flow
For multi instance creation scenario, we need to schedule for all requested instances first then run the flow separately, so better to move this task out, and leave the OnFailureReschedule task to the flow. Change-Id: If576003cd6a2db0dd90e2ee5cdf0b0cb00f6da63
This commit is contained in:
parent
c2cf94d947
commit
7a341d8e04
|
@ -36,25 +36,6 @@ ACTION = 'instance:create'
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
class ScheduleCreateInstanceTask(flow_utils.MoganTask):
|
|
||||||
"""Activates a scheduler driver and handles any subsequent failure."""
|
|
||||||
|
|
||||||
def __init__(self, manager):
|
|
||||||
requires = ['filter_properties', 'request_spec', 'instance',
|
|
||||||
'context']
|
|
||||||
super(ScheduleCreateInstanceTask, self).__init__(addons=[ACTION],
|
|
||||||
requires=requires)
|
|
||||||
self.manager = manager
|
|
||||||
|
|
||||||
def execute(self, context, instance, request_spec, filter_properties):
|
|
||||||
top_node = self.manager.scheduler_rpcapi.select_destinations(
|
|
||||||
context,
|
|
||||||
request_spec,
|
|
||||||
filter_properties)
|
|
||||||
instance.node_uuid = top_node
|
|
||||||
instance.save()
|
|
||||||
|
|
||||||
|
|
||||||
class OnFailureRescheduleTask(flow_utils.MoganTask):
|
class OnFailureRescheduleTask(flow_utils.MoganTask):
|
||||||
"""Triggers a rescheduling request to be sent when reverting occurs.
|
"""Triggers a rescheduling request to be sent when reverting occurs.
|
||||||
|
|
||||||
|
@ -246,9 +227,9 @@ def get_flow(context, manager, instance, requested_networks, request_spec,
|
||||||
|
|
||||||
This flow will do the following:
|
This flow will do the following:
|
||||||
|
|
||||||
1. Schedule a node to create instance
|
1. Build networks for the instance and set port id back to baremetal port
|
||||||
3. Build networks for the instance and set port id back to baremetal port
|
2. Do node deploy and handle errors.
|
||||||
4. Do node deploy and handle errors.
|
3. Reschedule if the tasks are on failure.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
flow_name = ACTION.replace(":", "_") + "_manager"
|
flow_name = ACTION.replace(":", "_") + "_manager"
|
||||||
|
@ -265,8 +246,7 @@ def get_flow(context, manager, instance, requested_networks, request_spec,
|
||||||
'requested_networks': requested_networks
|
'requested_networks': requested_networks
|
||||||
}
|
}
|
||||||
|
|
||||||
instance_flow.add(ScheduleCreateInstanceTask(manager),
|
instance_flow.add(OnFailureRescheduleTask(manager.engine_rpcapi),
|
||||||
OnFailureRescheduleTask(manager.engine_rpcapi),
|
|
||||||
BuildNetworkTask(manager),
|
BuildNetworkTask(manager),
|
||||||
CreateInstanceTask(manager.driver))
|
CreateInstanceTask(manager.driver))
|
||||||
|
|
||||||
|
|
|
@ -326,6 +326,19 @@ class EngineManager(base_manager.BaseEngineManager):
|
||||||
if filter_properties is None:
|
if filter_properties is None:
|
||||||
filter_properties = {}
|
filter_properties = {}
|
||||||
|
|
||||||
|
try:
|
||||||
|
node = self.scheduler_rpcapi.select_destinations(
|
||||||
|
context, request_spec, filter_properties)
|
||||||
|
instance.node_uuid = node['node_uuid']
|
||||||
|
instance.save()
|
||||||
|
except Exception as e:
|
||||||
|
utils.process_event(fsm, instance, event='error')
|
||||||
|
LOG.error(_LE("Created instance %(uuid)s failed."
|
||||||
|
"Exception: %(exception)s"),
|
||||||
|
{"uuid": instance.uuid,
|
||||||
|
"exception": e})
|
||||||
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
flow_engine = create_instance.get_flow(
|
flow_engine = create_instance.get_flow(
|
||||||
context,
|
context,
|
||||||
|
@ -336,6 +349,7 @@ class EngineManager(base_manager.BaseEngineManager):
|
||||||
filter_properties,
|
filter_properties,
|
||||||
)
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
|
utils.process_event(fsm, instance, event='error')
|
||||||
msg = _("Create manager instance flow failed.")
|
msg = _("Create manager instance flow failed.")
|
||||||
LOG.exception(msg)
|
LOG.exception(msg)
|
||||||
raise exception.MoganException(msg)
|
raise exception.MoganException(msg)
|
||||||
|
|
|
@ -189,8 +189,9 @@ class FilterScheduler(driver.Scheduler):
|
||||||
|
|
||||||
top_node = self._choose_top_node(weighed_nodes, request_spec)
|
top_node = self._choose_top_node(weighed_nodes, request_spec)
|
||||||
top_node.obj.consume_from_request(context)
|
top_node.obj.consume_from_request(context)
|
||||||
self._add_retry_node(filter_properties, top_node.obj.node)
|
self._add_retry_node(filter_properties, top_node.obj.node_uuid)
|
||||||
return top_node.obj.node
|
dest = dict(node_uuid=top_node.obj.node_uuid)
|
||||||
|
return dest
|
||||||
|
|
||||||
return _schedule(self, context, request_spec, filter_properties)
|
return _schedule(self, context, request_spec, filter_properties)
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ class NodeState(object):
|
||||||
"""Mutable and immutable information tracked for a Ironic node."""
|
"""Mutable and immutable information tracked for a Ironic node."""
|
||||||
|
|
||||||
def __init__(self, node):
|
def __init__(self, node):
|
||||||
self.node = node.node_uuid
|
self.node_uuid = node.node_uuid
|
||||||
self.capabilities = node.extra_specs
|
self.capabilities = node.extra_specs
|
||||||
self.availability_zone = node.availability_zone \
|
self.availability_zone = node.availability_zone \
|
||||||
or CONF.engine.default_availability_zone
|
or CONF.engine.default_availability_zone
|
||||||
|
@ -43,7 +43,7 @@ class NodeState(object):
|
||||||
|
|
||||||
def consume_from_request(self, context):
|
def consume_from_request(self, context):
|
||||||
"""Consume the compute node."""
|
"""Consume the compute node."""
|
||||||
objects.ComputeNode.consume_node(context, self.node)
|
objects.ComputeNode.consume_node(context, self.node_uuid)
|
||||||
|
|
||||||
|
|
||||||
class NodeManager(object):
|
class NodeManager(object):
|
||||||
|
|
|
@ -24,12 +24,12 @@ class WeighedNode(base_weight.WeighedObject):
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
return {
|
return {
|
||||||
'weight': self.weight,
|
'weight': self.weight,
|
||||||
'node': self.obj.node,
|
'node': self.obj.node_uuid,
|
||||||
}
|
}
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return ("WeighedNode [node: %s, weight: %s]" %
|
return ("WeighedNode [node: %s, weight: %s]" %
|
||||||
(self.obj.node, self.weight))
|
(self.obj.node_uuid, self.weight))
|
||||||
|
|
||||||
|
|
||||||
class BaseNodeWeigher(base_weight.BaseWeigher):
|
class BaseNodeWeigher(base_weight.BaseWeigher):
|
||||||
|
|
|
@ -16,13 +16,11 @@
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
from oslo_context import context
|
from oslo_context import context
|
||||||
from oslo_utils import uuidutils
|
|
||||||
|
|
||||||
from mogan.engine.baremetal.ironic import IronicDriver
|
from mogan.engine.baremetal.ironic import IronicDriver
|
||||||
from mogan.engine.flows import create_instance
|
from mogan.engine.flows import create_instance
|
||||||
from mogan.engine import manager
|
from mogan.engine import manager
|
||||||
from mogan import objects
|
from mogan import objects
|
||||||
from mogan.scheduler import rpcapi as scheduler_rpcapi
|
|
||||||
from mogan.tests import base
|
from mogan.tests import base
|
||||||
from mogan.tests.unit.objects import utils as obj_utils
|
from mogan.tests.unit.objects import utils as obj_utils
|
||||||
|
|
||||||
|
@ -33,30 +31,6 @@ class CreateInstanceFlowTestCase(base.TestCase):
|
||||||
super(CreateInstanceFlowTestCase, self).setUp()
|
super(CreateInstanceFlowTestCase, self).setUp()
|
||||||
self.ctxt = context.get_admin_context()
|
self.ctxt = context.get_admin_context()
|
||||||
|
|
||||||
@mock.patch.object(objects.instance.Instance, 'save')
|
|
||||||
@mock.patch.object(scheduler_rpcapi.SchedulerAPI, 'select_destinations')
|
|
||||||
def test_schedule_task_execute(self, mock_schedule, mock_save):
|
|
||||||
fake_uuid = uuidutils.generate_uuid()
|
|
||||||
fake_engine_manager = mock.MagicMock()
|
|
||||||
sche_rpcapi = scheduler_rpcapi.SchedulerAPI()
|
|
||||||
fake_engine_manager.scheduler_rpcapi = sche_rpcapi
|
|
||||||
fake_request_spec = mock.MagicMock()
|
|
||||||
fake_filter_props = mock.MagicMock()
|
|
||||||
task = create_instance.ScheduleCreateInstanceTask(
|
|
||||||
fake_engine_manager)
|
|
||||||
instance_obj = obj_utils.get_test_instance(self.ctxt)
|
|
||||||
mock_schedule.return_value = fake_uuid
|
|
||||||
mock_save.side_effect = None
|
|
||||||
|
|
||||||
task.execute(self.ctxt,
|
|
||||||
instance_obj,
|
|
||||||
fake_request_spec,
|
|
||||||
fake_filter_props)
|
|
||||||
mock_schedule.assert_called_once_with(self.ctxt,
|
|
||||||
fake_request_spec,
|
|
||||||
fake_filter_props)
|
|
||||||
self.assertEqual(fake_uuid, instance_obj.node_uuid)
|
|
||||||
|
|
||||||
@mock.patch.object(objects.instance.Instance, 'save')
|
@mock.patch.object(objects.instance.Instance, 'save')
|
||||||
@mock.patch.object(create_instance.BuildNetworkTask, '_build_networks')
|
@mock.patch.object(create_instance.BuildNetworkTask, '_build_networks')
|
||||||
def test_create_network_task_execute(self, mock_build_networks, mock_save):
|
def test_create_network_task_execute(self, mock_build_networks, mock_save):
|
||||||
|
|
Loading…
Reference in New Issue