From c08cf464e3a81d48f3017e36c2209800f28c14a7 Mon Sep 17 00:00:00 2001 From: Russell Bryant Date: Mon, 20 May 2013 17:44:02 -0400 Subject: [PATCH] Set up 'compute_task' conductor namespace. This patch sets up a new API to be exposed by the nova-conductor service. The existing methods exposed by conductor are all proxy operations on behalf of compute nodes. For Havana, we have plans to add methods that go the other direction. Operations initiated by the API will be processed by the conductor, which will include telling one or more compute nodes what to do. By putting all operations of this form in their own API, it will keep things a bit more clearly separated. Change-Id: Ifa3d443b9bd7f406a7a3bd837351bc689bf2b6c8 --- nova/conductor/__init__.py | 9 +++++++ nova/conductor/api.py | 15 ++++++++++++ nova/conductor/manager.py | 34 +++++++++++++++++++++++++- nova/conductor/rpcapi.py | 17 +++++++++++++ nova/tests/conductor/test_conductor.py | 6 +++++ 5 files changed, 80 insertions(+), 1 deletion(-) diff --git a/nova/conductor/__init__.py b/nova/conductor/__init__.py index b192ca7a7926..a1e2fad919e3 100644 --- a/nova/conductor/__init__.py +++ b/nova/conductor/__init__.py @@ -24,3 +24,12 @@ def API(*args, **kwargs): else: api = conductor_api.API return api(*args, **kwargs) + + +def ComputeTaskAPI(*args, **kwargs): + use_local = kwargs.pop('use_local', False) + if oslo.config.cfg.CONF.conductor.use_local or use_local: + api = conductor_api.LocalComputeTaskAPI + else: + api = conductor_api.ComputeTaskAPI + return api(*args, **kwargs) diff --git a/nova/conductor/api.py b/nova/conductor/api.py index 6706440f5a6e..63ad11064446 100644 --- a/nova/conductor/api.py +++ b/nova/conductor/api.py @@ -337,6 +337,14 @@ class LocalAPI(object): return self._manager.compute_unrescue(context, instance) +class LocalComputeTaskAPI(object): + def __init__(self): + # TODO(danms): This needs to be something more generic for + # other/future users of this sort of functionality. + self._manager = utils.ExceptionHelper( + manager.ComputeTaskManager()) + + class API(object): """Conductor API that does updates via RPC to the ConductorManager.""" @@ -666,3 +674,10 @@ class API(object): def compute_unrescue(self, context, instance): return self.conductor_rpcapi.compute_unrescue(context, instance) + + +class ComputeTaskAPI(object): + """ComputeTask API that queues up compute tasks for nova-conductor.""" + + def __init__(self): + self.conductor_compute_rpcapi = rpcapi.ComputeTaskAPI() diff --git a/nova/conductor/manager.py b/nova/conductor/manager.py index a45c83b8d1f2..3565e3778042 100644 --- a/nova/conductor/manager.py +++ b/nova/conductor/manager.py @@ -47,7 +47,17 @@ datetime_fields = ['launched_at', 'terminated_at', 'updated_at'] class ConductorManager(manager.Manager): - """Mission: TBD.""" + """Mission: Conduct things. + + The methods in the base API for nova-conductor are various proxy operations + performed on behalf of the nova-compute service running on compute nodes. + Compute nodes are not allowed to directly access the database, so this set + of methods allows them to get specific work done without locally accessing + the database. + + The nova-conductor service also exposes an API in the 'compute_task' + namespace. See the ComputeTaskManager class for details. + """ RPC_API_VERSION = '1.49' @@ -58,8 +68,14 @@ class ConductorManager(manager.Manager): openstack_driver.get_openstack_security_group_driver()) self._network_api = None self._compute_api = None + self.compute_task_mgr = ComputeTaskManager() self.quotas = quota.QUOTAS + def create_rpc_dispatcher(self, *args, **kwargs): + kwargs['additional_apis'] = [self.compute_task_mgr] + return super(ConductorManager, self).create_rpc_dispatcher(*args, + **kwargs) + @property def network_api(self): # NOTE(danms): We need to instantiate our network_api on first use @@ -442,3 +458,19 @@ class ConductorManager(manager.Manager): def compute_unrescue(self, context, instance): self.compute_api.unrescue(context, instance) + + +class ComputeTaskManager(object): + """Namespace for compute methods. + + This class presents an rpc API for nova-conductor under the 'compute_task' + namespace. The methods here are compute operations that are invoked + by the API service. These methods see the operation to completion, which + may involve coordinating activities on multiple compute nodes. + """ + + RPC_API_NAMESPACE = 'compute_task' + RPC_API_VERSION = '1.0' + + def __init__(self): + pass diff --git a/nova/conductor/rpcapi.py b/nova/conductor/rpcapi.py index c9be5dd791a3..cb72089909b4 100644 --- a/nova/conductor/rpcapi.py +++ b/nova/conductor/rpcapi.py @@ -440,3 +440,20 @@ class ConductorAPI(nova.openstack.common.rpc.proxy.RpcProxy): instance_p = jsonutils.to_primitive(instance) msg = self.make_msg('compute_unrescue', instance=instance_p) return self.call(context, msg, version='1.48') + + +class ComputeTaskAPI(nova.openstack.common.rpc.proxy.RpcProxy): + """Client side of the conductor 'compute' namespaced RPC API + + API version history: + + 1.0 - Initial version (empty). + """ + + BASE_RPC_API_VERSION = '1.0' + RPC_API_NAMESPACE = 'compute_task' + + def __init__(self): + super(ComputeTaskAPI, self).__init__( + topic=CONF.conductor.topic, + default_version=self.BASE_RPC_API_VERSION) diff --git a/nova/tests/conductor/test_conductor.py b/nova/tests/conductor/test_conductor.py index 3aebf76af3b8..8195a0bc6660 100644 --- a/nova/tests/conductor/test_conductor.py +++ b/nova/tests/conductor/test_conductor.py @@ -1083,16 +1083,22 @@ class ConductorImportTest(test.TestCase): self.flags(use_local=True, group='conductor') self.assertTrue(isinstance(conductor.API(), conductor_api.LocalAPI)) + self.assertTrue(isinstance(conductor.ComputeTaskAPI(), + conductor_api.LocalComputeTaskAPI)) def test_import_conductor_rpc(self): self.flags(use_local=False, group='conductor') self.assertTrue(isinstance(conductor.API(), conductor_api.API)) + self.assertTrue(isinstance(conductor.ComputeTaskAPI(), + conductor_api.ComputeTaskAPI)) def test_import_conductor_override_to_local(self): self.flags(use_local=False, group='conductor') self.assertTrue(isinstance(conductor.API(use_local=True), conductor_api.LocalAPI)) + self.assertTrue(isinstance(conductor.ComputeTaskAPI(use_local=True), + conductor_api.LocalComputeTaskAPI)) class ConductorPolicyTest(test.TestCase):