Merge "Bump major version of Scheduler RPC API to 4.0"
This commit is contained in:
commit
614d88f817
|
@ -23,7 +23,6 @@ import random
|
|||
|
||||
from oslo.config import cfg
|
||||
|
||||
from nova.compute import rpcapi as compute_rpcapi
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
from nova.scheduler import driver
|
||||
|
@ -35,10 +34,6 @@ CONF.import_opt('compute_topic', 'nova.compute.rpcapi')
|
|||
class ChanceScheduler(driver.Scheduler):
|
||||
"""Implements Scheduler as a random node selector."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ChanceScheduler, self).__init__(*args, **kwargs)
|
||||
self.compute_rpcapi = compute_rpcapi.ComputeAPI()
|
||||
|
||||
def _filter_hosts(self, request_spec, hosts, filter_properties):
|
||||
"""Filter a list of hosts based on request_spec."""
|
||||
|
||||
|
@ -77,34 +72,3 @@ class ChanceScheduler(driver.Scheduler):
|
|||
if len(dests) < num_instances:
|
||||
raise exception.NoValidHost(reason='')
|
||||
return dests
|
||||
|
||||
# NOTE(alaski): Remove this method when the scheduler rpc interface is
|
||||
# bumped to 4.x as it is no longer used.
|
||||
def schedule_run_instance(self, context, request_spec,
|
||||
admin_password, injected_files,
|
||||
requested_networks, is_first_time,
|
||||
filter_properties, legacy_bdm_in_spec):
|
||||
"""Create and run an instance or instances."""
|
||||
instance_uuids = request_spec.get('instance_uuids')
|
||||
for num, instance_uuid in enumerate(instance_uuids):
|
||||
request_spec['instance_properties']['launch_index'] = num
|
||||
try:
|
||||
host = self._schedule(context, CONF.compute_topic,
|
||||
request_spec, filter_properties)
|
||||
updated_instance = driver.instance_update_db(context,
|
||||
instance_uuid)
|
||||
self.compute_rpcapi.run_instance(context,
|
||||
instance=updated_instance, host=host,
|
||||
requested_networks=requested_networks,
|
||||
injected_files=injected_files,
|
||||
admin_password=admin_password,
|
||||
is_first_time=is_first_time,
|
||||
request_spec=request_spec,
|
||||
filter_properties=filter_properties,
|
||||
legacy_bdm_in_spec=legacy_bdm_in_spec)
|
||||
except Exception as ex:
|
||||
# NOTE(vish): we don't reraise the exception here to make sure
|
||||
# that all instances in the request get set to
|
||||
# error properly
|
||||
driver.handle_schedule_error(context, ex, instance_uuid,
|
||||
request_spec)
|
||||
|
|
|
@ -115,16 +115,6 @@ class Scheduler(object):
|
|||
for service in services
|
||||
if self.servicegroup_api.service_is_up(service)]
|
||||
|
||||
# NOTE(alaski): Remove this method when the scheduler rpc interface is
|
||||
# bumped to 4.x as it is no longer used.
|
||||
def schedule_run_instance(self, context, request_spec,
|
||||
admin_password, injected_files,
|
||||
requested_networks, is_first_time,
|
||||
filter_properties, legacy_bdm_in_spec):
|
||||
"""Must override schedule_run_instance method for scheduler to work."""
|
||||
msg = _("Driver must implement schedule_run_instance")
|
||||
raise NotImplementedError(msg)
|
||||
|
||||
def select_destinations(self, context, request_spec, filter_properties):
|
||||
"""Must override select_destinations method.
|
||||
|
||||
|
|
|
@ -23,14 +23,12 @@ import random
|
|||
|
||||
from oslo.config import cfg
|
||||
|
||||
from nova.compute import rpcapi as compute_rpcapi
|
||||
from nova import exception
|
||||
from nova.i18n import _, _LI, _LW
|
||||
from nova.i18n import _
|
||||
from nova.openstack.common import log as logging
|
||||
from nova import rpc
|
||||
from nova.scheduler import driver
|
||||
from nova.scheduler import scheduler_options
|
||||
from nova.scheduler import utils as scheduler_utils
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
@ -57,81 +55,8 @@ class FilterScheduler(driver.Scheduler):
|
|||
def __init__(self, *args, **kwargs):
|
||||
super(FilterScheduler, self).__init__(*args, **kwargs)
|
||||
self.options = scheduler_options.SchedulerOptions()
|
||||
self.compute_rpcapi = compute_rpcapi.ComputeAPI()
|
||||
self.notifier = rpc.get_notifier('scheduler')
|
||||
|
||||
# NOTE(alaski): Remove this method when the scheduler rpc interface is
|
||||
# bumped to 4.x as it is no longer used.
|
||||
def schedule_run_instance(self, context, request_spec,
|
||||
admin_password, injected_files,
|
||||
requested_networks, is_first_time,
|
||||
filter_properties, legacy_bdm_in_spec):
|
||||
"""Provisions instances that needs to be scheduled
|
||||
|
||||
Applies filters and weighters on request properties to get a list of
|
||||
compute hosts and calls them to spawn instance(s).
|
||||
"""
|
||||
payload = dict(request_spec=request_spec)
|
||||
self.notifier.info(context, 'scheduler.run_instance.start', payload)
|
||||
|
||||
instance_uuids = request_spec.get('instance_uuids')
|
||||
LOG.info(_LI("Attempting to build %(num_instances)d instance(s) "
|
||||
"uuids: %(instance_uuids)s"),
|
||||
{'num_instances': len(instance_uuids),
|
||||
'instance_uuids': instance_uuids})
|
||||
LOG.debug("Request Spec: %s" % request_spec)
|
||||
|
||||
# check retry policy. Rather ugly use of instance_uuids[0]...
|
||||
# but if we've exceeded max retries... then we really only
|
||||
# have a single instance.
|
||||
scheduler_utils.populate_retry(filter_properties,
|
||||
instance_uuids[0])
|
||||
weighed_hosts = self._schedule(context, request_spec,
|
||||
filter_properties)
|
||||
|
||||
# NOTE: Pop instance_uuids as individual creates do not need the
|
||||
# set of uuids. Do not pop before here as the upper exception
|
||||
# handler fo NoValidHost needs the uuid to set error state
|
||||
instance_uuids = request_spec.pop('instance_uuids')
|
||||
|
||||
# NOTE(comstud): Make sure we do not pass this through. It
|
||||
# contains an instance of RpcContext that cannot be serialized.
|
||||
filter_properties.pop('context', None)
|
||||
|
||||
for num, instance_uuid in enumerate(instance_uuids):
|
||||
request_spec['instance_properties']['launch_index'] = num
|
||||
|
||||
try:
|
||||
try:
|
||||
weighed_host = weighed_hosts.pop(0)
|
||||
LOG.info(_LI("Choosing host %(weighed_host)s "
|
||||
"for instance %(instance_uuid)s"),
|
||||
{'weighed_host': weighed_host,
|
||||
'instance_uuid': instance_uuid})
|
||||
except IndexError:
|
||||
raise exception.NoValidHost(reason="")
|
||||
|
||||
self._provision_resource(context, weighed_host,
|
||||
request_spec,
|
||||
filter_properties,
|
||||
requested_networks,
|
||||
injected_files, admin_password,
|
||||
is_first_time,
|
||||
instance_uuid=instance_uuid,
|
||||
legacy_bdm_in_spec=legacy_bdm_in_spec)
|
||||
except Exception as ex:
|
||||
# NOTE(vish): we don't reraise the exception here to make sure
|
||||
# that all instances in the request get set to
|
||||
# error properly
|
||||
driver.handle_schedule_error(context, ex, instance_uuid,
|
||||
request_spec)
|
||||
# scrub retry host list in case we're scheduling multiple
|
||||
# instances:
|
||||
retry = filter_properties.get('retry', {})
|
||||
retry['hosts'] = []
|
||||
|
||||
self.notifier.info(context, 'scheduler.run_instance.end', payload)
|
||||
|
||||
def select_destinations(self, context, request_spec, filter_properties):
|
||||
"""Selects a filtered set of hosts and nodes."""
|
||||
self.notifier.info(context, 'scheduler.select_destinations.start',
|
||||
|
@ -161,42 +86,6 @@ class FilterScheduler(driver.Scheduler):
|
|||
dict(request_spec=request_spec))
|
||||
return dests
|
||||
|
||||
def _provision_resource(self, context, weighed_host, request_spec,
|
||||
filter_properties, requested_networks, injected_files,
|
||||
admin_password, is_first_time, instance_uuid=None,
|
||||
legacy_bdm_in_spec=True):
|
||||
"""Create the requested resource in this Zone."""
|
||||
# NOTE(vish): add our current instance back into the request spec
|
||||
request_spec['instance_uuids'] = [instance_uuid]
|
||||
payload = dict(request_spec=request_spec,
|
||||
weighted_host=weighed_host.to_dict(),
|
||||
instance_id=instance_uuid)
|
||||
self.notifier.info(context,
|
||||
'scheduler.run_instance.scheduled', payload)
|
||||
|
||||
# Update the metadata if necessary
|
||||
try:
|
||||
updated_instance = driver.instance_update_db(context,
|
||||
instance_uuid)
|
||||
except exception.InstanceNotFound:
|
||||
LOG.warning(_LW("Instance disappeared during scheduling"),
|
||||
context=context, instance_uuid=instance_uuid)
|
||||
|
||||
else:
|
||||
scheduler_utils.populate_filter_properties(filter_properties,
|
||||
weighed_host.obj)
|
||||
|
||||
self.compute_rpcapi.run_instance(context,
|
||||
instance=updated_instance,
|
||||
host=weighed_host.obj.host,
|
||||
request_spec=request_spec,
|
||||
filter_properties=filter_properties,
|
||||
requested_networks=requested_networks,
|
||||
injected_files=injected_files,
|
||||
admin_password=admin_password, is_first_time=is_first_time,
|
||||
node=weighed_host.obj.nodename,
|
||||
legacy_bdm_in_spec=legacy_bdm_in_spec)
|
||||
|
||||
def _get_configuration_options(self):
|
||||
"""Fetch options dictionary. Broken out for testing."""
|
||||
return self.options.get_configuration()
|
||||
|
|
|
@ -22,19 +22,14 @@ Scheduler Service
|
|||
from oslo.config import cfg
|
||||
from oslo import messaging
|
||||
from oslo.serialization import jsonutils
|
||||
from oslo.utils import excutils
|
||||
from oslo.utils import importutils
|
||||
|
||||
from nova.compute import rpcapi as compute_rpcapi
|
||||
from nova.compute import utils as compute_utils
|
||||
from nova.compute import vm_states
|
||||
from nova import exception
|
||||
from nova import manager
|
||||
from nova import objects
|
||||
from nova.openstack.common import log as logging
|
||||
from nova.openstack.common import periodic_task
|
||||
from nova import quota
|
||||
from nova.scheduler import utils as scheduler_utils
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
@ -60,99 +55,15 @@ QUOTAS = quota.QUOTAS
|
|||
class SchedulerManager(manager.Manager):
|
||||
"""Chooses a host to run instances on."""
|
||||
|
||||
target = messaging.Target(version='3.1')
|
||||
target = messaging.Target(version='4.0')
|
||||
|
||||
def __init__(self, scheduler_driver=None, *args, **kwargs):
|
||||
if not scheduler_driver:
|
||||
scheduler_driver = CONF.scheduler_driver
|
||||
self.driver = importutils.import_object(scheduler_driver)
|
||||
self.compute_rpcapi = compute_rpcapi.ComputeAPI()
|
||||
super(SchedulerManager, self).__init__(service_name='scheduler',
|
||||
*args, **kwargs)
|
||||
|
||||
# NOTE(alaski): Remove this method when the scheduler rpc interface is
|
||||
# bumped to 4.x as it is no longer used.
|
||||
def run_instance(self, context, request_spec, admin_password,
|
||||
injected_files, requested_networks, is_first_time,
|
||||
filter_properties, legacy_bdm_in_spec):
|
||||
"""Tries to call schedule_run_instance on the driver.
|
||||
Sets instance vm_state to ERROR on exceptions
|
||||
"""
|
||||
instance_uuids = request_spec['instance_uuids']
|
||||
with compute_utils.EventReporter(context, 'schedule', *instance_uuids):
|
||||
try:
|
||||
return self.driver.schedule_run_instance(context,
|
||||
request_spec, admin_password, injected_files,
|
||||
requested_networks, is_first_time, filter_properties,
|
||||
legacy_bdm_in_spec)
|
||||
|
||||
except exception.NoValidHost as ex:
|
||||
# don't re-raise
|
||||
self._set_vm_state_and_notify('run_instance',
|
||||
{'vm_state': vm_states.ERROR,
|
||||
'task_state': None},
|
||||
context, ex, request_spec)
|
||||
except Exception as ex:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self._set_vm_state_and_notify('run_instance',
|
||||
{'vm_state': vm_states.ERROR,
|
||||
'task_state': None},
|
||||
context, ex, request_spec)
|
||||
|
||||
# NOTE(sbauza): Remove this method when the scheduler rpc interface is
|
||||
# bumped to 4.x as it is no longer used.
|
||||
def prep_resize(self, context, image, request_spec, filter_properties,
|
||||
instance, instance_type, reservations):
|
||||
"""Tries to call schedule_prep_resize on the driver.
|
||||
Sets instance vm_state to ACTIVE on NoHostFound
|
||||
Sets vm_state to ERROR on other exceptions
|
||||
"""
|
||||
instance_uuid = instance['uuid']
|
||||
with compute_utils.EventReporter(context, 'schedule', instance_uuid):
|
||||
try:
|
||||
request_spec['num_instances'] = len(
|
||||
request_spec['instance_uuids'])
|
||||
hosts = self.driver.select_destinations(
|
||||
context, request_spec, filter_properties)
|
||||
host_state = hosts[0]
|
||||
|
||||
scheduler_utils.populate_filter_properties(filter_properties,
|
||||
host_state)
|
||||
# context is not serializable
|
||||
filter_properties.pop('context', None)
|
||||
|
||||
(host, node) = (host_state['host'], host_state['nodename'])
|
||||
attrs = ['metadata', 'system_metadata', 'info_cache',
|
||||
'security_groups']
|
||||
inst_obj = objects.Instance._from_db_object(
|
||||
context, objects.Instance(), instance,
|
||||
expected_attrs=attrs)
|
||||
self.compute_rpcapi.prep_resize(
|
||||
context, image, inst_obj, instance_type, host,
|
||||
reservations, request_spec=request_spec,
|
||||
filter_properties=filter_properties, node=node)
|
||||
|
||||
except exception.NoValidHost as ex:
|
||||
vm_state = instance.get('vm_state', vm_states.ACTIVE)
|
||||
self._set_vm_state_and_notify('prep_resize',
|
||||
{'vm_state': vm_state,
|
||||
'task_state': None},
|
||||
context, ex, request_spec)
|
||||
if reservations:
|
||||
QUOTAS.rollback(context, reservations)
|
||||
except Exception as ex:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self._set_vm_state_and_notify('prep_resize',
|
||||
{'vm_state': vm_states.ERROR,
|
||||
'task_state': None},
|
||||
context, ex, request_spec)
|
||||
if reservations:
|
||||
QUOTAS.rollback(context, reservations)
|
||||
|
||||
def _set_vm_state_and_notify(self, method, updates, context, ex,
|
||||
request_spec):
|
||||
scheduler_utils.set_vm_state_and_notify(
|
||||
context, 'scheduler', method, updates, ex, request_spec, self.db)
|
||||
self.additional_endpoints.append(_SchedulerManagerV3Proxy(self))
|
||||
|
||||
@periodic_task.periodic_task
|
||||
def _expire_reservations(self, context):
|
||||
|
@ -163,6 +74,30 @@ class SchedulerManager(manager.Manager):
|
|||
def _run_periodic_tasks(self, context):
|
||||
self.driver.run_periodic_tasks(context)
|
||||
|
||||
@messaging.expected_exceptions(exception.NoValidHost)
|
||||
def select_destinations(self, context, request_spec, filter_properties):
|
||||
"""Returns destinations(s) best suited for this request_spec and
|
||||
filter_properties.
|
||||
|
||||
The result should be a list of dicts with 'host', 'nodename' and
|
||||
'limits' as keys.
|
||||
"""
|
||||
dests = self.driver.select_destinations(context, request_spec,
|
||||
filter_properties)
|
||||
return jsonutils.to_primitive(dests)
|
||||
|
||||
|
||||
class _SchedulerManagerV3Proxy(object):
|
||||
|
||||
target = messaging.Target(version='3.0')
|
||||
|
||||
def __init__(self, manager):
|
||||
self.manager = manager
|
||||
|
||||
# NOTE(sbauza): Previous run_instance() and prep_resize() methods were
|
||||
# removed from the Juno branch before Juno released, so we can safely
|
||||
# remove them even from the V3.1 proxy as there is no Juno RPC client
|
||||
# that can call them
|
||||
@messaging.expected_exceptions(exception.NoValidHost)
|
||||
def select_destinations(self, context, request_spec, filter_properties):
|
||||
"""Returns destinations(s) best suited for this request_spec and
|
||||
|
@ -178,6 +113,6 @@ class SchedulerManager(manager.Manager):
|
|||
# is receiving an object, so lookup the flavor to ensure this.
|
||||
flavor = objects.Flavor.get_by_id(context, flavor['id'])
|
||||
filter_properties = dict(filter_properties, instance_type=flavor)
|
||||
dests = self.driver.select_destinations(context, request_spec,
|
||||
dests = self.manager.select_destinations(context, request_spec,
|
||||
filter_properties)
|
||||
return jsonutils.to_primitive(dests)
|
||||
return dests
|
||||
|
|
|
@ -86,6 +86,9 @@ class SchedulerAPI(object):
|
|||
|
||||
* 3.1 - Made select_destinations() send flavor object
|
||||
|
||||
* 4.0 - Removed backwards compat for Icehouse
|
||||
|
||||
|
||||
'''
|
||||
|
||||
VERSION_ALIASES = {
|
||||
|
@ -93,11 +96,12 @@ class SchedulerAPI(object):
|
|||
'havana': '2.9',
|
||||
'icehouse': '3.0',
|
||||
'juno': '3.0',
|
||||
'kilo': '4.0',
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
super(SchedulerAPI, self).__init__()
|
||||
target = messaging.Target(topic=CONF.scheduler_topic, version='3.0')
|
||||
target = messaging.Target(topic=CONF.scheduler_topic, version='4.0')
|
||||
version_cap = self.VERSION_ALIASES.get(CONF.upgrade_levels.scheduler,
|
||||
CONF.upgrade_levels.scheduler)
|
||||
serializer = objects_base.NovaObjectSerializer()
|
||||
|
@ -105,14 +109,6 @@ class SchedulerAPI(object):
|
|||
serializer=serializer)
|
||||
|
||||
def select_destinations(self, ctxt, request_spec, filter_properties):
|
||||
version = '3.1'
|
||||
if not self.client.can_send_version(version):
|
||||
version = '3.0'
|
||||
if 'instance_type' in filter_properties:
|
||||
flavor = filter_properties['instance_type']
|
||||
flavor_p = objects_base.obj_to_primitive(flavor)
|
||||
filter_properties = dict(filter_properties,
|
||||
instance_type=flavor_p)
|
||||
cctxt = self.client.prepare(version=version)
|
||||
cctxt = self.client.prepare(version='4.0')
|
||||
return cctxt.call(ctxt, 'select_destinations',
|
||||
request_spec=request_spec, filter_properties=filter_properties)
|
||||
|
|
|
@ -20,14 +20,9 @@ import random
|
|||
|
||||
from mox3 import mox
|
||||
|
||||
from nova.compute import rpcapi as compute_rpcapi
|
||||
from nova.compute import utils as compute_utils
|
||||
from nova.compute import vm_states
|
||||
from nova import context
|
||||
from nova import db
|
||||
from nova import exception
|
||||
from nova.scheduler import chance
|
||||
from nova.scheduler import driver
|
||||
from nova.tests.unit.scheduler import test_scheduler
|
||||
|
||||
|
||||
|
@ -62,80 +57,6 @@ class ChanceSchedulerTestCase(test_scheduler.SchedulerTestCase):
|
|||
filter_properties=filter_properties)
|
||||
self.assertEqual(filtered, hosts)
|
||||
|
||||
def test_basic_schedule_run_instance(self):
|
||||
ctxt = context.RequestContext('fake', 'fake', False)
|
||||
ctxt_elevated = 'fake-context-elevated'
|
||||
instance_opts = {'fake_opt1': 'meow', 'launch_index': -1}
|
||||
instance1 = {'uuid': 'fake-uuid1'}
|
||||
instance2 = {'uuid': 'fake-uuid2'}
|
||||
request_spec = {'instance_uuids': ['fake-uuid1', 'fake-uuid2'],
|
||||
'instance_properties': instance_opts}
|
||||
|
||||
def inc_launch_index(*args):
|
||||
request_spec['instance_properties']['launch_index'] = (
|
||||
request_spec['instance_properties']['launch_index'] + 1)
|
||||
|
||||
self.mox.StubOutWithMock(ctxt, 'elevated')
|
||||
self.mox.StubOutWithMock(self.driver, 'hosts_up')
|
||||
self.mox.StubOutWithMock(random, 'choice')
|
||||
self.mox.StubOutWithMock(driver, 'instance_update_db')
|
||||
self.mox.StubOutWithMock(compute_rpcapi.ComputeAPI, 'run_instance')
|
||||
|
||||
ctxt.elevated().AndReturn(ctxt_elevated)
|
||||
# instance 1
|
||||
hosts_full = ['host1', 'host2', 'host3', 'host4']
|
||||
self.driver.hosts_up(ctxt_elevated, 'compute').AndReturn(hosts_full)
|
||||
random.choice(hosts_full).AndReturn('host3')
|
||||
driver.instance_update_db(ctxt, instance1['uuid']).WithSideEffects(
|
||||
inc_launch_index).AndReturn(instance1)
|
||||
compute_rpcapi.ComputeAPI.run_instance(ctxt, host='host3',
|
||||
instance=instance1, requested_networks=None,
|
||||
injected_files=None, admin_password=None, is_first_time=None,
|
||||
request_spec=request_spec, filter_properties={},
|
||||
legacy_bdm_in_spec=False)
|
||||
|
||||
# instance 2
|
||||
ctxt.elevated().AndReturn(ctxt_elevated)
|
||||
self.driver.hosts_up(ctxt_elevated, 'compute').AndReturn(hosts_full)
|
||||
random.choice(hosts_full).AndReturn('host1')
|
||||
driver.instance_update_db(ctxt, instance2['uuid']).WithSideEffects(
|
||||
inc_launch_index).AndReturn(instance2)
|
||||
compute_rpcapi.ComputeAPI.run_instance(ctxt, host='host1',
|
||||
instance=instance2, requested_networks=None,
|
||||
injected_files=None, admin_password=None, is_first_time=None,
|
||||
request_spec=request_spec, filter_properties={},
|
||||
legacy_bdm_in_spec=False)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
self.driver.schedule_run_instance(ctxt, request_spec,
|
||||
None, None, None, None, {}, False)
|
||||
|
||||
def test_basic_schedule_run_instance_no_hosts(self):
|
||||
ctxt = context.RequestContext('fake', 'fake', False)
|
||||
ctxt_elevated = 'fake-context-elevated'
|
||||
uuid = 'fake-uuid1'
|
||||
instance_opts = {'fake_opt1': 'meow', 'launch_index': -1}
|
||||
request_spec = {'instance_uuids': [uuid],
|
||||
'instance_properties': instance_opts}
|
||||
|
||||
self.mox.StubOutWithMock(ctxt, 'elevated')
|
||||
self.mox.StubOutWithMock(self.driver, 'hosts_up')
|
||||
self.mox.StubOutWithMock(compute_utils, 'add_instance_fault_from_exc')
|
||||
self.mox.StubOutWithMock(db, 'instance_update_and_get_original')
|
||||
|
||||
# instance 1
|
||||
ctxt.elevated().AndReturn(ctxt_elevated)
|
||||
self.driver.hosts_up(ctxt_elevated, 'compute').AndReturn([])
|
||||
old_ref, new_ref = db.instance_update_and_get_original(ctxt, uuid,
|
||||
{'vm_state': vm_states.ERROR,
|
||||
'task_state': None}).AndReturn(({}, {}))
|
||||
compute_utils.add_instance_fault_from_exc(ctxt, new_ref,
|
||||
mox.IsA(exception.NoValidHost), mox.IgnoreArg())
|
||||
|
||||
self.mox.ReplayAll()
|
||||
self.driver.schedule_run_instance(
|
||||
ctxt, request_spec, None, None, None, None, {}, False)
|
||||
|
||||
def test_select_destinations(self):
|
||||
ctxt = context.RequestContext('fake', 'fake', False)
|
||||
ctxt_elevated = 'fake-context-elevated'
|
||||
|
|
|
@ -17,14 +17,9 @@ Tests For Filter Scheduler.
|
|||
"""
|
||||
|
||||
import mock
|
||||
from mox3 import mox
|
||||
|
||||
from nova.compute import utils as compute_utils
|
||||
from nova.compute import vm_states
|
||||
from nova import context
|
||||
from nova import db
|
||||
from nova import exception
|
||||
from nova.scheduler import driver
|
||||
from nova.scheduler import filter_scheduler
|
||||
from nova.scheduler import host_manager
|
||||
from nova.scheduler import utils as scheduler_utils
|
||||
|
@ -42,108 +37,6 @@ class FilterSchedulerTestCase(test_scheduler.SchedulerTestCase):
|
|||
|
||||
driver_cls = filter_scheduler.FilterScheduler
|
||||
|
||||
def test_run_instance_no_hosts(self):
|
||||
sched = fakes.FakeFilterScheduler()
|
||||
uuid = 'fake-uuid1'
|
||||
fake_context = context.RequestContext('user', 'project')
|
||||
instance_properties = {'project_id': 1, 'os_type': 'Linux'}
|
||||
request_spec = {'instance_type': {'memory_mb': 1, 'root_gb': 1,
|
||||
'ephemeral_gb': 0},
|
||||
'instance_properties': instance_properties,
|
||||
'instance_uuids': [uuid]}
|
||||
|
||||
self.mox.StubOutWithMock(compute_utils, 'add_instance_fault_from_exc')
|
||||
self.mox.StubOutWithMock(db, 'instance_update_and_get_original')
|
||||
old_ref, new_ref = db.instance_update_and_get_original(fake_context,
|
||||
uuid, {'vm_state': vm_states.ERROR, 'task_state':
|
||||
None}).AndReturn(({}, {}))
|
||||
compute_utils.add_instance_fault_from_exc(fake_context, new_ref,
|
||||
mox.IsA(exception.NoValidHost), mox.IgnoreArg())
|
||||
|
||||
self.mox.StubOutWithMock(db, 'compute_node_get_all')
|
||||
db.compute_node_get_all(mox.IgnoreArg()).AndReturn([])
|
||||
|
||||
self.mox.ReplayAll()
|
||||
sched.schedule_run_instance(
|
||||
fake_context, request_spec, None, None,
|
||||
None, None, {}, False)
|
||||
|
||||
def test_run_instance_non_admin(self):
|
||||
self.was_admin = False
|
||||
|
||||
def fake_get(context, *args, **kwargs):
|
||||
# make sure this is called with admin context, even though
|
||||
# we're using user context below
|
||||
self.was_admin = context.is_admin
|
||||
return {}
|
||||
|
||||
sched = fakes.FakeFilterScheduler()
|
||||
self.stubs.Set(sched.host_manager, 'get_all_host_states', fake_get)
|
||||
|
||||
fake_context = context.RequestContext('user', 'project')
|
||||
|
||||
uuid = 'fake-uuid1'
|
||||
instance_properties = {'project_id': 1, 'os_type': 'Linux'}
|
||||
request_spec = {'instance_type': {'memory_mb': 1, 'local_gb': 1},
|
||||
'instance_properties': instance_properties,
|
||||
'instance_uuids': [uuid]}
|
||||
self.mox.StubOutWithMock(compute_utils, 'add_instance_fault_from_exc')
|
||||
self.mox.StubOutWithMock(db, 'instance_update_and_get_original')
|
||||
old_ref, new_ref = db.instance_update_and_get_original(fake_context,
|
||||
uuid, {'vm_state': vm_states.ERROR, 'task_state':
|
||||
None}).AndReturn(({}, {}))
|
||||
compute_utils.add_instance_fault_from_exc(fake_context, new_ref,
|
||||
mox.IsA(exception.NoValidHost), mox.IgnoreArg())
|
||||
self.mox.ReplayAll()
|
||||
sched.schedule_run_instance(
|
||||
fake_context, request_spec, None, None, None, None, {}, False)
|
||||
self.assertTrue(self.was_admin)
|
||||
|
||||
def test_scheduler_includes_launch_index(self):
|
||||
fake_context = context.RequestContext('user', 'project')
|
||||
instance_opts = {'fake_opt1': 'meow'}
|
||||
request_spec = {'instance_uuids': ['fake-uuid1', 'fake-uuid2'],
|
||||
'instance_properties': instance_opts}
|
||||
instance1 = {'uuid': 'fake-uuid1'}
|
||||
instance2 = {'uuid': 'fake-uuid2'}
|
||||
|
||||
def _has_launch_index(expected_index):
|
||||
"""Return a function that verifies the expected index."""
|
||||
def _check_launch_index(value):
|
||||
if 'instance_properties' in value:
|
||||
if 'launch_index' in value['instance_properties']:
|
||||
index = value['instance_properties']['launch_index']
|
||||
if index == expected_index:
|
||||
return True
|
||||
return False
|
||||
return _check_launch_index
|
||||
|
||||
self.mox.StubOutWithMock(self.driver, '_schedule')
|
||||
self.mox.StubOutWithMock(self.driver, '_provision_resource')
|
||||
|
||||
expected_filter_properties = {'retry': {'num_attempts': 1,
|
||||
'hosts': []}}
|
||||
self.driver._schedule(fake_context, request_spec,
|
||||
expected_filter_properties).AndReturn(['host1', 'host2'])
|
||||
# instance 1
|
||||
self.driver._provision_resource(
|
||||
fake_context, 'host1',
|
||||
mox.Func(_has_launch_index(0)), expected_filter_properties,
|
||||
None, None, None, None,
|
||||
instance_uuid='fake-uuid1',
|
||||
legacy_bdm_in_spec=False).AndReturn(instance1)
|
||||
# instance 2
|
||||
self.driver._provision_resource(
|
||||
fake_context, 'host2',
|
||||
mox.Func(_has_launch_index(1)), expected_filter_properties,
|
||||
None, None, None, None,
|
||||
instance_uuid='fake-uuid2',
|
||||
legacy_bdm_in_spec=False).AndReturn(instance2)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
self.driver.schedule_run_instance(fake_context, request_spec,
|
||||
None, None, None, None, {}, False)
|
||||
|
||||
@mock.patch('nova.db.instance_extra_get_by_instance_uuid',
|
||||
return_value={'numa_topology': None,
|
||||
'pci_requests': None})
|
||||
|
@ -195,148 +88,6 @@ class FilterSchedulerTestCase(test_scheduler.SchedulerTestCase):
|
|||
self.assertRaises(exception.NovaException,
|
||||
scheduler_utils._max_attempts)
|
||||
|
||||
def test_retry_disabled(self):
|
||||
# Retry info should not get populated when re-scheduling is off.
|
||||
self.flags(scheduler_max_attempts=1)
|
||||
sched = fakes.FakeFilterScheduler()
|
||||
request_spec = dict(instance_properties={},
|
||||
instance_uuids=['fake-uuid1'])
|
||||
filter_properties = {}
|
||||
|
||||
self.mox.StubOutWithMock(sched, '_schedule')
|
||||
self.mox.StubOutWithMock(sched, '_provision_resource')
|
||||
|
||||
sched._schedule(self.context, request_spec,
|
||||
filter_properties).AndReturn(['host1'])
|
||||
sched._provision_resource(
|
||||
self.context, 'host1',
|
||||
request_spec, filter_properties,
|
||||
None, None, None, None,
|
||||
instance_uuid='fake-uuid1',
|
||||
legacy_bdm_in_spec=False)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
sched.schedule_run_instance(self.context, request_spec, None, None,
|
||||
None, None, filter_properties, False)
|
||||
|
||||
def test_retry_force_hosts(self):
|
||||
# Retry info should not get populated when re-scheduling is off.
|
||||
self.flags(scheduler_max_attempts=2)
|
||||
sched = fakes.FakeFilterScheduler()
|
||||
request_spec = dict(instance_properties={},
|
||||
instance_uuids=['fake-uuid1'])
|
||||
filter_properties = {'force_hosts': ['force_host']}
|
||||
|
||||
self.mox.StubOutWithMock(sched, '_schedule')
|
||||
self.mox.StubOutWithMock(sched, '_provision_resource')
|
||||
|
||||
sched._schedule(self.context, request_spec,
|
||||
filter_properties).AndReturn(['host1'])
|
||||
sched._provision_resource(
|
||||
self.context, 'host1',
|
||||
request_spec, filter_properties,
|
||||
None, None, None, None,
|
||||
instance_uuid='fake-uuid1',
|
||||
legacy_bdm_in_spec=False)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
sched.schedule_run_instance(self.context, request_spec, None, None,
|
||||
None, None, filter_properties, False)
|
||||
|
||||
def test_retry_force_nodes(self):
|
||||
# Retry info should not get populated when re-scheduling is off.
|
||||
self.flags(scheduler_max_attempts=2)
|
||||
sched = fakes.FakeFilterScheduler()
|
||||
request_spec = dict(instance_properties={},
|
||||
instance_uuids=['fake-uuid1'])
|
||||
filter_properties = {'force_nodes': ['force_node']}
|
||||
|
||||
self.mox.StubOutWithMock(sched, '_schedule')
|
||||
self.mox.StubOutWithMock(sched, '_provision_resource')
|
||||
|
||||
sched._schedule(self.context, request_spec,
|
||||
filter_properties).AndReturn(['host1'])
|
||||
sched._provision_resource(
|
||||
self.context, 'host1',
|
||||
request_spec, filter_properties,
|
||||
None, None, None, None,
|
||||
instance_uuid='fake-uuid1',
|
||||
legacy_bdm_in_spec=False)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
sched.schedule_run_instance(self.context, request_spec, None, None,
|
||||
None, None, filter_properties, False)
|
||||
|
||||
def test_retry_attempt_one(self):
|
||||
# Test retry logic on initial scheduling attempt.
|
||||
self.flags(scheduler_max_attempts=2)
|
||||
sched = fakes.FakeFilterScheduler()
|
||||
request_spec = dict(instance_properties={},
|
||||
instance_uuids=['fake-uuid1'])
|
||||
filter_properties = {}
|
||||
expected_filter_properties = {'retry': {'num_attempts': 1,
|
||||
'hosts': []}}
|
||||
self.mox.StubOutWithMock(sched, '_schedule')
|
||||
self.mox.StubOutWithMock(sched, '_provision_resource')
|
||||
|
||||
sched._schedule(self.context, request_spec,
|
||||
expected_filter_properties).AndReturn(['host1'])
|
||||
sched._provision_resource(
|
||||
self.context, 'host1',
|
||||
request_spec, expected_filter_properties,
|
||||
None, None, None, None,
|
||||
instance_uuid='fake-uuid1',
|
||||
legacy_bdm_in_spec=False)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
sched.schedule_run_instance(self.context, request_spec, None, None,
|
||||
None, None, filter_properties, False)
|
||||
|
||||
def test_retry_attempt_two(self):
|
||||
# Test retry logic when re-scheduling.
|
||||
self.flags(scheduler_max_attempts=2)
|
||||
sched = fakes.FakeFilterScheduler()
|
||||
request_spec = dict(instance_properties={},
|
||||
instance_uuids=['fake-uuid1'])
|
||||
filter_properties = {'retry': {'num_attempts': 1}}
|
||||
expected_filter_properties = {'retry': {'num_attempts': 2}}
|
||||
self.mox.StubOutWithMock(sched, '_schedule')
|
||||
self.mox.StubOutWithMock(sched, '_provision_resource')
|
||||
|
||||
sched._schedule(self.context, request_spec,
|
||||
expected_filter_properties).AndReturn(['host1'])
|
||||
sched._provision_resource(
|
||||
self.context, 'host1',
|
||||
request_spec, expected_filter_properties,
|
||||
None, None, None, None,
|
||||
instance_uuid='fake-uuid1',
|
||||
legacy_bdm_in_spec=False)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
sched.schedule_run_instance(self.context, request_spec, None, None,
|
||||
None, None, filter_properties, False)
|
||||
|
||||
def test_retry_exceeded_max_attempts(self):
|
||||
# Test for necessary explosion when max retries is exceeded and that
|
||||
# the information needed in request_spec is still present for error
|
||||
# handling
|
||||
self.flags(scheduler_max_attempts=2)
|
||||
sched = fakes.FakeFilterScheduler()
|
||||
request_spec = dict(instance_properties={},
|
||||
instance_uuids=['fake-uuid1'])
|
||||
filter_properties = {'retry': {'num_attempts': 2}}
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
self.assertRaises(exception.NoValidHost, sched.schedule_run_instance,
|
||||
self.context, request_spec, None, None,
|
||||
None, None, filter_properties, False)
|
||||
|
||||
def test_add_retry_host(self):
|
||||
retry = dict(num_attempts=1, hosts=[])
|
||||
filter_properties = dict(retry=retry)
|
||||
|
@ -569,28 +320,3 @@ class FilterSchedulerTestCase(test_scheduler.SchedulerTestCase):
|
|||
# Make sure that we provided a reason why NoValidHost.
|
||||
self.assertIn('reason', e.kwargs)
|
||||
self.assertTrue(len(e.kwargs['reason']) > 0)
|
||||
|
||||
def test_handles_deleted_instance(self):
|
||||
"""Test instance deletion while being scheduled."""
|
||||
|
||||
def _raise_instance_not_found(*args, **kwargs):
|
||||
raise exception.InstanceNotFound(instance_id='123')
|
||||
|
||||
self.stubs.Set(driver, 'instance_update_db',
|
||||
_raise_instance_not_found)
|
||||
|
||||
sched = fakes.FakeFilterScheduler()
|
||||
|
||||
fake_context = context.RequestContext('user', 'project')
|
||||
host_state = host_manager.HostState('host2', 'node2')
|
||||
weighted_host = weights.WeighedHost(host_state, 1.42)
|
||||
filter_properties = {}
|
||||
|
||||
uuid = 'fake-uuid1'
|
||||
instance_properties = {'project_id': 1, 'os_type': 'Linux'}
|
||||
request_spec = {'instance_type': {'memory_mb': 1, 'local_gb': 1},
|
||||
'instance_properties': instance_properties,
|
||||
'instance_uuids': [uuid]}
|
||||
sched._provision_resource(fake_context, weighted_host,
|
||||
request_spec, filter_properties,
|
||||
None, None, None, None)
|
||||
|
|
|
@ -67,4 +67,4 @@ class SchedulerRpcAPITestCase(test.NoDBTestCase):
|
|||
self._test_scheduler_api('select_destinations', rpc_method='call',
|
||||
request_spec='fake_request_spec',
|
||||
filter_properties='fake_prop',
|
||||
version='3.1')
|
||||
version='4.0')
|
||||
|
|
|
@ -17,23 +17,20 @@
|
|||
Tests For Scheduler
|
||||
"""
|
||||
|
||||
import mock
|
||||
from mox3 import mox
|
||||
from oslo.config import cfg
|
||||
|
||||
from nova.compute import api as compute_api
|
||||
from nova.compute import utils as compute_utils
|
||||
from nova.compute import vm_states
|
||||
from nova import context
|
||||
from nova import db
|
||||
from nova import exception
|
||||
from nova.image import glance
|
||||
from nova import objects
|
||||
from nova import rpc
|
||||
from nova.scheduler import driver
|
||||
from nova.scheduler import manager
|
||||
from nova import servicegroup
|
||||
from nova import test
|
||||
from nova.tests.unit import fake_instance
|
||||
from nova.tests.unit import fake_server_actions
|
||||
from nova.tests.unit.image import fake as fake_image
|
||||
from nova.tests.unit.objects import test_instance_fault
|
||||
|
@ -75,199 +72,24 @@ class SchedulerManagerTestCase(test.NoDBTestCase):
|
|||
self.mox.StubOutWithMock(self.manager.driver,
|
||||
method_name)
|
||||
|
||||
def test_run_instance_exception_puts_instance_in_error_state(self):
|
||||
fake_instance_uuid = 'fake-instance-id'
|
||||
inst = {"vm_state": "", "task_state": ""}
|
||||
def test_select_destination(self):
|
||||
with mock.patch.object(self.manager, 'select_destinations'
|
||||
) as select_destinations:
|
||||
self.manager.select_destinations(None, None, {})
|
||||
select_destinations.assert_called_once_with(None, None, {})
|
||||
|
||||
self._mox_schedule_method_helper('schedule_run_instance')
|
||||
self.mox.StubOutWithMock(compute_utils, 'add_instance_fault_from_exc')
|
||||
self.mox.StubOutWithMock(db, 'instance_update_and_get_original')
|
||||
|
||||
request_spec = {'instance_properties': inst,
|
||||
'instance_uuids': [fake_instance_uuid]}
|
||||
class SchedulerV3PassthroughTestCase(test.TestCase):
|
||||
def setUp(self):
|
||||
super(SchedulerV3PassthroughTestCase, self).setUp()
|
||||
self.manager = manager.SchedulerManager()
|
||||
self.proxy = manager._SchedulerManagerV3Proxy(self.manager)
|
||||
|
||||
self.manager.driver.schedule_run_instance(self.context,
|
||||
request_spec, None, None, None, None, {}, False).AndRaise(
|
||||
exception.NoValidHost(reason=""))
|
||||
old, new_ref = db.instance_update_and_get_original(self.context,
|
||||
fake_instance_uuid,
|
||||
{"vm_state": vm_states.ERROR,
|
||||
"task_state": None}).AndReturn((inst, inst))
|
||||
compute_utils.add_instance_fault_from_exc(self.context,
|
||||
new_ref, mox.IsA(exception.NoValidHost), mox.IgnoreArg())
|
||||
|
||||
self.mox.ReplayAll()
|
||||
self.manager.run_instance(self.context, request_spec,
|
||||
None, None, None, None, {}, False)
|
||||
|
||||
def test_prep_resize_no_valid_host_back_in_active_state(self):
|
||||
fake_instance_uuid = 'fake-instance-id'
|
||||
fake_instance = {'uuid': fake_instance_uuid}
|
||||
inst = {"vm_state": "", "task_state": ""}
|
||||
|
||||
self._mox_schedule_method_helper('select_destinations')
|
||||
|
||||
self.mox.StubOutWithMock(compute_utils, 'add_instance_fault_from_exc')
|
||||
self.mox.StubOutWithMock(db, 'instance_update_and_get_original')
|
||||
|
||||
request_spec = {'instance_type': 'fake_type',
|
||||
'instance_uuids': [fake_instance_uuid],
|
||||
'instance_properties': {'uuid': fake_instance_uuid}}
|
||||
kwargs = {
|
||||
'context': self.context,
|
||||
'image': 'fake_image',
|
||||
'request_spec': request_spec,
|
||||
'filter_properties': 'fake_props',
|
||||
'instance': fake_instance,
|
||||
'instance_type': 'fake_type',
|
||||
'reservations': list('fake_res'),
|
||||
}
|
||||
self.manager.driver.select_destinations(
|
||||
self.context, request_spec, 'fake_props').AndRaise(
|
||||
exception.NoValidHost(reason=""))
|
||||
old_ref, new_ref = db.instance_update_and_get_original(self.context,
|
||||
fake_instance_uuid,
|
||||
{"vm_state": vm_states.ACTIVE, "task_state": None}).AndReturn(
|
||||
(inst, inst))
|
||||
compute_utils.add_instance_fault_from_exc(self.context, new_ref,
|
||||
mox.IsA(exception.NoValidHost), mox.IgnoreArg())
|
||||
|
||||
self.mox.ReplayAll()
|
||||
self.manager.prep_resize(**kwargs)
|
||||
|
||||
def test_prep_resize_no_valid_host_back_in_shutoff_state(self):
|
||||
fake_instance_uuid = 'fake-instance-id'
|
||||
fake_instance = {'uuid': fake_instance_uuid, "vm_state": "stopped"}
|
||||
inst = {"vm_state": "stopped", "task_state": ""}
|
||||
|
||||
self._mox_schedule_method_helper('select_destinations')
|
||||
|
||||
self.mox.StubOutWithMock(compute_utils, 'add_instance_fault_from_exc')
|
||||
self.mox.StubOutWithMock(db, 'instance_update_and_get_original')
|
||||
|
||||
request_spec = {'instance_type': 'fake_type',
|
||||
'instance_uuids': [fake_instance_uuid],
|
||||
'instance_properties': {'uuid': fake_instance_uuid}}
|
||||
kwargs = {
|
||||
'context': self.context,
|
||||
'image': 'fake_image',
|
||||
'request_spec': request_spec,
|
||||
'filter_properties': 'fake_props',
|
||||
'instance': fake_instance,
|
||||
'instance_type': 'fake_type',
|
||||
'reservations': list('fake_res'),
|
||||
}
|
||||
self.manager.driver.select_destinations(
|
||||
self.context, request_spec, 'fake_props').AndRaise(
|
||||
exception.NoValidHost(reason=""))
|
||||
old_ref, new_ref = db.instance_update_and_get_original(self.context,
|
||||
fake_instance_uuid,
|
||||
{"vm_state": vm_states.STOPPED, "task_state": None}).AndReturn(
|
||||
(inst, inst))
|
||||
compute_utils.add_instance_fault_from_exc(self.context, new_ref,
|
||||
mox.IsA(exception.NoValidHost), mox.IgnoreArg())
|
||||
|
||||
self.mox.ReplayAll()
|
||||
self.manager.prep_resize(**kwargs)
|
||||
|
||||
def test_prep_resize_exception_host_in_error_state_and_raise(self):
|
||||
fake_instance_uuid = 'fake-instance-id'
|
||||
fake_instance = {'uuid': fake_instance_uuid}
|
||||
|
||||
self._mox_schedule_method_helper('select_destinations')
|
||||
|
||||
self.mox.StubOutWithMock(compute_utils, 'add_instance_fault_from_exc')
|
||||
self.mox.StubOutWithMock(db, 'instance_update_and_get_original')
|
||||
|
||||
request_spec = {
|
||||
'instance_properties': {'uuid': fake_instance_uuid},
|
||||
'instance_uuids': [fake_instance_uuid]
|
||||
}
|
||||
kwargs = {
|
||||
'context': self.context,
|
||||
'image': 'fake_image',
|
||||
'request_spec': request_spec,
|
||||
'filter_properties': 'fake_props',
|
||||
'instance': fake_instance,
|
||||
'instance_type': 'fake_type',
|
||||
'reservations': list('fake_res'),
|
||||
}
|
||||
|
||||
self.manager.driver.select_destinations(
|
||||
self.context, request_spec, 'fake_props').AndRaise(
|
||||
test.TestingException('something happened'))
|
||||
|
||||
inst = {
|
||||
"vm_state": "",
|
||||
"task_state": "",
|
||||
}
|
||||
old_ref, new_ref = db.instance_update_and_get_original(self.context,
|
||||
fake_instance_uuid,
|
||||
{"vm_state": vm_states.ERROR,
|
||||
"task_state": None}).AndReturn((inst, inst))
|
||||
compute_utils.add_instance_fault_from_exc(self.context, new_ref,
|
||||
mox.IsA(test.TestingException), mox.IgnoreArg())
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
self.assertRaises(test.TestingException, self.manager.prep_resize,
|
||||
**kwargs)
|
||||
|
||||
def test_set_vm_state_and_notify_adds_instance_fault(self):
|
||||
request = {'instance_properties': {'uuid': 'fake-uuid'}}
|
||||
updates = {'vm_state': 'foo'}
|
||||
fake_inst = {'uuid': 'fake-uuid'}
|
||||
|
||||
self.mox.StubOutWithMock(db, 'instance_update_and_get_original')
|
||||
self.mox.StubOutWithMock(db, 'instance_fault_create')
|
||||
self.mox.StubOutWithMock(rpc, 'get_notifier')
|
||||
notifier = self.mox.CreateMockAnything()
|
||||
rpc.get_notifier('scheduler').AndReturn(notifier)
|
||||
db.instance_update_and_get_original(self.context, 'fake-uuid',
|
||||
updates).AndReturn((None,
|
||||
fake_inst))
|
||||
db.instance_fault_create(self.context, mox.IgnoreArg()).AndReturn(
|
||||
test_instance_fault.fake_faults['fake-uuid'][0])
|
||||
notifier.error(self.context, 'scheduler.foo', mox.IgnoreArg())
|
||||
self.mox.ReplayAll()
|
||||
|
||||
self.manager._set_vm_state_and_notify('foo', {'vm_state': 'foo'},
|
||||
self.context, None, request)
|
||||
|
||||
def test_prep_resize_post_populates_retry(self):
|
||||
self.manager.driver = fakes.FakeFilterScheduler()
|
||||
|
||||
image = 'image'
|
||||
instance_uuid = 'fake-instance-id'
|
||||
instance = fake_instance.fake_db_instance(uuid=instance_uuid)
|
||||
|
||||
instance_properties = {'project_id': 'fake', 'os_type': 'Linux'}
|
||||
instance_type = "m1.tiny"
|
||||
request_spec = {'instance_properties': instance_properties,
|
||||
'instance_type': instance_type,
|
||||
'instance_uuids': [instance_uuid]}
|
||||
retry = {'hosts': [], 'num_attempts': 1}
|
||||
filter_properties = {'retry': retry}
|
||||
reservations = None
|
||||
|
||||
hosts = [dict(host='host', nodename='node', limits={})]
|
||||
|
||||
self._mox_schedule_method_helper('select_destinations')
|
||||
self.manager.driver.select_destinations(
|
||||
self.context, request_spec, filter_properties).AndReturn(hosts)
|
||||
|
||||
self.mox.StubOutWithMock(self.manager.compute_rpcapi, 'prep_resize')
|
||||
self.manager.compute_rpcapi.prep_resize(self.context, image,
|
||||
mox.IsA(objects.Instance),
|
||||
instance_type, 'host', reservations, request_spec=request_spec,
|
||||
filter_properties=filter_properties, node='node')
|
||||
|
||||
self.mox.ReplayAll()
|
||||
self.manager.prep_resize(self.context, image, request_spec,
|
||||
filter_properties, instance, instance_type, reservations)
|
||||
|
||||
self.assertEqual([['host', 'node']],
|
||||
filter_properties['retry']['hosts'])
|
||||
def test_select_destination(self):
|
||||
with mock.patch.object(self.manager, 'select_destinations'
|
||||
) as select_destinations:
|
||||
self.proxy.select_destinations(None, None, {})
|
||||
select_destinations.assert_called_once_with(None, None, {})
|
||||
|
||||
|
||||
class SchedulerTestCase(test.NoDBTestCase):
|
||||
|
@ -342,15 +164,6 @@ class SchedulerDriverBaseTestCase(SchedulerTestCase):
|
|||
that will fail if the driver is changed.
|
||||
"""
|
||||
|
||||
def test_unimplemented_schedule_run_instance(self):
|
||||
fake_request_spec = {'instance_properties':
|
||||
{'uuid': 'uuid'}}
|
||||
|
||||
self.assertRaises(NotImplementedError,
|
||||
self.driver.schedule_run_instance,
|
||||
self.context, fake_request_spec, None, None, None,
|
||||
None, None, False)
|
||||
|
||||
def test_unimplemented_select_destinations(self):
|
||||
self.assertRaises(NotImplementedError,
|
||||
self.driver.select_destinations, self.context, {}, {})
|
||||
|
|
Loading…
Reference in New Issue