]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Add version to scheduler rpc API.
authorRussell Bryant <rbryant@redhat.com>
Wed, 16 May 2012 20:40:05 +0000 (16:40 -0400)
committerMark McLoughlin <markmc@redhat.com>
Thu, 19 Jul 2012 16:20:18 +0000 (17:20 +0100)
Part of blueprint versioned-rpc-apis.

One side effect of this change was that cinder.scheduler.api was removed
in favor of cinder.scheduler.rpcapi.  In this case, the api was just a
direct wrapper around rpc usage.  For other APIs, I've been following
the pattern that the rpcapi module provides the rpc client wrapper, and
if any other client-side logic is needed, that's where an api module is
used.

Change-Id: Ibd0292936f9afc77aeb5d040660bfa857861eed1

cinder/manager.py
cinder/scheduler/api.py [deleted file]
cinder/scheduler/manager.py
cinder/scheduler/rpcapi.py [new file with mode: 0644]
cinder/tests/scheduler/test_rpcapi.py [new file with mode: 0644]
cinder/tests/test_quota.py

index bd2e2423e8cccd8eec95d9ed8108f2feeb71c476..b7f2a0bde48331bf1882d48468699fb193fa3e93 100644 (file)
@@ -57,7 +57,7 @@ from cinder.db import base
 from cinder import flags
 from cinder import log as logging
 from cinder.rpc import dispatcher as rpc_dispatcher
-from cinder.scheduler import api
+from cinder.scheduler import rpcapi as scheduler_rpcapi
 from cinder import version
 
 
@@ -202,6 +202,7 @@ class SchedulerDependentManager(Manager):
     def __init__(self, host=None, db_driver=None, service_name='undefined'):
         self.last_capabilities = None
         self.service_name = service_name
+        self.scheduler_rpcapi = scheduler_rpcapi.SchedulerAPI()
         super(SchedulerDependentManager, self).__init__(host, db_driver)
 
     def update_service_capabilities(self, capabilities):
@@ -213,5 +214,5 @@ class SchedulerDependentManager(Manager):
         """Pass data back to the scheduler at a periodic interval."""
         if self.last_capabilities:
             LOG.debug(_('Notifying Schedulers of capabilities ...'))
