Make nova notifier work with sessions

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
This commit is contained in:
Jamie Lennox 2014-12-17 13:57:35 +10:00
parent 194afde3a6
commit 13427a4076
2 changed files with 86 additions and 29 deletions

View 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',

View 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