from cinder.api.openstack import wsgi
from cinder import context
+from cinder.openstack.common import jsonutils
from cinder.openstack.common import log as logging
from cinder import wsgi as base_wsgi
# Build a context, including the auth_token...
remote_address = req.remote_addr
+
+ service_catalog = None
+ if req.headers.get('X_SERVICE_CATALOG') is not None:
+ try:
+ catalog_header = req.headers.get('X_SERVICE_CATALOG')
+ service_catalog = jsonutils.loads(catalog_header)
+ except ValueError:
+ raise webob.exc.HTTPInternalServerError(
+ _('Invalid service catalog json.'))
+
if CONF.use_forwarded_for:
remote_address = req.headers.get('X-Forwarded-For', remote_address)
ctx = context.RequestContext(user_id,
project_name=project_name,
roles=roles,
auth_token=auth_token,
- remote_address=remote_address)
+ remote_address=remote_address,
+ service_catalog=service_catalog)
req.environ['cinder.context'] = ctx
return self.application
+# Copyright 2013 OpenStack Foundation.
+# 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.
+
+import oslo.config.cfg
+
+import cinder.openstack.common.importutils
+
+_compute_opts = [
+ oslo.config.cfg.StrOpt('compute_api_class',
+ default='cinder.compute.nova.API',
+ help='The full class name of the '
+ 'compute API class to use'),
+]
+
+oslo.config.cfg.CONF.register_opts(_compute_opts)
+
+
+def API():
+ importutils = cinder.openstack.common.importutils
+ compute_api_class = oslo.config.cfg.CONF.compute_api_class
+ cls = importutils.import_class(compute_api_class)
+ return cls()
--- /dev/null
+# Copyright 2013 IBM Corp.
+#
+# 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 to Nova.
+"""
+
+
+from novaclient import service_catalog
+from novaclient.v1_1 import client as nova_client
+from oslo.config import cfg
+
+from cinder.db import base
+from cinder.openstack.common import log as logging
+
+nova_opts = [
+ cfg.StrOpt('nova_catalog_info',
+ default='compute:nova:publicURL',
+ help='Info to match when looking for nova in the service '
+ 'catalog. Format is : separated values of the form: '
+ '<service_type>:<service_name>:<endpoint_type>'),
+ cfg.StrOpt('nova_endpoint_template',
+ default=None,
+ help='Override service catalog lookup with template for nova '
+ 'endpoint e.g. http://localhost:8774/v2/%(tenant_id)s'),
+ cfg.StrOpt('os_region_name',
+ default=None,
+ help='region name of this node'),
+ cfg.StrOpt('nova_ca_certificates_file',
+ default=None,
+ help='Location of ca certicates file to use for nova client '
+ 'requests.'),
+ cfg.BoolOpt('nova_api_insecure',
+ default=False,
+ help='Allow to perform insecure SSL requests to nova'),
+]
+
+CONF = cfg.CONF
+CONF.register_opts(nova_opts)
+
+LOG = logging.getLogger(__name__)
+
+
+def novaclient(context):
+
+ # FIXME: the novaclient ServiceCatalog object is mis-named.
+ # It actually contains the entire access blob.
+ # Only needed parts of the service catalog are passed in, see
+ # nova/context.py.
+ compat_catalog = {
+ 'access': {'serviceCatalog': context.service_catalog or []}
+ }
+ sc = service_catalog.ServiceCatalog(compat_catalog)
+ if CONF.nova_endpoint_template:
+ url = CONF.nova_endpoint_template % context.to_dict()
+ else:
+ info = CONF.nova_catalog_info
+ service_type, service_name, endpoint_type = info.split(':')
+ # extract the region if set in configuration
+ if CONF.os_region_name:
+ attr = 'region'
+ filter_value = CONF.os_region_name
+ else:
+ attr = None
+ filter_value = None
+ url = sc.url_for(attr=attr,
+ filter_value=filter_value,
+ service_type=service_type,
+ service_name=service_name,
+ endpoint_type=endpoint_type)
+
+ LOG.debug(_('Novaclient connection created using URL: %s') % url)
+
+ c = nova_client.Client(context.user_id,
+ context.auth_token,
+ context.project_id,
+ auth_url=url,
+ insecure=CONF.nova_api_insecure,
+ cacert=CONF.nova_ca_certificates_file)
+ # noauth extracts user_id:project_id from auth_token
+ c.client.auth_token = context.auth_token or '%s:%s' % (context.user_id,
+ context.project_id)
+ c.client.management_url = url
+ return c
+
+
+class API(base.Base):
+ """API for interacting with novaclient."""
def __init__(self, user_id, project_id, is_admin=None, read_deleted="no",
roles=None, project_name=None, remote_address=None,
timestamp=None, request_id=None, auth_token=None,
- overwrite=True, quota_class=None, **kwargs):
+ overwrite=True, quota_class=None, service_catalog=None,
+ **kwargs):
"""
:param read_deleted: 'no' indicates deleted records are hidden, 'yes'
indicates deleted records are visible, 'only' indicates that
if overwrite or not hasattr(local.store, 'context'):
self.update_store()
+ if service_catalog:
+ # Only include required parts of service_catalog
+ self.service_catalog = [s for s in service_catalog
+ if s.get('type') in ('compute')]
+ else:
+ # if list is empty or none
+ self.service_catalog = []
+
def _get_read_deleted(self):
return self._read_deleted
'request_id': self.request_id,
'auth_token': self.auth_token,
'quota_class': self.quota_class,
+ 'service_catalog': self.service_catalog,
'tenant': self.tenant,
'user': self.user}
--- /dev/null
+# Copyright 2013 IBM Corp.
+#
+# 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.
+
+from cinderclient import exceptions as cinder_exception
+
+from cinder.compute import nova
+from cinder import context
+from cinder import exception
+from cinder import test
+
+
+class FakeNovaClient(object):
+ def __init__(self):
+ pass
+
+
+class NovaApiTestCase(test.TestCase):
+ def setUp(self):
+ super(NovaApiTestCase, self).setUp()
+
+ self.api = nova.API()
+ self.novaclient = FakeNovaClient()
+ self.ctx = context.get_admin_context()
+ self.mox.StubOutWithMock(nova, 'novaclient')