-            api.update_service_capabilities(context, self.service_name,
-                                self.host, self.last_capabilities)
+            self.scheduler_rpcapi.update_service_capabilities(context,
+                    self.service_name, self.host, self.last_capabilities)
diff --git a/cinder/scheduler/api.py b/cinder/scheduler/api.py
deleted file mode 100644 (file)
index c7065c5..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-# Copyright (c) 2011 OpenStack, LLC.
-# All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-"""
-Handles all requests relating to schedulers.
-"""
-
-from cinder import flags
-from cinder import log as logging
-from cinder import rpc
-
-FLAGS = flags.FLAGS
-LOG = logging.getLogger(__name__)
-
-
-def _call_scheduler(method, context, params=None):
-    """Generic handler for RPC calls to the scheduler.
-
-    :param params: Optional dictionary of arguments to be passed to the
-                   scheduler worker
-
-    :retval: Result returned by scheduler worker
-    """
-    if not params:
-        params = {}
-    queue = FLAGS.scheduler_topic
-    kwargs = {'method': method, 'args': params}
-    return rpc.call(context, queue, kwargs)
-
-
-def get_host_list(context):
-    """Return a list of hosts associated with this zone."""
-    return _call_scheduler('get_host_list', context)
-
-
-def get_service_capabilities(context):
-    """Return aggregated capabilities for all services."""
-    return _call_scheduler('get_service_capabilities', context)
-
-
-def update_service_capabilities(context, service_name, host, capabilities):
-    """Send an update to all the scheduler services informing them
-       of the capabilities of this service."""
-    kwargs = dict(method='update_service_capabilities',
-                  args=dict(service_name=service_name, host=host,
-                            capabilities=capabilities))
-    return rpc.fanout_cast(context, 'scheduler', kwargs)
-
-
-def live_migration(context, block_migration, disk_over_commit,
-                   instance_id, dest, topic):
-    """Migrate a server to a new host"""
-    params = {"instance_id": instance_id,
-              "dest": dest,
-              "topic": topic,
-              "block_migration": block_migration,
-              "disk_over_commit": disk_over_commit}
-    # NOTE(comstud): Call vs cast so we can get exceptions back, otherwise
-    # this call in the scheduler driver doesn't return anything.
-    _call_scheduler("live_migration", context=context, params=params)
index 35e73db468544fc4e00b1c6db05d7ce798804d55..5b67c407c5c63bb853cc993dfc92779a7a639ce6 100644 (file)
@@ -47,6 +47,8 @@ FLAGS.register_opt(scheduler_driver_opt)
 class SchedulerManager(manager.Manager):
     """Chooses a host to run instances on."""
 
+    RPC_API_VERSION = '1.0'
+
     def __init__(self, scheduler_driver=None, *args, **kwargs):
         if not scheduler_driver:
             scheduler_driver = FLAGS.scheduler_driver
@@ -55,6 +57,9 @@ class SchedulerManager(manager.Manager):
 
     def __getattr__(self, key):
         """Converts all method calls to use the schedule method"""
+        # NOTE(russellb) Because of what this is doing, we must be careful
+        # when changing the API of the scheduler drivers, as that changes
+        # the rpc API as well, and the version should be updated accordingly.
         return functools.partial(self._schedule, key)
 
     def get_host_list(self, context):
diff --git a/cinder/scheduler/rpcapi.py b/cinder/scheduler/rpcapi.py
new file mode 100644 (file)
index 0000000..f899b22
--- /dev/null
@@ -0,0 +1,79 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012, Red Hat, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+"""
+Client side of the scheduler manager RPC API.
+"""
+
+from cinder import flags
+import cinder.rpc.proxy
+
+
+FLAGS = flags.FLAGS
+
+
+class SchedulerAPI(cinder.rpc.proxy.RpcProxy):
+    '''Client side of the scheduler rpc API.
+
+    API version history:
+
+        1.0 - Initial version.
+    '''
+
+    RPC_API_VERSION = '1.0'
+
+    def __init__(self):
+        super(SchedulerAPI, self).__init__(topic=FLAGS.scheduler_topic,
+                default_version=self.RPC_API_VERSION)
+
+    def run_instance(self, ctxt, topic, request_spec, admin_password,
+            injected_files, requested_networks, is_first_time,
+            filter_properties, call=True):
+        rpc_method = self.call if call else self.cast
+        return rpc_method(ctxt, self.make_msg('run_instance', topic=topic,
+                request_spec=request_spec, admin_password=admin_password,
+                injected_files=injected_files,
+                requested_networks=requested_networks,
+                is_first_time=is_first_time,
+                filter_properties=filter_properties))
+
+    def prep_resize(self, ctxt, topic, instance_uuid, instance_type_id, image,
+            update_db, request_spec, filter_properties):
+        self.cast(ctxt, self.make_msg('prep_resize', topic=topic,
+                instance_uuid=instance_uuid, instance_type_id=instance_type_id,
+                image=image, update_db=update_db, request_spec=request_spec,
+                filter_properties=filter_properties))
+
+    def show_host_resources(self, ctxt, host):
+        return self.call(ctxt, self.make_msg('show_host_resources', host=host))
+
+    def live_migration(self, ctxt, block_migration, disk_over_commit,
+            instance_id, dest, topic):
+        # NOTE(comstud): Call vs cast so we can get exceptions back, otherwise
+        # this call in the scheduler driver doesn't return anything.
+        return self.call(ctxt, self.make_msg('live_migration',
+                block_migration=block_migration,
+                disk_over_commit=disk_over_commit, instance_id=instance_id,
+                dest=dest, topic=topic))
+
+    def update_service_capabilities(self, ctxt, service_name, host,
+            capabilities):
+        self.fanout_cast(ctxt, self.make_msg('update_service_capabilities',
+                service_name=service_name, host=host,
+                capabilities=capabilities))
+
+    def get_host_list(self, ctxt):
+        return self.call(ctxt, self.make_msg('get_host_list'))
diff --git a/cinder/tests/scheduler/test_rpcapi.py b/cinder/tests/scheduler/test_rpcapi.py
new file mode 100644 (file)
index 0000000..972060f
--- /dev/null
@@ -0,0 +1,103 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012, Red Hat, Inc.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+"""
+Unit Tests for cinder.scheduler.rpcapi
+"""
+
+from cinder import context
+from cinder import flags
+from cinder import rpc
+from cinder.scheduler import rpcapi as scheduler_rpcapi
+from cinder import test
+
+
+FLAGS = flags.FLAGS
+
+
+class SchedulerRpcAPITestCase(test.TestCase):
+
+    def setUp(self):
+        super(SchedulerRpcAPITestCase, self).setUp()
+
+    def tearDown(self):
+        super(SchedulerRpcAPITestCase, self).tearDown()
+
+    def _test_scheduler_api(self, method, rpc_method, **kwargs):
+        ctxt = context.RequestContext('fake_user', 'fake_project')
+        rpcapi = scheduler_rpcapi.SchedulerAPI()
+        expected_retval = 'foo' if method == 'call' else None
+        expected_msg = rpcapi.make_msg(method, **kwargs)
+        expected_msg['version'] = rpcapi.RPC_API_VERSION
+        if rpc_method == 'cast' and method == 'run_instance':
+            kwargs['call'] = False
+
+        self.fake_args = None
+        self.fake_kwargs = None
+
+        def _fake_rpc_method(*args, **kwargs):
+            self.fake_args = args
+            self.fake_kwargs = kwargs
+            if expected_retval:
+                return expected_retval
+
+        self.stubs.Set(rpc, rpc_method, _fake_rpc_method)
+
+        retval = getattr(rpcapi, method)(ctxt, **kwargs)
+
+        self.assertEqual(retval, expected_retval)
+        expected_args = [ctxt, FLAGS.scheduler_topic, expected_msg]
+        for arg, expected_arg in zip(self.fake_args, expected_args):
+            self.assertEqual(arg, expected_arg)
+
+    def test_run_instance_call(self):
+        self._test_scheduler_api('run_instance', rpc_method='call',
+                topic='fake_topic', request_spec='fake_request_spec',
+                admin_password='pw', injected_files='fake_injected_files',
+                requested_networks='fake_requested_networks',
+                is_first_time=True, filter_properties='fake_filter_properties')
+
+    def test_run_instance_cast(self):
+        self._test_scheduler_api('run_instance', rpc_method='cast',
+                topic='fake_topic', request_spec='fake_request_spec',
+                admin_password='pw', injected_files='fake_injected_files',
+                requested_networks='fake_requested_networks',
+                is_first_time=True, filter_properties='fake_filter_properties')
+
+    def test_prep_resize(self):
+        self._test_scheduler_api('prep_resize', rpc_method='cast',
+                topic='fake_topic', instance_uuid='fake_uuid',
+                instance_type_id='fake_type_id', image='fake_image',
+                update_db='fake_update_db', request_spec='fake_request_spec',
+                filter_properties='fake_props')
+
+    def test_show_host_resources(self):
+        self._test_scheduler_api('show_host_resources', rpc_method='call',
+                host='fake_host')
+
+    def test_live_migration(self):
+        self._test_scheduler_api('live_migration', rpc_method='call',
+                block_migration='fake_block_migration',
+                disk_over_commit='fake_disk_over_commit',
+                instance_id='fake_id', dest='fake_dest', topic='fake_topic')
+
+    def test_update_service_capabilities(self):
+        self._test_scheduler_api('update_service_capabilities',
+                rpc_method='fanout_cast', service_name='fake_name',
+                host='fake_host', capabilities='fake_capabilities')
+
+    def test_get_host_list(self):
+        self._test_scheduler_api('get_host_list', rpc_method='call')
index 6e794d6e4e7c64298885771673b95f5cb8750630..962768e5b329d2095973afc7e2777001a2045218 100644 (file)
@@ -262,7 +262,7 @@ class QuotaTestCase(test.TestCase):
                                               is_admin=True)
         orig_rpc_call = rpc.call
 
-        def rpc_call_wrapper(context, topic, msg):
+        def rpc_call_wrapper(context, topic, msg, timeout=None):
             """Stub out the scheduler creating the instance entry"""
             if (topic == FLAGS.scheduler_topic and
                 msg['method'] == 'run_instance'):