Added processing /compute URL for getting list of versions

After implementing blueprint "Ability to run some Nova services under Apache2"(
https://blueprints.launchpad.net/nova/+spec/run-nova-services-under-apache2)
it becomes possible not to use separate ports for each openstack service but
share 80 port with different URL prefixes.

Mailing list thread with discussion the details of this feature:
http://lists.openstack.org/pipermail/openstack-dev/2015-June/067147.html.

Openstack wiki page with mapping urls to services:
https://wiki.openstack.org/wiki/URLs.

If nova-api service is started by Apache (or similar),
using 'Alias' directive script name contains alias-prefix.
We get things like: '/ALIAS/NAME/v2', '/ALIAS/NAME/v2.1'
This change makes sure we compose correct url for getting list of versions.

Co-Authored-By: Marian Horban <mhorban@mirantis.com>
Co-Authored-By: Pavel Kholkin <pkholkin@mirantis.com>

Closes-Bug: #1471833

Change-Id: I2c78e22095975aef777bc62b19d46bcc8fea2d96
This commit is contained in:
Sergey Nikitin 2016-02-25 12:55:51 +03:00
parent 11df0f3b96
commit ba67867b17
4 changed files with 62 additions and 17 deletions

View File

@ -323,10 +323,10 @@ class KeystoneV2AuthProvider(KeystoneAuthProvider):
parts = urlparse.urlparse(_base_url)
if filters.get('api_version', None) is not None:
path = "/" + filters['api_version']
noversion_path = "/".join(parts.path.split("/")[2:])
if noversion_path != "":
path += "/" + noversion_path
path = re.sub(r'(^|/)+v\d+(?:\.\d+)?',
'/' + filters['api_version'],
parts.path,
count=1)
_base_url = _base_url.replace(parts.path, path)
if filters.get('skip_path', None) is not None and parts.path != '':
_base_url = _base_url.replace(parts.path, "/")
@ -445,10 +445,10 @@ class KeystoneV3AuthProvider(KeystoneAuthProvider):
parts = urlparse.urlparse(_base_url)
if filters.get('api_version', None) is not None:
path = "/" + filters['api_version']
noversion_path = "/".join(parts.path.split("/")[2:])
if noversion_path != "":
path += "/" + noversion_path
path = re.sub(r'(^|/)+v\d+(?:\.\d+)?',
'/' + filters['api_version'],
parts.path,
count=1)
_base_url = _base_url.replace(parts.path, path)
if filters.get('skip_path', None) is not None:
_base_url = _base_url.replace(parts.path, "/")

View File

@ -12,6 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
import re
from oslo_serialization import jsonutils as json
from six.moves import urllib
@ -22,14 +24,17 @@ from tempest.lib.common import rest_client
class VersionsClient(rest_client.RestClient):
def _get_base_version_url(self):
# NOTE: The URL which is gotten from keystone's catalog contains
# API version and project-id like "v2/{project-id}", but we need
# to access the URL which doesn't contain them for getting API
# versions. For that, here should use raw_request() instead of
# get().
# NOTE: The URL which is got from keystone's catalog contains
# API version and project-id like "/app-name/v2/{project-id}" or
# "/v2/{project-id}", but we need to access the URL which doesn't
# contain API version for getting API versions. For that, here
# should use raw_request() instead of get().
endpoint = self.base_url
url = urllib.parse.urlparse(endpoint)
return '%s://%s/' % (url.scheme, url.netloc)
url = urllib.parse.urlsplit(endpoint)
new_path = re.split(r'(^|/)+v\d+(\.\d+)?', url.path)[0]
url = list(url)
url[2] = new_path + '/'
return urllib.parse.urlunsplit(url)
def list_versions(self):
version_url = self._get_base_version_url()

View File

@ -16,15 +16,16 @@
class FakeAuthProvider(object):
def __init__(self, creds_dict=None):
def __init__(self, creds_dict=None, fake_base_url=None):
creds_dict = creds_dict or {}
self.credentials = FakeCredentials(creds_dict)
self.fake_base_url = fake_base_url
def auth_request(self, method, url, headers=None, body=None, filters=None):
return url, headers, body
def base_url(self, filters, auth_data=None):
return "https://example.com"
return self.fake_base_url or "https://example.com"
class FakeCredentials(object):

View File

@ -94,3 +94,42 @@ class TestVersionsClient(base.BaseComputeServiceTest):
def test_get_version_by_url_with_bytes_body(self):
self._test_get_version_by_url(bytes_body=True)
def _test_get_base_version_url(self, url, expected_base_url):
auth = fake_auth_provider.FakeAuthProvider(fake_base_url=url)
client = versions_client.VersionsClient(auth, 'compute', 'regionOne')
self.assertEqual(expected_base_url, client._get_base_version_url())
def test_get_base_version_url(self):
self._test_get_base_version_url('https://bar.org/v2/123',
'https://bar.org/')
self._test_get_base_version_url('https://bar.org/v2.1/123',
'https://bar.org/')
self._test_get_base_version_url('https://bar.org/v2.15/123',
'https://bar.org/')
self._test_get_base_version_url('https://bar.org/v22.2/123',
'https://bar.org/')
self._test_get_base_version_url('https://bar.org/v22/123',
'https://bar.org/')
def test_get_base_version_url_app_name(self):
self._test_get_base_version_url('https://bar.org/compute/v2/123',
'https://bar.org/compute/')
self._test_get_base_version_url('https://bar.org/compute/v2.1/123',
'https://bar.org/compute/')
self._test_get_base_version_url('https://bar.org/compute/v2.15/123',
'https://bar.org/compute/')
self._test_get_base_version_url('https://bar.org/compute/v22.2/123',
'https://bar.org/compute/')
self._test_get_base_version_url('https://bar.org/compute/v22/123',
'https://bar.org/compute/')
def test_get_base_version_url_double_slash(self):
self._test_get_base_version_url('https://bar.org//v2/123',
'https://bar.org/')
self._test_get_base_version_url('https://bar.org//v2.1/123',
'https://bar.org/')
self._test_get_base_version_url('https://bar.org/compute//v2/123',
'https://bar.org/compute/')
self._test_get_base_version_url('https://bar.org/compute//v2.1/123',
'https://bar.org/compute/')