]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Make nova notifier work with sessions
authorJamie Lennox <jamielennox@redhat.com>
Wed, 17 Dec 2014 03:57:35 +0000 (13:57 +1000)
committerJamie Lennox <jamielennox@redhat.com>
Sun, 22 Feb 2015 23:07:03 +0000 (10:07 +1100)
This allows a variety of additional authentication methods and gives us
keystone V3 auth for free.

DocImpact: Deprecates the nova_admin_* config options in favour of
putting nova config options in the [nova] section.

Closes-Bug: #1403686
Change-Id: Ia9941cd3e85f21cbd4db9eb3cef8b200131af9ce

neutron/common/config.py
neutron/notifiers/nova.py

index 080396b7ca1d074811551ac576019c19b56f8b45..696f1c4f913155a8c86f7dc52b36862e0d65937c 100644 (file)
@@ -20,6 +20,8 @@ Routines for configuring Neutron
 import os
 import sys
 
+from keystoneclient import auth
+from keystoneclient import session as ks_session
 from oslo_config import cfg
 from oslo_db import options as db_options
 import oslo_messaging
@@ -96,27 +98,26 @@ core_opts = [
                        "floatingip) changes so nova can update its cache.")),
     cfg.StrOpt('nova_url',
                default='http://127.0.0.1:8774/v2',
-               help=_('URL for connection to nova')),
+               help=_('URL for connection to nova. '
+                      'Deprecated in favour of an auth plugin in [nova].')),
     cfg.StrOpt('nova_admin_username',
-               help=_('Username for connecting to nova in admin context')),
+               help=_('Username for connecting to nova in admin context. '
+                      'Deprecated in favour of an auth plugin in [nova].')),
     cfg.StrOpt('nova_admin_password',
-               help=_('Password for connection to nova in admin context'),
+               help=_('Password for connection to nova in admin context. '
+                      'Deprecated in favour of an auth plugin in [nova].'),
                secret=True),
     cfg.StrOpt('nova_admin_tenant_id',
-               help=_('The uuid of the admin nova tenant')),
+               help=_('The uuid of the admin nova tenant. '
+                      'Deprecated in favour of an auth plugin in [nova].')),
     cfg.StrOpt('nova_admin_tenant_name',
-               help=_('The name of the admin nova tenant')),
+               help=_('The name of the admin nova tenant. '
+                      'Deprecated in favour of an auth plugin in [nova].')),
     cfg.StrOpt('nova_admin_auth_url',
                default='http://localhost:5000/v2.0',
                help=_('Authorization URL for connecting to nova in admin '
-                      'context')),
-    cfg.StrOpt('nova_ca_certificates_file',
-               help=_('CA file for novaclient to verify server certificates')),
-    cfg.BoolOpt('nova_api_insecure', default=False,
-                help=_("If True, ignore any SSL validation issues")),
-    cfg.StrOpt('nova_region_name',
-               help=_('Name of nova region to use. Useful if keystone manages'
-                      ' more than one region.')),
+                      'context. '
+                      'Deprecated in favour of an auth plugin in [nova].')),
     cfg.IntOpt('send_events_interval', default=2,
                help=_('Number of seconds between sending events to nova if '
                       'there are any events to send.')),
@@ -143,6 +144,25 @@ db_options.set_defaults(cfg.CONF,
                         sqlite_db='', max_pool_size=10,
                         max_overflow=20, pool_timeout=10)
 
