Change RPC to use new BDM format for instance boot
This patch makes rpc calls that are the result of booting an instance propagate the new block device mapping format. The way this is done is by adding a 'legacy_bdm' flag to the conductor (task) API. Since both the scheduler and the compute service propagate the block device mapping as part of the request_spec field, a flag named legacy_bdm_in_spec to indicate that was introduced in their respective APIs. Currently block_device_mapping is not used by any of the in-tree filters in the scheduler, so it is assumed that scheduler's boot functionality has now transitioned to the new format. This patch also bumps RPC versions of the task, scheduler and compute manager classes. Finally this patch propagates the legacy_bdm_in_spec through the run_instance callback of the compute manager so that, in case of error - the instance is re-scheduled with the proper flag set. blueprint: improve-block-device-handling Change-Id: I5f25ddd4d586dda91061f065c1796be726b0ede3
This commit is contained in:
@@ -92,7 +92,7 @@ class ChanceScheduler(driver.Scheduler):
|
|||||||
def schedule_run_instance(self, context, request_spec,
|
def schedule_run_instance(self, context, request_spec,
|
||||||
admin_password, injected_files,
|
admin_password, injected_files,
|
||||||
requested_networks, is_first_time,
|
requested_networks, is_first_time,
|
||||||
filter_properties):
|
filter_properties, legacy_bdm_in_spec):
|
||||||
"""Create and run an instance or instances."""
|
"""Create and run an instance or instances."""
|
||||||
instance_uuids = request_spec.get('instance_uuids')
|
instance_uuids = request_spec.get('instance_uuids')
|
||||||
for num, instance_uuid in enumerate(instance_uuids):
|
for num, instance_uuid in enumerate(instance_uuids):
|
||||||
@@ -109,7 +109,8 @@ class ChanceScheduler(driver.Scheduler):
|
|||||||
admin_password=admin_password,
|
admin_password=admin_password,
|
||||||
is_first_time=is_first_time,
|
is_first_time=is_first_time,
|
||||||
request_spec=request_spec,
|
request_spec=request_spec,
|
||||||
filter_properties=filter_properties)
|
filter_properties=filter_properties,
|
||||||
|
legacy_bdm_in_spec=legacy_bdm_in_spec)
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
# NOTE(vish): we don't reraise the exception here to make sure
|
# NOTE(vish): we don't reraise the exception here to make sure
|
||||||
# that all instances in the request get set to
|
# that all instances in the request get set to
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ class Scheduler(object):
|
|||||||
def schedule_run_instance(self, context, request_spec,
|
def schedule_run_instance(self, context, request_spec,
|
||||||
admin_password, injected_files,
|
admin_password, injected_files,
|
||||||
requested_networks, is_first_time,
|
requested_networks, is_first_time,
|
||||||
filter_properties):
|
filter_properties, legacy_bdm_in_spec):
|
||||||
"""Must override schedule_run_instance method for scheduler to work."""
|
"""Must override schedule_run_instance method for scheduler to work."""
|
||||||
msg = _("Driver must implement schedule_run_instance")
|
msg = _("Driver must implement schedule_run_instance")
|
||||||
raise NotImplementedError(msg)
|
raise NotImplementedError(msg)
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ class FilterScheduler(driver.Scheduler):
|
|||||||
def schedule_run_instance(self, context, request_spec,
|
def schedule_run_instance(self, context, request_spec,
|
||||||
admin_password, injected_files,
|
admin_password, injected_files,
|
||||||
requested_networks, is_first_time,
|
requested_networks, is_first_time,
|
||||||
filter_properties):
|
filter_properties, legacy_bdm_in_spec):
|
||||||
"""This method is called from nova.compute.api to provision
|
"""This method is called from nova.compute.api to provision
|
||||||
an instance. We first create a build plan (a list of WeightedHosts)
|
an instance. We first create a build plan (a list of WeightedHosts)
|
||||||
and then provision.
|
and then provision.
|
||||||
@@ -113,7 +113,8 @@ class FilterScheduler(driver.Scheduler):
|
|||||||
requested_networks,
|
requested_networks,
|
||||||
injected_files, admin_password,
|
injected_files, admin_password,
|
||||||
is_first_time,
|
is_first_time,
|
||||||
instance_uuid=instance_uuid)
|
instance_uuid=instance_uuid,
|
||||||
|
legacy_bdm_in_spec=legacy_bdm_in_spec)
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
# NOTE(vish): we don't reraise the exception here to make sure
|
# NOTE(vish): we don't reraise the exception here to make sure
|
||||||
# that all instances in the request get set to
|
# that all instances in the request get set to
|
||||||
@@ -154,7 +155,8 @@ class FilterScheduler(driver.Scheduler):
|
|||||||
|
|
||||||
def _provision_resource(self, context, weighed_host, request_spec,
|
def _provision_resource(self, context, weighed_host, request_spec,
|
||||||
filter_properties, requested_networks, injected_files,
|
filter_properties, requested_networks, injected_files,
|
||||||
admin_password, is_first_time, instance_uuid=None):
|
admin_password, is_first_time, instance_uuid=None,
|
||||||
|
legacy_bdm_in_spec=True):
|
||||||
"""Create the requested resource in this Zone."""
|
"""Create the requested resource in this Zone."""
|
||||||
# NOTE(vish): add our current instance back into the request spec
|
# NOTE(vish): add our current instance back into the request spec
|
||||||
request_spec['instance_uuids'] = [instance_uuid]
|
request_spec['instance_uuids'] = [instance_uuid]
|
||||||
@@ -194,7 +196,8 @@ class FilterScheduler(driver.Scheduler):
|
|||||||
requested_networks=requested_networks,
|
requested_networks=requested_networks,
|
||||||
injected_files=injected_files,
|
injected_files=injected_files,
|
||||||
admin_password=admin_password, is_first_time=is_first_time,
|
admin_password=admin_password, is_first_time=is_first_time,
|
||||||
node=weighed_host.obj.nodename)
|
node=weighed_host.obj.nodename,
|
||||||
|
legacy_bdm_in_spec=legacy_bdm_in_spec)
|
||||||
|
|
||||||
def _get_configuration_options(self):
|
def _get_configuration_options(self):
|
||||||
"""Fetch options dictionary. Broken out for testing."""
|
"""Fetch options dictionary. Broken out for testing."""
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ QUOTAS = quota.QUOTAS
|
|||||||
class SchedulerManager(manager.Manager):
|
class SchedulerManager(manager.Manager):
|
||||||
"""Chooses a host to run instances on."""
|
"""Chooses a host to run instances on."""
|
||||||
|
|
||||||
RPC_API_VERSION = '2.8'
|
RPC_API_VERSION = '2.9'
|
||||||
|
|
||||||
def __init__(self, scheduler_driver=None, *args, **kwargs):
|
def __init__(self, scheduler_driver=None, *args, **kwargs):
|
||||||
if not scheduler_driver:
|
if not scheduler_driver:
|
||||||
@@ -138,7 +138,7 @@ class SchedulerManager(manager.Manager):
|
|||||||
|
|
||||||
def run_instance(self, context, request_spec, admin_password,
|
def run_instance(self, context, request_spec, admin_password,
|
||||||
injected_files, requested_networks, is_first_time,
|
injected_files, requested_networks, is_first_time,
|
||||||
filter_properties):
|
filter_properties, legacy_bdm_in_spec=True):
|
||||||
"""Tries to call schedule_run_instance on the driver.
|
"""Tries to call schedule_run_instance on the driver.
|
||||||
Sets instance vm_state to ERROR on exceptions
|
Sets instance vm_state to ERROR on exceptions
|
||||||
"""
|
"""
|
||||||
@@ -148,7 +148,8 @@ class SchedulerManager(manager.Manager):
|
|||||||
try:
|
try:
|
||||||
return self.driver.schedule_run_instance(context,
|
return self.driver.schedule_run_instance(context,
|
||||||
request_spec, admin_password, injected_files,
|
request_spec, admin_password, injected_files,
|
||||||
requested_networks, is_first_time, filter_properties)
|
requested_networks, is_first_time, filter_properties,
|
||||||
|
legacy_bdm_in_spec)
|
||||||
|
|
||||||
except exception.NoValidHost as ex:
|
except exception.NoValidHost as ex:
|
||||||
# don't re-raise
|
# don't re-raise
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ class SchedulerAPI(nova.openstack.common.rpc.proxy.RpcProxy):
|
|||||||
|
|
||||||
2.7 - Add select_destinations()
|
2.7 - Add select_destinations()
|
||||||
2.8 - Deprecate prep_resize()
|
2.8 - Deprecate prep_resize()
|
||||||
|
2.9 - Added the leagacy_bdm_in_spec parameter to run_instances
|
||||||
'''
|
'''
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -99,13 +100,14 @@ class SchedulerAPI(nova.openstack.common.rpc.proxy.RpcProxy):
|
|||||||
|
|
||||||
def run_instance(self, ctxt, request_spec, admin_password,
|
def run_instance(self, ctxt, request_spec, admin_password,
|
||||||
injected_files, requested_networks, is_first_time,
|
injected_files, requested_networks, is_first_time,
|
||||||
filter_properties):
|
filter_properties, legacy_bdm_in_spec=True):
|
||||||
return self.cast(ctxt, self.make_msg('run_instance',
|
return self.cast(ctxt, self.make_msg('run_instance',
|
||||||
request_spec=request_spec, admin_password=admin_password,
|
request_spec=request_spec, admin_password=admin_password,
|
||||||
injected_files=injected_files,
|
injected_files=injected_files,
|
||||||
requested_networks=requested_networks,
|
requested_networks=requested_networks,
|
||||||
is_first_time=is_first_time,
|
is_first_time=is_first_time,
|
||||||
filter_properties=filter_properties))
|
filter_properties=filter_properties,
|
||||||
|
legacy_bdm_in_spec=legacy_bdm_in_spec), version='2.9')
|
||||||
|
|
||||||
# NOTE(timello): This method is deprecated and it's functionality has
|
# NOTE(timello): This method is deprecated and it's functionality has
|
||||||
# been moved to conductor. This should be removed in RPC_API_VERSION 3.0.
|
# been moved to conductor. This should be removed in RPC_API_VERSION 3.0.
|
||||||
|
|||||||
@@ -94,7 +94,8 @@ class ChanceSchedulerTestCase(test_scheduler.SchedulerTestCase):
|
|||||||
compute_rpcapi.ComputeAPI.run_instance(ctxt, host='host3',
|
compute_rpcapi.ComputeAPI.run_instance(ctxt, host='host3',
|
||||||
instance=instance1, requested_networks=None,
|
instance=instance1, requested_networks=None,
|
||||||
injected_files=None, admin_password=None, is_first_time=None,
|
injected_files=None, admin_password=None, is_first_time=None,
|
||||||
request_spec=request_spec, filter_properties={})
|
request_spec=request_spec, filter_properties={},
|
||||||
|
legacy_bdm_in_spec=False)
|
||||||
|
|
||||||
# instance 2
|
# instance 2
|
||||||
ctxt.elevated().AndReturn(ctxt_elevated)
|
ctxt.elevated().AndReturn(ctxt_elevated)
|
||||||
@@ -105,11 +106,12 @@ class ChanceSchedulerTestCase(test_scheduler.SchedulerTestCase):
|
|||||||
compute_rpcapi.ComputeAPI.run_instance(ctxt, host='host1',
|
compute_rpcapi.ComputeAPI.run_instance(ctxt, host='host1',
|
||||||
instance=instance2, requested_networks=None,
|
instance=instance2, requested_networks=None,
|
||||||
injected_files=None, admin_password=None, is_first_time=None,
|
injected_files=None, admin_password=None, is_first_time=None,
|
||||||
request_spec=request_spec, filter_properties={})
|
request_spec=request_spec, filter_properties={},
|
||||||
|
legacy_bdm_in_spec=False)
|
||||||
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
self.driver.schedule_run_instance(ctxt, request_spec,
|
self.driver.schedule_run_instance(ctxt, request_spec,
|
||||||
None, None, None, None, {})
|
None, None, None, None, {}, False)
|
||||||
|
|
||||||
def test_basic_schedule_run_instance_no_hosts(self):
|
def test_basic_schedule_run_instance_no_hosts(self):
|
||||||
ctxt = context.RequestContext('fake', 'fake', False)
|
ctxt = context.RequestContext('fake', 'fake', False)
|
||||||
@@ -136,7 +138,7 @@ class ChanceSchedulerTestCase(test_scheduler.SchedulerTestCase):
|
|||||||
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
self.driver.schedule_run_instance(
|
self.driver.schedule_run_instance(
|
||||||
ctxt, request_spec, None, None, None, None, {})
|
ctxt, request_spec, None, None, None, None, {}, False)
|
||||||
|
|
||||||
def test_select_hosts(self):
|
def test_select_hosts(self):
|
||||||
ctxt = context.RequestContext('fake', 'fake', False)
|
ctxt = context.RequestContext('fake', 'fake', False)
|
||||||
|
|||||||
@@ -82,7 +82,8 @@ class FilterSchedulerTestCase(test_scheduler.SchedulerTestCase):
|
|||||||
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
sched.schedule_run_instance(
|
sched.schedule_run_instance(
|
||||||
fake_context, request_spec, None, None, None, None, {})
|
fake_context, request_spec, None, None,
|
||||||
|
None, None, {}, False)
|
||||||
|
|
||||||
def test_run_instance_non_admin(self):
|
def test_run_instance_non_admin(self):
|
||||||
self.was_admin = False
|
self.was_admin = False
|
||||||
@@ -113,7 +114,7 @@ class FilterSchedulerTestCase(test_scheduler.SchedulerTestCase):
|
|||||||
mox.IsA(exception.NoValidHost), mox.IgnoreArg())
|
mox.IsA(exception.NoValidHost), mox.IgnoreArg())
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
sched.schedule_run_instance(
|
sched.schedule_run_instance(
|
||||||
fake_context, request_spec, None, None, None, None, {})
|
fake_context, request_spec, None, None, None, None, {}, False)
|
||||||
self.assertTrue(self.was_admin)
|
self.assertTrue(self.was_admin)
|
||||||
|
|
||||||
def test_scheduler_includes_launch_index(self):
|
def test_scheduler_includes_launch_index(self):
|
||||||
@@ -145,17 +146,19 @@ class FilterSchedulerTestCase(test_scheduler.SchedulerTestCase):
|
|||||||
fake_context, 'host1',
|
fake_context, 'host1',
|
||||||
mox.Func(_has_launch_index(0)), {},
|
mox.Func(_has_launch_index(0)), {},
|
||||||
None, None, None, None,
|
None, None, None, None,
|
||||||
instance_uuid='fake-uuid1').AndReturn(instance1)
|
instance_uuid='fake-uuid1',
|
||||||
|
legacy_bdm_in_spec=False).AndReturn(instance1)
|
||||||
# instance 2
|
# instance 2
|
||||||
self.driver._provision_resource(
|
self.driver._provision_resource(
|
||||||
fake_context, 'host2',
|
fake_context, 'host2',
|
||||||
mox.Func(_has_launch_index(1)), {},
|
mox.Func(_has_launch_index(1)), {},
|
||||||
None, None, None, None,
|
None, None, None, None,
|
||||||
instance_uuid='fake-uuid2').AndReturn(instance2)
|
instance_uuid='fake-uuid2',
|
||||||
|
legacy_bdm_in_spec=False).AndReturn(instance2)
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
self.driver.schedule_run_instance(fake_context, request_spec,
|
self.driver.schedule_run_instance(fake_context, request_spec,
|
||||||
None, None, None, None, {})
|
None, None, None, None, {}, False)
|
||||||
|
|
||||||
def test_schedule_happy_day(self):
|
def test_schedule_happy_day(self):
|
||||||
"""Make sure there's nothing glaringly wrong with _schedule()
|
"""Make sure there's nothing glaringly wrong with _schedule()
|
||||||
@@ -285,7 +288,8 @@ class FilterSchedulerTestCase(test_scheduler.SchedulerTestCase):
|
|||||||
self.context, request_spec, admin_password=None,
|
self.context, request_spec, admin_password=None,
|
||||||
injected_files=None, requested_networks=None,
|
injected_files=None, requested_networks=None,
|
||||||
is_first_time=False,
|
is_first_time=False,
|
||||||
filter_properties=filter_properties)
|
filter_properties=filter_properties,
|
||||||
|
legacy_bdm_in_spec=False)
|
||||||
uuids = request_spec.get('instance_uuids')
|
uuids = request_spec.get('instance_uuids')
|
||||||
self.assertEqual(uuids, instance_uuids)
|
self.assertEqual(uuids, instance_uuids)
|
||||||
|
|
||||||
@@ -368,7 +372,7 @@ class FilterSchedulerTestCase(test_scheduler.SchedulerTestCase):
|
|||||||
instance=instance1_1, requested_networks=None,
|
instance=instance1_1, requested_networks=None,
|
||||||
injected_files=None, admin_password=None, is_first_time=None,
|
injected_files=None, admin_password=None, is_first_time=None,
|
||||||
request_spec=request_spec1, filter_properties=mox.IgnoreArg(),
|
request_spec=request_spec1, filter_properties=mox.IgnoreArg(),
|
||||||
node='node3')
|
node='node3', legacy_bdm_in_spec=False)
|
||||||
|
|
||||||
driver.instance_update_db(fake_context, instance1_2['uuid'],
|
driver.instance_update_db(fake_context, instance1_2['uuid'],
|
||||||
extra_values=expected_metadata).WithSideEffects(
|
extra_values=expected_metadata).WithSideEffects(
|
||||||
@@ -377,10 +381,10 @@ class FilterSchedulerTestCase(test_scheduler.SchedulerTestCase):
|
|||||||
instance=instance1_2, requested_networks=None,
|
instance=instance1_2, requested_networks=None,
|
||||||
injected_files=None, admin_password=None, is_first_time=None,
|
injected_files=None, admin_password=None, is_first_time=None,
|
||||||
request_spec=request_spec1, filter_properties=mox.IgnoreArg(),
|
request_spec=request_spec1, filter_properties=mox.IgnoreArg(),
|
||||||
node='node4')
|
node='node4', legacy_bdm_in_spec=False)
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
sched.schedule_run_instance(fake_context, request_spec1,
|
sched.schedule_run_instance(fake_context, request_spec1,
|
||||||
None, None, None, None, filter_properties)
|
None, None, None, None, filter_properties, False)
|
||||||
|
|
||||||
def test_schedule_host_pool(self):
|
def test_schedule_host_pool(self):
|
||||||
"""Make sure the scheduler_host_subset_size property works properly."""
|
"""Make sure the scheduler_host_subset_size property works properly."""
|
||||||
|
|||||||
@@ -60,7 +60,8 @@ class SchedulerRpcAPITestCase(test.NoDBTestCase):
|
|||||||
request_spec='fake_request_spec',
|
request_spec='fake_request_spec',
|
||||||
admin_password='pw', injected_files='fake_injected_files',
|
admin_password='pw', injected_files='fake_injected_files',
|
||||||
requested_networks='fake_requested_networks',
|
requested_networks='fake_requested_networks',
|
||||||
is_first_time=True, filter_properties='fake_filter_properties')
|
is_first_time=True, filter_properties='fake_filter_properties',
|
||||||
|
legacy_bdm_in_spec=False, version='2.9')
|
||||||
|
|
||||||
def test_prep_resize(self):
|
def test_prep_resize(self):
|
||||||
self._test_scheduler_api('prep_resize', rpc_method='cast',
|
self._test_scheduler_api('prep_resize', rpc_method='cast',
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ class SchedulerManagerTestCase(test.NoDBTestCase):
|
|||||||
'instance_uuids': [fake_instance_uuid]}
|
'instance_uuids': [fake_instance_uuid]}
|
||||||
|
|
||||||
self.manager.driver.schedule_run_instance(self.context,
|
self.manager.driver.schedule_run_instance(self.context,
|
||||||
request_spec, None, None, None, None, {}).AndRaise(
|
request_spec, None, None, None, None, {}, False).AndRaise(
|
||||||
exception.NoValidHost(reason=""))
|
exception.NoValidHost(reason=""))
|
||||||
old, new_ref = db.instance_update_and_get_original(self.context,
|
old, new_ref = db.instance_update_and_get_original(self.context,
|
||||||
fake_instance_uuid,
|
fake_instance_uuid,
|
||||||
@@ -204,7 +204,7 @@ class SchedulerManagerTestCase(test.NoDBTestCase):
|
|||||||
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
self.manager.run_instance(self.context, request_spec,
|
self.manager.run_instance(self.context, request_spec,
|
||||||
None, None, None, None, {})
|
None, None, None, None, {}, False)
|
||||||
|
|
||||||
def test_live_migration_schedule_novalidhost(self):
|
def test_live_migration_schedule_novalidhost(self):
|
||||||
inst = {"uuid": "fake-instance-id",
|
inst = {"uuid": "fake-instance-id",
|
||||||
@@ -586,7 +586,7 @@ class SchedulerDriverBaseTestCase(SchedulerTestCase):
|
|||||||
self.assertRaises(NotImplementedError,
|
self.assertRaises(NotImplementedError,
|
||||||
self.driver.schedule_run_instance,
|
self.driver.schedule_run_instance,
|
||||||
self.context, fake_request_spec, None, None, None,
|
self.context, fake_request_spec, None, None, None,
|
||||||
None, None)
|
None, None, False)
|
||||||
|
|
||||||
def test_unimplemented_select_hosts(self):
|
def test_unimplemented_select_hosts(self):
|
||||||
self.assertRaises(NotImplementedError,
|
self.assertRaises(NotImplementedError,
|
||||||
|
|||||||
Reference in New Issue
Block a user