Fix issue "SDKException: Connection failure that may be retried."

This issue will happen when your cloud service endpoints are in
  https and you are using openstack client to perform some
actions related to neutron service.

This issue happened in openstacksdk-0.9.2 and higher.

This issue is because something not expected when finding
  a suitable version of Neutron service endpoint. You will
find you will get an endpoint which is http instead of https.

Change-Id: Iad5187a03b939fcd237d79e9bd868421d360cc63
Closes-Bug: #1616522
This commit is contained in:
Jian Zhao
2016-08-25 04:45:08 -04:00
parent a4ac7f437a
commit b003c3d1cf
2 changed files with 23 additions and 17 deletions

View File

@@ -169,7 +169,9 @@ class Session(_session.Session):
* When an exact major/minor is specified, e.g., v2.0,
it will only match v2.0.
"""
match = None
match_version = None
for version in versions:
api_version = self._parse_version(version["id"])
if profile_version.major != api_version.major:
@@ -178,23 +180,22 @@ class Session(_session.Session):
if profile_version.minor <= api_version.minor:
for link in version["links"]:
if link["rel"] == "self":
match = link["href"]
resp_link = link['href']
match_version = parse.urlsplit(resp_link).path
# Only break out of the loop on an exact match,
# otherwise keep trying.
if profile_version.minor == api_version.minor:
break
if match is None:
if match_version is None:
raise exceptions.EndpointNotFound(
"Unable to determine endpoint for %s" % service_type)
# Some services return only the path fragment of a URI.
# If we split and see that we're not given the scheme and netloc,
# construct the match with the root from the service catalog.
match_split = parse.urlsplit(match)
if not all([match_split.scheme, match_split.netloc]):
match = root_endpoint + match
# Make sure "root_endpoint" has no overlap with match_version
root_parts = parse.urlsplit(root_endpoint)
match_version = match_version.replace(root_parts.path, "", 1)
match = utils.urljoin(root_endpoint, match_version)
# For services that require the project id in the request URI,
# add them in here.

View File

@@ -18,6 +18,7 @@ from keystoneauth1 import exceptions as _exceptions
from openstack import exceptions
from openstack import profile
from openstack import session
from openstack import utils
class TestSession(testtools.TestCase):
@@ -166,7 +167,8 @@ class TestSession(testtools.TestCase):
sot._get_version_match, [], None, "service", "root", False)
def test__get_version_match_fuzzy(self):
match = "http://devstack/v2.1/"
match = "http://devstack/v2.1"
root_endpoint = "http://devstack"
versions = [{"id": "v2.0",
"links": [{"href": "http://devstack/v2/",
"rel": "self"}]},
@@ -178,11 +180,12 @@ class TestSession(testtools.TestCase):
# Look for a v2 match, which we internally denote as a minor
# version of -1 so we can find the highest matching minor.
rv = sot._get_version_match(versions, session.Version(2, -1),
"service", "root", False)
"service", root_endpoint, False)
self.assertEqual(rv, match)
def test__get_version_match_exact(self):
match = "http://devstack/v2/"
match = "http://devstack/v2"
root_endpoint = "http://devstack"
versions = [{"id": "v2.0",
"links": [{"href": match,
"rel": "self"}]},
@@ -192,12 +195,12 @@ class TestSession(testtools.TestCase):
sot = session.Session(None)
rv = sot._get_version_match(versions, session.Version(2, 0),
"service", "root", False)
"service", root_endpoint, False)
self.assertEqual(rv, match)
def test__get_version_match_fragment(self):
root = "http://cloud.net"
match = "/v2/"
match = "/v2"
versions = [{"id": "v2.0", "links": [{"href": match, "rel": "self"}]}]
sot = session.Session(None)
@@ -206,15 +209,17 @@ class TestSession(testtools.TestCase):
self.assertEqual(rv, root+match)
def test__get_version_match_project_id(self):
match = "http://devstack/v2/"
match = "http://devstack/v2"
root_endpoint = "http://devstack"
project_id = "asdf123"
versions = [{"id": "v2.0", "links": [{"href": match, "rel": "self"}]}]
sot = session.Session(None)
sot.get_project_id = mock.Mock(return_value=project_id)
rv = sot._get_version_match(versions, session.Version(2, 0),
"service", "root", True)
self.assertEqual(rv, match + project_id)
"service", root_endpoint, True)
match_endpoint = utils.urljoin(match, project_id)
self.assertEqual(rv, match_endpoint)
def test_get_endpoint_cached(self):
sot = session.Session(None)