+NOVA_CONF_SECTION = 'nova'
+
+nova_deprecated_opts = {
+    'cafile': [cfg.DeprecatedOpt('nova_ca_certificates_file', 'DEFAULT')],
+    'insecure': [cfg.DeprecatedOpt('nova_api_insecure', 'DEFAULT')],
+}
+ks_session.Session.register_conf_options(cfg.CONF, NOVA_CONF_SECTION,
+                                         deprecated_opts=nova_deprecated_opts)
+auth.register_conf_options(cfg.CONF, NOVA_CONF_SECTION)
+
+nova_opts = [
+    cfg.StrOpt('region_name',
+               deprecated_name='nova_region_name',
+               deprecated_group='DEFAULT',
+               help=_('Name of nova region to use. Useful if keystone manages'
+                      ' more than one region.')),
+]
+cfg.CONF.register_opts(nova_opts, group=NOVA_CONF_SECTION)
+
 
 def init(args, **kwargs):
     cfg.CONF(args=args, project='neutron',
index bf0c3c28d92fd08566a5cdea0cd0391b7aed8284..39b3af78558764f64fc1a7c66c18bcfb996a1e05 100644 (file)
@@ -14,6 +14,9 @@
 #    under the License.
 
 import eventlet
+from keystoneclient import auth as ks_auth
+from keystoneclient.auth.identity import v2 as v2_auth
+from keystoneclient import session as ks_session
 from novaclient import client as nova_client
 from novaclient import exceptions as nova_exceptions
 from oslo_config import cfg
@@ -38,16 +41,57 @@ NEUTRON_NOVA_EVENT_STATUS_MAP = {constants.PORT_STATUS_ACTIVE: 'completed',
 NOVA_API_VERSION = "2"
 
 
+class DefaultAuthPlugin(v2_auth.Password):
+    """A wrapper around standard v2 user/pass to handle bypass url.
+
+    This is only necessary because novaclient doesn't support endpoint_override
+    yet - bug #1403329.
+
+    When this bug is fixed we can pass the endpoint_override to the client
+    instead and remove this class.
+    """
+
+    def __init__(self, **kwargs):
+        self._endpoint_override = kwargs.pop('endpoint_override', None)
+        super(DefaultAuthPlugin, self).__init__(**kwargs)
+
+    def get_endpoint(self, session, **kwargs):
+        if self._endpoint_override:
+            return self._endpoint_override
+
+        return super(DefaultAuthPlugin, self).get_endpoint(session, **kwargs)
+
+
 class Notifier(object):
 
     def __init__(self):
-        # TODO(arosen): we need to cache the endpoints and figure out
-        # how to deal with different regions here....
-        if cfg.CONF.nova_admin_tenant_id:
-            bypass_url = "%s/%s" % (cfg.CONF.nova_url,
-                                    cfg.CONF.nova_admin_tenant_id)
-        else:
-            bypass_url = None
+        # FIXME(jamielennox): A notifier is being created for each Controller
+        # and each Notifier is handling it's own auth. That means that we are
+        # authenticating the exact same thing len(controllers) times. This
+        # should be an easy thing to optimize.
+        auth = ks_auth.load_from_conf_options(cfg.CONF, 'nova')
+        endpoint_override = None
+
+        if not auth:
+            LOG.warning(_LW('Authenticating to nova using nova_admin_* options'
+                            ' is deprecated. This should be done using'
+                            ' an auth plugin, like password'))
+
+            if cfg.CONF.nova_admin_tenant_id:
+                endpoint_override = "%s/%s" % (cfg.CONF.nova_url,
+                                               cfg.CONF.nova_admin_tenant_id)
+
+            auth = DefaultAuthPlugin(
+                auth_url=cfg.CONF.nova_admin_auth_url,
+                username=cfg.CONF.nova_admin_username,
+                password=cfg.CONF.nova_admin_password,
+                tenant_id=cfg.CONF.nova_admin_tenant_id,
+                tenant_name=cfg.CONF.nova_admin_tenant_name,
+                endpoint_override=endpoint_override)
+
+        session = ks_session.Session.load_from_conf_options(cfg.CONF,
+                                                            'nova',
+                                                            auth=auth)
 
         # NOTE(andreykurilin): novaclient.v1_1 was renamed to v2 and there is
         # no way to import the contrib module directly without referencing v2,
@@ -58,15 +102,8 @@ class Notifier(object):
                 ".client", ".contrib.server_external_events"))
 
         self.nclient = novaclient_cls(
-            username=cfg.CONF.nova_admin_username,
-            api_key=cfg.CONF.nova_admin_password,
-            project_id=cfg.CONF.nova_admin_tenant_name,
-            tenant_id=cfg.CONF.nova_admin_tenant_id,
-            auth_url=cfg.CONF.nova_admin_auth_url,
-            cacert=cfg.CONF.nova_ca_certificates_file,
-            insecure=cfg.CONF.nova_api_insecure,
-            bypass_url=bypass_url,
-            region_name=cfg.CONF.nova_region_name,
+            session=session,
+            region_name=cfg.CONF.nova.region_name,
             extensions=[server_external_events])
         self.pending_events = []
         self._waiting_to_send = False