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:
EdLeafe 2015-03-01 18:03:38 +00:00
parent 82cc056fb7
commit b6cd8c7dde
6 changed files with 138 additions and 2 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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):

View File

@ -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)

View File

@ -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')

View File

@ -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):