From 6cde77ebbab85bc8ccd2ab7ad977b1d4af4a13fa Mon Sep 17 00:00:00 2001 From: Eric Fried Date: Thu, 5 Oct 2017 15:00:08 -0500 Subject: [PATCH] Use ksa adapter for neutron client nova.network.neutronv2.api.get_client now uses the common get_ksa_adapter utility to create an Adapter from common keystoneauth1 configuration options if the legacy [neutron] config option ``url`` is not specified. As part of blueprint use-ksa-adapter-for-endpoints, this provides a consistent mechanism for endpoint communication from Nova. Change-Id: I41724a612a5f3eabd504f3eaa9d2f9d141ca3f69 Partial-Implements: bp use-ksa-adapter-for-endpoints --- nova/conf/neutron.py | 36 ++++++++++-------- nova/network/neutronv2/api.py | 37 +++++++++++++++---- nova/tests/unit/network/test_neutronv2.py | 35 +++++++++++++++++- .../neutron-via-ksa-9f386b09cff98a9e.yaml | 15 ++++++++ 4 files changed, 98 insertions(+), 25 deletions(-) create mode 100644 releasenotes/notes/neutron-via-ksa-9f386b09cff98a9e.yaml diff --git a/nova/conf/neutron.py b/nova/conf/neutron.py index 46a73ca74fc8..48cadc77cea9 100644 --- a/nova/conf/neutron.py +++ b/nova/conf/neutron.py @@ -16,6 +16,10 @@ from keystoneauth1 import loading as ks_loading from oslo_config import cfg +from nova.conf import utils as confutils + + +DEFAULT_SERVICE_TYPE = 'network' NEUTRON_GROUP = 'neutron' neutron_group = cfg.OptGroup( @@ -27,7 +31,15 @@ Configuration options for neutron (network connectivity as a service). neutron_opts = [ cfg.URIOpt('url', - default='http://127.0.0.1:9696', + sample_default='http://127.0.0.1:9696', + deprecated_for_removal=True, + deprecated_since='17.0.0', + deprecated_reason='Endpoint lookup uses the service catalog via ' + 'common keystoneauth1 Adapter configuration ' + 'options. In the current release, "url" will ' + 'override this behavior, but will be ignored and/or ' + 'removed in a future release. To achieve the same ' + 'result, use the endpoint_override option instead.', help=""" This option specifies the URL for connecting to Neutron. @@ -36,18 +48,6 @@ Possible values: * Any valid URL that points to the Neutron API service is appropriate here. This typically matches the URL returned for the 'network' service type from the Keystone service catalog. -"""), - cfg.StrOpt('region_name', - default='RegionOne', - help=""" -Region name for connecting to Neutron in admin context. - -This option is used in multi-region setups. If there are two Neutron -servers running in two regions in two different machines, then two -services need to be created in Keystone with two different regions and -associate corresponding endpoints to those services. When requests are made -to Keystone, the Keystone service uses the region_name to determine the -region the request is coming from. """), cfg.StrOpt('ovs_bridge', default='br-int', @@ -111,8 +111,11 @@ ALL_OPTS = (neutron_opts + metadata_proxy_opts) def register_opts(conf): conf.register_group(neutron_group) conf.register_opts(ALL_OPTS, group=neutron_group) - ks_loading.register_session_conf_options(conf, NEUTRON_GROUP) - ks_loading.register_auth_conf_options(conf, NEUTRON_GROUP) + # NOTE(efried): We don't pass `url` as a deprecated opt because that would + # make CONF.neutron.url indistinguishable from + # CONF.neutron.endpoint_override in the code, and we need to be able to use + # the former to trigger the legacy behavior. + confutils.register_ksa_opts(conf, neutron_group, DEFAULT_SERVICE_TYPE) def list_opts(): @@ -123,5 +126,6 @@ def list_opts(): ks_loading.get_auth_common_conf_options() + ks_loading.get_auth_plugin_conf_options('password') + ks_loading.get_auth_plugin_conf_options('v2password') + - ks_loading.get_auth_plugin_conf_options('v3password')) + ks_loading.get_auth_plugin_conf_options('v3password') + + confutils.get_ksa_adapter_opts(DEFAULT_SERVICE_TYPE)) } diff --git a/nova/network/neutronv2/api.py b/nova/network/neutronv2/api.py index 454ca7fa59c4..3e1f2bd1b3f4 100644 --- a/nova/network/neutronv2/api.py +++ b/nova/network/neutronv2/api.py @@ -41,6 +41,7 @@ from nova.pci import whitelist as pci_whitelist from nova.policies import servers as servers_policies from nova import profiler from nova import service_auth +from nova import utils CONF = nova.conf.CONF @@ -159,13 +160,35 @@ def get_client(context, admin=False): # an admin token so log an error raise exception.Unauthorized() - return ClientWrapper( - clientv20.Client(session=_SESSION, - auth=auth_plugin, - endpoint_override=CONF.neutron.url, - region_name=CONF.neutron.region_name, - global_request_id=context.global_id), - admin=admin or context.is_admin) + client_args = dict(session=_SESSION, + auth=auth_plugin, + global_request_id=context.global_request_id) + + if CONF.neutron.url: + # TODO(efried): Remove in Rocky + client_args = dict(client_args, + endpoint_override=CONF.neutron.url, + # NOTE(efried): The legacy behavior was to default + # region_name in the conf. + region_name=CONF.neutron.region_name or 'RegionOne') + else: + # The new way + # NOTE(efried): We build an adapter + # to pull conf options + # to pass to neutronclient + # which uses them to build an Adapter. + # This should be unwound at some point. + adap = utils.get_ksa_adapter( + 'network', ksa_auth=auth_plugin, ksa_session=_SESSION) + client_args = dict(client_args, + service_type=adap.service_type, + service_name=adap.service_name, + interface=adap.interface, + region_name=adap.region_name, + endpoint_override=adap.endpoint_override) + + return ClientWrapper(clientv20.Client(**client_args), + admin=admin or context.is_admin) def _is_not_duplicate(item, items, items_list_name, instance): diff --git a/nova/tests/unit/network/test_neutronv2.py b/nova/tests/unit/network/test_neutronv2.py index 1fefcfb2f8a9..4ec23f635666 100644 --- a/nova/tests/unit/network/test_neutronv2.py +++ b/nova/tests/unit/network/test_neutronv2.py @@ -122,6 +122,36 @@ class TestNeutronClient(test.NoDBTestCase): super(TestNeutronClient, self).setUp() neutronapi.reset_state() + def test_ksa_adapter_loading_defaults(self): + """No 'url' triggers ksa loading path with defaults.""" + my_context = context.RequestContext('userid', + uuids.my_tenant, + auth_token='token') + cl = neutronapi.get_client(my_context) + self.assertEqual('network', cl.httpclient.service_type) + self.assertIsNone(cl.httpclient.service_name) + self.assertEqual(['internal', 'public'], cl.httpclient.interface) + self.assertIsNone(cl.httpclient.region_name) + self.assertIsNone(cl.httpclient.endpoint_override) + + def test_ksa_adapter_loading(self): + """Test ksa loading path with specified values.""" + self.flags(group='neutron', + service_type='st', + service_name='sn', + valid_interfaces='admin', + region_name='RegionTwo', + endpoint_override='eo') + my_context = context.RequestContext('userid', + uuids.my_tenant, + auth_token='token') + cl = neutronapi.get_client(my_context) + self.assertEqual('st', cl.httpclient.service_type) + self.assertEqual('sn', cl.httpclient.service_name) + self.assertEqual(['admin'], cl.httpclient.interface) + self.assertEqual('RegionTwo', cl.httpclient.region_name) + self.assertEqual('eo', cl.httpclient.endpoint_override) + def test_withtoken(self): self.flags(url='http://anyhost/', group='neutron') self.flags(timeout=30, group='neutron') @@ -131,8 +161,9 @@ class TestNeutronClient(test.NoDBTestCase): cl = neutronapi.get_client(my_context) self.assertEqual(CONF.neutron.url, cl.httpclient.endpoint_override) - self.assertEqual(my_context.auth_token, - cl.httpclient.auth.auth_token) + # Specifying 'url' defaults 'region_name' + self.assertEqual('RegionOne', cl.httpclient.region_name) + self.assertEqual(my_context.auth_token, cl.httpclient.auth.auth_token) self.assertEqual(CONF.neutron.timeout, cl.httpclient.session.timeout) def test_withouttoken(self): diff --git a/releasenotes/notes/neutron-via-ksa-9f386b09cff98a9e.yaml b/releasenotes/notes/neutron-via-ksa-9f386b09cff98a9e.yaml new file mode 100644 index 000000000000..4e78605282fc --- /dev/null +++ b/releasenotes/notes/neutron-via-ksa-9f386b09cff98a9e.yaml @@ -0,0 +1,15 @@ +--- +upgrade: + - | + Nova now uses keystoneauth1 configuration to set up communication with the + network service. Use keystoneauth1 loading parameters for Adapter setup in + the ``[neutron]`` conf section (auth and Session options continue to work + as before). Of note: + + * Legacy option ``url`` is deprecated and replaced by + ``endpoint_override``. This should not need to be specified if an + appropriate service catalog entry exists for the network service. + * When ``url`` is not used, ``region_name`` no longer defaults to + ``RegionOne``. + * In Queens, specifying ``url`` will trigger the legacy behavior. The + ``url`` option will be removed in Rocky.