From f45957a67f2b3a45dbaf48629a4d84380be15756 Mon Sep 17 00:00:00 2001 From: Mark Doffman Date: Wed, 17 Aug 2016 15:47:43 -0500 Subject: [PATCH] Add a new configuration variable for api links. Currently we use WebOb.request.application_url to return a link to the neutron api. This may not be the correct link in the case where 'X-Forwarded-Proto' is used. Nova provides the osapi_compute_link_prefix variable for providing custom links to the api. This does the same for Neutron. Co-Authored-By: Kevin Benton Change-Id: I92227803b1bc2fec10ee168a0285f2f6f09f55b0 --- neutron/api/api_common.py | 17 ++++++++-- neutron/api/views/versions.py | 4 ++- neutron/conf/common.py | 5 +++ neutron/tests/unit/api/test_api_common.py | 33 +++++++++++++++++++ .../network_link_prefix-e3fe37e37ea275b7.yaml | 7 ++++ 5 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 neutron/tests/unit/api/test_api_common.py create mode 100644 releasenotes/notes/network_link_prefix-e3fe37e37ea275b7.yaml diff --git a/neutron/api/api_common.py b/neutron/api/api_common.py index 2c7cdf3574a..6dd94931d5d 100644 --- a/neutron/api/api_common.py +++ b/neutron/api/api_common.py @@ -72,7 +72,7 @@ def get_previous_link(request, items, id_key): marker = items[0][id_key] params['marker'] = marker params['page_reverse'] = True - return "%s?%s" % (request.path_url, parse.urlencode(params)) + return "%s?%s" % (prepare_url(request.path_url), parse.urlencode(params)) def get_next_link(request, items, id_key): @@ -82,7 +82,20 @@ def get_next_link(request, items, id_key): marker = items[-1][id_key] params['marker'] = marker params.pop('page_reverse', None) - return "%s?%s" % (request.path_url, parse.urlencode(params)) + return "%s?%s" % (prepare_url(request.path_url), parse.urlencode(params)) + + +def prepare_url(orig_url): + """Takes a link and swaps in network_link_prefix if set.""" + prefix = cfg.CONF.network_link_prefix + # Copied directly from nova/api/openstack/common.py + if not prefix: + return orig_url + url_parts = list(parse.urlsplit(orig_url)) + prefix_parts = list(parse.urlsplit(prefix)) + url_parts[0:2] = prefix_parts[0:2] + url_parts[2] = prefix_parts[2] + url_parts[2] + return parse.urlunsplit(url_parts).rstrip('/') def get_limit_and_marker(request): diff --git a/neutron/api/views/versions.py b/neutron/api/views/versions.py index 7b54547adfa..d050394b009 100644 --- a/neutron/api/views/versions.py +++ b/neutron/api/views/versions.py @@ -15,6 +15,8 @@ import os +from neutron.api import api_common + def get_view_builder(req): base_url = req.application_url @@ -28,7 +30,7 @@ class ViewBuilder(object): :param base_url: url of the root wsgi application """ - self.base_url = base_url + self.base_url = api_common.prepare_url(base_url) def build(self, version_data): """Generic method used to generate a version entity.""" diff --git a/neutron/conf/common.py b/neutron/conf/common.py index f7b2fd0a388..b7715a8fc71 100644 --- a/neutron/conf/common.py +++ b/neutron/conf/common.py @@ -102,6 +102,11 @@ core_opts = [ "services running on this machine. All the agents and " "services running on this machine must use the same " "host value.")), + cfg.StrOpt("network_link_prefix", + help=_("This string is prepended to the normal URL that is " + "returned in links to the OpenStack Network API. If it " + "is empty (the default), the URLs are returned " + "unchanged.")), cfg.BoolOpt('notify_nova_on_port_status_changes', default=True, help=_("Send notification to nova when port status changes")), cfg.BoolOpt('notify_nova_on_port_data_changes', default=True, diff --git a/neutron/tests/unit/api/test_api_common.py b/neutron/tests/unit/api/test_api_common.py new file mode 100644 index 00000000000..5e28a01352d --- /dev/null +++ b/neutron/tests/unit/api/test_api_common.py @@ -0,0 +1,33 @@ +# 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. + +from oslo_config import cfg + +from neutron.api import api_common +from neutron.tests import base + + +class PrepareUrlTestCase(base.BaseTestCase): + + def test_no_configured_prefix(self): + self.assertFalse(cfg.CONF.network_link_prefix) + requrl = 'http://neutron.example/sub/ports.json?test=1' + # should be unchanged + self.assertEqual(requrl, api_common.prepare_url(requrl)) + + def test_configured_prefix(self): + cfg.CONF.set_override('network_link_prefix', 'http://quantum.example') + requrl = 'http://neutron.example/sub/ports.json?test=1' + expected = 'http://quantum.example/sub/ports.json?test=1' + self.assertEqual(expected, api_common.prepare_url(requrl)) diff --git a/releasenotes/notes/network_link_prefix-e3fe37e37ea275b7.yaml b/releasenotes/notes/network_link_prefix-e3fe37e37ea275b7.yaml new file mode 100644 index 00000000000..c82e83cc20f --- /dev/null +++ b/releasenotes/notes/network_link_prefix-e3fe37e37ea275b7.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + A new ``network_link_prefix`` configuration option is introduced that allows to + alter the domain returned in the URLs included in the API responses. It behaves the + same way as the ``compute_link_prefix`` and ``glance_link_prefix`` + options do for Nova and Glance.