Add the RPC calls for instance updates.
The Scheduler needs to receive updates from compute whenever there are changes to any instance so that it can update its view of the instances on each compute node. This adds the required RPC methods for updates (new and resized instances) and deletes, as well as a method for sending sync information to verify that the scheduler and compute views of the instances are the same. Partially-Implements: blueprint isolate-scheduler-db (https://blueprints.launchpad.net/nova/+spec/isolate-scheduler-db) Change-Id: I4c16f3080c1f2ed5ef0b9e50a46b7f4280f09a16
This commit is contained in:
parent
82cc056fb7
commit
b6cd8c7dde
|
@ -59,3 +59,14 @@ class SchedulerClient(object):
|
|||
|
||||
def update_resource_stats(self, context, name, stats):
|
||||
self.reportclient.update_resource_stats(context, name, stats)
|
||||
|
||||
def update_instance_info(self, context, host_name, instance_info):
|
||||
self.queryclient.update_instance_info(context, host_name,
|
||||
instance_info)
|
||||
|
||||
def delete_instance_info(self, context, host_name, instance_uuid):
|
||||
self.queryclient.delete_instance_info(context, host_name,
|
||||
instance_uuid)
|
||||
|
||||
def sync_instance_info(self, context, host_name, instance_uuids):
|
||||
self.queryclient.sync_instance_info(context, host_name, instance_uuids)
|
||||
|
|
|
@ -49,3 +49,39 @@ class SchedulerQueryClient(object):
|
|||
:type aggregate: :class:`nova.objects.Aggregate`
|
||||
"""
|
||||
self.scheduler_rpcapi.delete_aggregate(context, aggregate)
|
||||
|
||||
def update_instance_info(self, context, host_name, instance_info):
|
||||
"""Updates the HostManager with the current information about the
|
||||
instances on a host.
|
||||
|
||||
:param context: local context
|
||||
:param host_name: name of host sending the update
|
||||
:param instance_info: an InstanceList object.
|
||||
"""
|
||||
self.scheduler_rpcapi.update_instance_info(context, host_name,
|
||||
instance_info)
|
||||
|
||||
def delete_instance_info(self, context, host_name, instance_uuid):
|
||||
"""Updates the HostManager with the current information about an
|
||||
instance that has been deleted on a host.
|
||||
|
||||
:param context: local context
|
||||
:param host_name: name of host sending the update
|
||||
:param instance_uuid: the uuid of the deleted instance
|
||||
"""
|
||||
self.scheduler_rpcapi.delete_instance_info(context, host_name,
|
||||
instance_uuid)
|
||||
|
||||
def sync_instance_info(self, context, host_name, instance_uuids):
|
||||
"""Notifies the HostManager of the current instances on a host by
|
||||
sending a list of the uuids for those instances. The HostManager can
|
||||
then compare that with its in-memory view of the instances to detect
|
||||
when they are out of sync.
|
||||
|
||||
:param context: local context
|
||||
:param host_name: name of host sending the update
|
||||
:param instance_uuids: a list of UUID strings representing the current
|
||||
instances on the specified host
|
||||
"""
|
||||
self.scheduler_rpcapi.sync_instance_info(context, host_name,
|
||||
instance_uuids)
|
||||
|
|
|
@ -55,7 +55,7 @@ QUOTAS = quota.QUOTAS
|
|||
class SchedulerManager(manager.Manager):
|
||||
"""Chooses a host to run instances on."""
|
||||
|
||||
target = messaging.Target(version='4.1')
|
||||
target = messaging.Target(version='4.2')
|
||||
|
||||
def __init__(self, scheduler_driver=None, *args, **kwargs):
|
||||
if not scheduler_driver:
|
||||
|
@ -105,6 +105,27 @@ class SchedulerManager(manager.Manager):
|
|||
# NOTE(sbauza): We're dropping the user context now as we don't need it
|
||||
self.driver.host_manager.delete_aggregate(aggregate)
|
||||
|
||||
def update_instance_info(self, context, host_name, instance_info):
|
||||
"""Receives information about changes to a host's instances, and
|
||||
updates the driver's HostManager with that information.
|
||||
"""
|
||||
self.driver.host_manager.update_instance_info(context, host_name,
|
||||
instance_info)
|
||||
|
||||
def delete_instance_info(self, context, host_name, instance_uuid):
|
||||
"""Receives information about the deletion of one of a host's
|
||||
instances, and updates the driver's HostManager with that information.
|
||||
"""
|
||||
self.driver.host_manager.delete_instance_info(context, host_name,
|
||||
instance_uuid)
|
||||
|
||||
def sync_instance_info(self, context, host_name, instance_uuids):
|
||||
"""Receives a sync request from a host, and passes it on to the
|
||||
driver's HostManager.
|
||||
"""
|
||||
self.driver.host_manager.sync_instance_info(context, host_name,
|
||||
instance_uuids)
|
||||
|
||||
|
||||
class _SchedulerManagerV3Proxy(object):
|
||||
|
||||
|
|
|
@ -88,6 +88,8 @@ class SchedulerAPI(object):
|
|||
|
||||
* 4.0 - Removed backwards compat for Icehouse
|
||||
* 4.1 - Add update_aggregates() and delete_aggregate()
|
||||
* 4.2 - Added update_instance_info(), delete_instance_info(), and
|
||||
sync_instance_info() methods
|
||||
|
||||
|
||||
'''
|
||||
|
@ -123,3 +125,18 @@ class SchedulerAPI(object):
|
|||
# NOTE(sbauza): Yes, it's a fanout, we need to update all schedulers
|
||||
cctxt = self.client.prepare(fanout=True, version='4.1')
|
||||
cctxt.cast(ctxt, 'delete_aggregate', aggregate=aggregate)
|
||||
|
||||
def update_instance_info(self, ctxt, host_name, instance_info):
|
||||
cctxt = self.client.prepare(version='4.2', fanout=True)
|
||||
return cctxt.cast(ctxt, 'update_instance_info', host_name=host_name,
|
||||
instance_info=instance_info)
|
||||
|
||||
def delete_instance_info(self, ctxt, host_name, instance_uuid):
|
||||
cctxt = self.client.prepare(version='4.2', fanout=True)
|
||||
return cctxt.cast(ctxt, 'delete_instance_info', host_name=host_name,
|
||||
instance_uuid=instance_uuid)
|
||||
|
||||
def sync_instance_info(self, ctxt, host_name, instance_uuids):
|
||||
cctxt = self.client.prepare(version='4.2', fanout=True)
|
||||
return cctxt.cast(ctxt, 'sync_instance_info', host_name=host_name,
|
||||
instance_uuids=instance_uuids)
|
||||
|
|
|
@ -53,7 +53,7 @@ class SchedulerRpcAPITestCase(test.NoDBTestCase):
|
|||
|
||||
rpc_method = getattr(rpcapi.client, rpc_method)
|
||||
|
||||
rpc_method(ctxt, method, **expected_kwargs).AndReturn('foo')
|
||||
rpc_method(ctxt, method, **expected_kwargs).AndReturn(expected_retval)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
|
@ -80,3 +80,24 @@ class SchedulerRpcAPITestCase(test.NoDBTestCase):
|
|||
aggregate='aggregate',
|
||||
version='4.1',
|
||||
fanout=True)
|
||||
|
||||
def test_update_instance_info(self):
|
||||
self._test_scheduler_api('update_instance_info', rpc_method='cast',
|
||||
host_name='fake_host',
|
||||
instance_info='fake_instance',
|
||||
fanout=True,
|
||||
version='4.2')
|
||||
|
||||
def test_delete_instance_info(self):
|
||||
self._test_scheduler_api('delete_instance_info', rpc_method='cast',
|
||||
host_name='fake_host',
|
||||
instance_uuid='fake_uuid',
|
||||
fanout=True,
|
||||
version='4.2')
|
||||
|
||||
def test_sync_instance_info(self):
|
||||
self._test_scheduler_api('sync_instance_info', rpc_method='cast',
|
||||
host_name='fake_host',
|
||||
instance_uuids=['fake1', 'fake2'],
|
||||
fanout=True,
|
||||
version='4.2')
|
||||
|
|
|
@ -74,6 +74,36 @@ class SchedulerManagerTestCase(test.NoDBTestCase):
|
|||
self.manager.delete_aggregate(None, aggregate='agg')
|
||||
delete_aggregate.assert_called_once_with('agg')
|
||||
|
||||
def test_update_instance_info(self):
|
||||
with mock.patch.object(self.manager.driver.host_manager,
|
||||
'update_instance_info') as mock_update:
|
||||
self.manager.update_instance_info(mock.sentinel.context,
|
||||
mock.sentinel.host_name,
|
||||
mock.sentinel.instance_info)
|
||||
mock_update.assert_called_once_with(mock.sentinel.context,
|
||||
mock.sentinel.host_name,
|
||||
mock.sentinel.instance_info)
|
||||
|
||||
def test_delete_instance_info(self):
|
||||
with mock.patch.object(self.manager.driver.host_manager,
|
||||
'delete_instance_info') as mock_delete:
|
||||
self.manager.delete_instance_info(mock.sentinel.context,
|
||||
mock.sentinel.host_name,
|
||||
mock.sentinel.instance_uuid)
|
||||
mock_delete.assert_called_once_with(mock.sentinel.context,
|
||||
mock.sentinel.host_name,
|
||||
mock.sentinel.instance_uuid)
|
||||
|
||||
def test_sync_instance_info(self):
|
||||
with mock.patch.object(self.manager.driver.host_manager,
|
||||
'sync_instance_info') as mock_sync:
|
||||
self.manager.sync_instance_info(mock.sentinel.context,
|
||||
mock.sentinel.host_name,
|
||||
mock.sentinel.instance_uuids)
|
||||
mock_sync.assert_called_once_with(mock.sentinel.context,
|
||||
mock.sentinel.host_name,
|
||||
mock.sentinel.instance_uuids)
|
||||
|
||||
|
||||
class SchedulerV3PassthroughTestCase(test.TestCase):
|
||||
|
||||
|
|
Loading…
Reference in New Issue