summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell Bryant <rbryant@redhat.com>2012-05-07 14:13:44 -0400
committerRussell Bryant <rbryant@redhat.com>2012-05-17 12:16:12 -0400
commit1b6aa2d1af3d65f381aa9c57cc80531704c0ca8a (patch)
treeb870bc75efcafcc3fcab032f002ce131ce74c2ee
parent8ed3059cb4cb6ff777b59716db32c3133900b393 (diff)
downloadnova-1b6aa2d1af3d65f381aa9c57cc80531704c0ca8a.tar.gz
nova-1b6aa2d1af3d65f381aa9c57cc80531704c0ca8a.tar.xz
nova-1b6aa2d1af3d65f381aa9c57cc80531704c0ca8a.zip
Add version to the cert rpc API.
Part of blueprint versioned-rpc-apis. Change-Id: Iea00a2e82eef7ca7b3ffef438e81e5b4fcca7751
-rw-r--r--nova/api/openstack/compute/contrib/certificates.py13
-rw-r--r--nova/cert/manager.py2
-rw-r--r--nova/cert/rpcapi.py71
-rw-r--r--nova/image/s3.py19
-rw-r--r--nova/tests/cert/__init__.py19
-rw-r--r--nova/tests/cert/test_rpcapi.py93
6 files changed, 200 insertions, 17 deletions
diff --git a/nova/api/openstack/compute/contrib/certificates.py b/nova/api/openstack/compute/contrib/certificates.py
index 601825950..7c33c295e 100644
--- a/nova/api/openstack/compute/contrib/certificates.py
+++ b/nova/api/openstack/compute/contrib/certificates.py
@@ -19,6 +19,7 @@ import webob.exc
from nova.api.openstack import extensions
from nova.api.openstack import wsgi
from nova.api.openstack import xmlutil
+import nova.cert.rpcapi
from nova import flags
from nova import log as logging
from nova import network
@@ -64,6 +65,7 @@ class CertificatesController(object):
def __init__(self):
self.network_api = network.API()
+ self.cert_rpcapi = nova.cert.rpcapi.CertAPI()
super(CertificatesController, self).__init__()
@wsgi.serializers(xml=CertificateTemplate)
@@ -74,9 +76,8 @@ class CertificatesController(object):
if id != 'root':
msg = _("Only root certificate can be retrieved.")
raise webob.exc.HTTPNotImplemented(explanation=msg)
- cert = rpc.call(context, FLAGS.cert_topic,
- {"method": "fetch_ca",
- "args": {"project_id": context.project_id}})
+ cert = self.cert_rpcapi.fetch_ca(context,
+ project_id=context.project_id)
return {'certificate': _translate_certificate_view(cert)}
@wsgi.serializers(xml=CertificateTemplate)
@@ -84,10 +85,8 @@ class CertificatesController(object):
"""Return a list of certificates."""
context = req.environ['nova.context']
authorize(context)
- pk, cert = rpc.call(context, FLAGS.cert_topic,
- {"method": "generate_x509_cert",
- "args": {"user_id": context.user_id,
- "project_id": context.project_id}})
+ pk, cert = self.cert_rpcapi.generate_x509_cert(context,
+ user_id=context.user_id, project_id=context.project_id)
context = req.environ['nova.context']
return {'certificate': _translate_certificate_view(cert, pk)}
diff --git a/nova/cert/manager.py b/nova/cert/manager.py
index b9f35b72d..840a782c5 100644
--- a/nova/cert/manager.py
+++ b/nova/cert/manager.py
@@ -36,6 +36,8 @@ FLAGS = flags.FLAGS
class CertManager(manager.Manager):
+ RPC_API_VERSION = '1.0'
+
def init_host(self):
crypto.ensure_ca_filesystem()
diff --git a/nova/cert/rpcapi.py b/nova/cert/rpcapi.py
new file mode 100644
index 000000000..d062026da
--- /dev/null
+++ b/nova/cert/rpcapi.py
@@ -0,0 +1,71 @@
+# 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 cert manager RPC API.
+"""
+
+from nova import flags
+import nova.rpc.proxy
+
+
+FLAGS = flags.FLAGS
+
+
+class CertAPI(nova.rpc.proxy.RpcProxy):
+ '''Client side of the cert rpc API.
+
+ API version history:
+
+ 1.0 - Initial version.
+ '''
+
+ RPC_API_VERSION = '1.0'
+
+ def __init__(self):
+ super(CertAPI, self).__init__(topic=FLAGS.cert_topic,
+ default_version=self.RPC_API_VERSION)
+
+ def revoke_certs_by_user(self, ctxt, user_id):
+ return self.call(ctxt, self.make_msg('revoke_certs_by_user',
+ user_id=user_id))
+
+ def revoke_certs_by_project(self, ctxt, project_id):
+ return self.call(ctxt, self.make_msg('revoke_certs_by_project',
+ project_id=project_id))
+
+ def revoke_certs_by_user_and_project(self, ctxt, user_id, project_id):
+ return self.call(ctxt,
+ self.make_msg('revoke_certs_by_user_and_project',
+ user_id=user_id, project_id=project_id))
+
+ def generate_x509_cert(self, ctxt, user_id, project_id):
+ return self.call(ctxt, self.make_msg('generate_x509_cert',
+ user_id=user_id,
+ project_id=project_id))
+
+ def fetch_ca(self, ctxt, project_id):
+ return self.call(ctxt, self.make_msg('fetch_ca',
+ project_id=project_id))
+
+ def fetch_crl(self, ctxt, project_id):
+ return self.call(ctxt, self.make_msg('fetch_crl',
+ project_id=project_id))
+
+ def decrypt_text(self, ctxt, project_id, text):
+ return self.call(ctxt, self.make_msg('decrypt_text',
+ project_id=project_id,
+ text=text))
diff --git a/nova/image/s3.py b/nova/image/s3.py
index 31dfa1916..9ed060464 100644
--- a/nova/image/s3.py
+++ b/nova/image/s3.py
@@ -30,6 +30,7 @@ import eventlet
from lxml import etree
from nova.api.ec2 import ec2utils
+import nova.cert.rpcapi
from nova import exception
from nova import flags
from nova import image
@@ -68,6 +69,7 @@ class S3ImageService(object):
"""Wraps an existing image service to support s3 based register."""
def __init__(self, service=None, *args, **kwargs):
+ self.cert_rpcapi = nova.cert.rpcapi.CertAPI()
self.service = service or image.get_default_image_service()
self.service.__init__(*args, **kwargs)
@@ -366,23 +368,20 @@ class S3ImageService(object):
return image
- @staticmethod
- def _decrypt_image(context, encrypted_filename, encrypted_key,
+ def _decrypt_image(self, context, encrypted_filename, encrypted_key,
encrypted_iv, decrypted_filename):
elevated = context.elevated()
try:
- key = rpc.call(elevated, FLAGS.cert_topic,
- {"method": "decrypt_text",
- "args": {"project_id": context.project_id,
- "text": base64.b64encode(encrypted_key)}})
+ key = self.cert_rpcapi.decrypt_text(elevated,
+ project_id=context.project_id,
+ text=base64.b64encode(encrypted_key))
except Exception, exc:
msg = _('Failed to decrypt private key: %s') % exc
raise exception.NovaException(msg)
try:
- iv = rpc.call(elevated, FLAGS.cert_topic,
- {"method": "decrypt_text",
- "args": {"project_id": context.project_id,
- "text": base64.b64encode(encrypted_iv)}})
+ iv = self.cert_rpcapi.decrypt_text(elevated,
+ project_id=context.project_id,
+ text=base64.b64encode(encrypted_iv))
except Exception, exc:
raise exception.NovaException(_('Failed to decrypt initialization '
'vector: %s') % exc)
diff --git a/nova/tests/cert/__init__.py b/nova/tests/cert/__init__.py
new file mode 100644
index 000000000..7e04e7c73
--- /dev/null
+++ b/nova/tests/cert/__init__.py
@@ -0,0 +1,19 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 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.
+
+# NOTE(vish): this forces the fixtures from tests/__init.py:setup() to work
+from nova.tests import *
diff --git a/nova/tests/cert/test_rpcapi.py b/nova/tests/cert/test_rpcapi.py
new file mode 100644
index 000000000..2e3feeaaf
--- /dev/null
+++ b/nova/tests/cert/test_rpcapi.py
@@ -0,0 +1,93 @@
+# 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 nova.cert.rpcapi
+"""
+
+from nova.cert import rpcapi as cert_rpcapi
+from nova import context
+from nova import flags
+from nova import rpc
+from nova import test
+
+
+FLAGS = flags.FLAGS
+
+
+class CertRpcAPITestCase(test.TestCase):
+
+ def setUp(self):
+ super(CertRpcAPITestCase, self).setUp()
+
+ def tearDown(self):
+ super(CertRpcAPITestCase, self).tearDown()
+
+ def _test_cert_api(self, method, **kwargs):
+ ctxt = context.RequestContext('fake_user', 'fake_project')
+ rpcapi = cert_rpcapi.CertAPI()
+ expected_retval = 'foo'
+ expected_msg = rpcapi.make_msg(method, **kwargs)
+ expected_msg['version'] = rpcapi.RPC_API_VERSION
+
+ self.call_ctxt = None
+ self.call_topic = None
+ self.call_msg = None
+ self.call_timeout = None
+
+ def _fake_call(_ctxt, _topic, _msg, _timeout):
+ self.call_ctxt = _ctxt
+ self.call_topic = _topic
+ self.call_msg = _msg
+ self.call_timeout = _timeout
+ return expected_retval
+
+ self.stubs.Set(rpc, 'call', _fake_call)
+
+ retval = getattr(rpcapi, method)(ctxt, **kwargs)
+
+ self.assertEqual(retval, expected_retval)
+ self.assertEqual(self.call_ctxt, ctxt)
+ self.assertEqual(self.call_topic, FLAGS.cert_topic)
+ self.assertEqual(self.call_msg, expected_msg)
+ self.assertEqual(self.call_timeout, None)
+
+ def test_revoke_certs_by_user(self):
+ self._test_cert_api('revoke_certs_by_user', user_id='fake_user_id')
+
+ def test_revoke_certs_by_project(self):
+ self._test_cert_api('revoke_certs_by_project',
+ project_id='fake_project_id')
+
+ def test_revoke_certs_by_user_and_project(self):
+ self._test_cert_api('revoke_certs_by_user_and_project',
+ user_id='fake_user_id',
+ project_id='fake_project_id')
+
+ def test_generate_x509_cert(self):
+ self._test_cert_api('generate_x509_cert',
+ user_id='fake_user_id',
+ project_id='fake_project_id')
+
+ def test_fetch_ca(self):
+ self._test_cert_api('fetch_ca', project_id='fake_project_id')
+
+ def test_fetch_crl(self):
+ self._test_cert_api('fetch_crl', project_id='fake_project_id')
+
+ def test_decrypt_text(self):
+ self._test_cert_api('decrypt_text',
+ project_id='fake_project_id', text='blah')