From 64bcb5ce2618505c103fb47871c5d7c7d4cad3f9 Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Mon, 14 Jan 2013 13:32:22 -0500 Subject: [PATCH] Make resource tracker use conductor for listing instances This patch extends the conductor manager's get_all_by_host() method to take an optional node parameter, which will cause the additional filtering, if present. It also makes resource tracker use the conductor for getting instances on the current host/node. Related to blueprint no-db-compute Change-Id: I407757d356b4162f32da29924175175a40f88f13 --- nova/compute/resource_tracker.py | 4 ++-- nova/conductor/api.py | 7 ++++++ nova/conductor/manager.py | 12 ++++++---- nova/conductor/rpcapi.py | 7 +++--- nova/tests/conductor/test_conductor.py | 32 +++++++++++++++++++++++--- 5 files changed, 50 insertions(+), 12 deletions(-) diff --git a/nova/compute/resource_tracker.py b/nova/compute/resource_tracker.py index a02a998b6f78..0559638736ef 100644 --- a/nova/compute/resource_tracker.py +++ b/nova/compute/resource_tracker.py @@ -252,8 +252,8 @@ class ResourceTracker(object): self._report_hypervisor_resource_view(resources) # Grab all instances assigned to this node: - instances = db.instance_get_all_by_host_and_node(context, self.host, - self.nodename) + instances = self.conductor_api.instance_get_all_by_host_and_node( + context, self.host, self.nodename) # Now calculate usage based on instance utilization: self._update_usage_from_instances(resources, instances) diff --git a/nova/conductor/api.py b/nova/conductor/api.py index dbd777ebf487..c805f403cb8d 100644 --- a/nova/conductor/api.py +++ b/nova/conductor/api.py @@ -97,6 +97,9 @@ class LocalAPI(object): def instance_get_all_by_host(self, context, host): return self._manager.instance_get_all_by_host(context, host) + def instance_get_all_by_host_and_node(self, context, host, node): + return self._manager.instance_get_all_by_host(context, host, node) + def instance_get_all_by_filters(self, context, filters, sort_key='created_at', sort_dir='desc'): @@ -335,6 +338,10 @@ class API(object): def instance_get_all_by_host(self, context, host): return self.conductor_rpcapi.instance_get_all_by_host(context, host) + def instance_get_all_by_host_and_node(self, context, host, node): + return self.conductor_rpcapi.instance_get_all_by_host(context, + host, node) + def instance_get_all_by_filters(self, context, filters, sort_key='created_at', sort_dir='desc'): diff --git a/nova/conductor/manager.py b/nova/conductor/manager.py index 0ff60f920861..4a82989eca46 100644 --- a/nova/conductor/manager.py +++ b/nova/conductor/manager.py @@ -43,7 +43,7 @@ datetime_fields = ['launched_at', 'terminated_at'] class ConductorManager(manager.SchedulerDependentManager): """Mission: TBD.""" - RPC_API_VERSION = '1.31' + RPC_API_VERSION = '1.32' def __init__(self, *args, **kwargs): super(ConductorManager, self).__init__(service_name='conductor', @@ -83,9 +83,13 @@ class ConductorManager(manager.SchedulerDependentManager): def instance_get_all(self, context): return jsonutils.to_primitive(self.db.instance_get_all(context)) - def instance_get_all_by_host(self, context, host): - return jsonutils.to_primitive( - self.db.instance_get_all_by_host(context.elevated(), host)) + def instance_get_all_by_host(self, context, host, node=None): + if node is not None: + result = self.db.instance_get_all_by_host_and_node( + context.elevated(), host, node) + else: + result = self.db.instance_get_all_by_host(context.elevated(), host) + return jsonutils.to_primitive(result) @rpc_common.client_exceptions(exception.MigrationNotFound) def migration_get(self, context, migration_id): diff --git a/nova/conductor/rpcapi.py b/nova/conductor/rpcapi.py index a39095ef4ee3..e5f901289f5c 100644 --- a/nova/conductor/rpcapi.py +++ b/nova/conductor/rpcapi.py @@ -64,6 +64,7 @@ class ConductorAPI(nova.openstack.common.rpc.proxy.RpcProxy): 1.29 - Added service_destroy 1.30 - Added migration_create 1.31 - Added migration_get_in_progress_by_host_and_node + 1.32 - Added optional node to instance_get_all_by_host """ BASE_RPC_API_VERSION = '1.0' @@ -278,9 +279,9 @@ class ConductorAPI(nova.openstack.common.rpc.proxy.RpcProxy): msg = self.make_msg('instance_get_all') return self.call(context, msg, version='1.23') - def instance_get_all_by_host(self, context, host): - msg = self.make_msg('instance_get_all_by_host', host=host) - return self.call(context, msg, version='1.23') + def instance_get_all_by_host(self, context, host, node=None): + msg = self.make_msg('instance_get_all_by_host', host=host, node=node) + return self.call(context, msg, version='1.32') def action_event_start(self, context, values): msg = self.make_msg('action_event_start', values=values) diff --git a/nova/tests/conductor/test_conductor.py b/nova/tests/conductor/test_conductor.py index 5fc4caaea2af..9f694060724d 100644 --- a/nova/tests/conductor/test_conductor.py +++ b/nova/tests/conductor/test_conductor.py @@ -461,8 +461,23 @@ class ConductorTestCase(_BaseTestCase, test.TestCase): self.conductor.instance_get_all_by_filters(self.context, filters, 'fake-key', 'fake-sort') + def test_instance_get_all_by_host(self): + self.mox.StubOutWithMock(db, 'instance_get_all_by_host') + self.mox.StubOutWithMock(db, 'instance_get_all_by_host_and_node') + db.instance_get_all_by_host(self.context.elevated(), + 'host').AndReturn('result') + db.instance_get_all_by_host_and_node(self.context.elevated(), 'host', + 'node').AndReturn('result') + self.mox.ReplayAll() + result = self.conductor.instance_get_all_by_host(self.context, 'host') + self.assertEqual(result, 'result') + result = self.conductor.instance_get_all_by_host(self.context, 'host', + 'node') + self.assertEqual(result, 'result') + def _test_stubbed(self, name, dbargs, condargs, db_result_listified=False): + self.mox.StubOutWithMock(db, name) getattr(db, name)(self.context, *dbargs).AndReturn('fake-result') self.mox.ReplayAll() @@ -665,19 +680,22 @@ class ConductorAPITestCase(_BaseTestCase, test.TestCase): def test_instance_get_all(self): self.mox.StubOutWithMock(db, 'instance_get_all_by_filters') db.instance_get_all(self.context) - db.instance_get_all_by_host(self.context.elevated(), 'fake-host') db.instance_get_all_by_filters(self.context, {'name': 'fake-inst'}, 'updated_at', 'asc') self.mox.ReplayAll() self.conductor.instance_get_all(self.context) - self.conductor.instance_get_all_by_host(self.context, 'fake-host') self.conductor.instance_get_all_by_filters(self.context, {'name': 'fake-inst'}, 'updated_at', 'asc') def _test_stubbed(self, name, *args, **kwargs): + if args and isinstance(args[0], FakeContext): + ctxt = args[0] + args = args[1:] + else: + ctxt = self.context self.mox.StubOutWithMock(db, name) - getattr(db, name)(self.context, *args).AndReturn('fake-result') + getattr(db, name)(ctxt, *args).AndReturn('fake-result') if name == 'service_destroy': # TODO(russellb) This is a hack ... SetUp() starts the conductor() # service. There is a cleanup step that runs after this test which @@ -710,6 +728,14 @@ class ConductorAPITestCase(_BaseTestCase, test.TestCase): def test_service_destroy(self): self._test_stubbed('service_destroy', '', returns=False) + def test_instance_get_all_by_host(self): + self._test_stubbed('instance_get_all_by_host', + self.context.elevated(), 'host') + + def test_instance_get_all_by_host_and_node(self): + self._test_stubbed('instance_get_all_by_host_and_node', + self.context.elevated(), 'host', 'node') + def test_ping(self): timeouts = [] calls = dict(count=0)