Fix version discovery and auth_plugins
V3Client support added version discovery and session supports. Most of the external auth system doesn't support this. This fix bypasses version discovery if the idenity service doesn't support that. Session is used only if no external auth plugin is used Change-Id: Ia84a2ad45940d35c5ef740727f5f7477c72ea9d4 Closes-Bug: #1333961
This commit is contained in:
parent
67a5f72378
commit
b4906c855f
cinderclient
@ -506,7 +506,9 @@ def _construct_http_client(username=None, password=None, project_id=None,
|
||||
cacert=None, tenant_id=None,
|
||||
session=None,
|
||||
auth=None):
|
||||
if session:
|
||||
|
||||
# Don't use sessions if third party plugin is used
|
||||
if session and not auth_plugin:
|
||||
|
||||
# If auth pluggin is specified use that pluggin
|
||||
session.auth = auth or session.auth
|
||||
@ -525,29 +527,29 @@ def _construct_http_client(username=None, password=None, project_id=None,
|
||||
service_name=service_name,
|
||||
region_name=region_name,
|
||||
http_log_debug=http_log_debug)
|
||||
else:
|
||||
# FIXME(jamielennox): username and password are now optional. Need
|
||||
# to test that they were provided in this mode.
|
||||
return HTTPClient(username,
|
||||
password,
|
||||
projectid=project_id,
|
||||
auth_url=auth_url,
|
||||
insecure=insecure,
|
||||
timeout=timeout,
|
||||
tenant_id=tenant_id,
|
||||
proxy_token=proxy_token,
|
||||
proxy_tenant_id=proxy_tenant_id,
|
||||
region_name=region_name,
|
||||
endpoint_type=endpoint_type,
|
||||
service_type=service_type,
|
||||
service_name=service_name,
|
||||
volume_service_name=volume_service_name,
|
||||
retries=retries,
|
||||
http_log_debug=http_log_debug,
|
||||
cacert=cacert,
|
||||
auth_system=auth_system,
|
||||
auth_plugin=auth_plugin,
|
||||
)
|
||||
|
||||
# FIXME(jamielennox): username and password are now optional. Need
|
||||
# to test that they were provided in this mode.
|
||||
return HTTPClient(username,
|
||||
password,
|
||||
projectid=project_id,
|
||||
auth_url=auth_url,
|
||||
insecure=insecure,
|
||||
timeout=timeout,
|
||||
tenant_id=tenant_id,
|
||||
proxy_token=proxy_token,
|
||||
proxy_tenant_id=proxy_tenant_id,
|
||||
region_name=region_name,
|
||||
endpoint_type=endpoint_type,
|
||||
service_type=service_type,
|
||||
service_name=service_name,
|
||||
volume_service_name=volume_service_name,
|
||||
retries=retries,
|
||||
http_log_debug=http_log_debug,
|
||||
cacert=cacert,
|
||||
auth_system=auth_system,
|
||||
auth_plugin=auth_plugin,
|
||||
)
|
||||
|
||||
|
||||
def get_client_class(version):
|
||||
|
@ -43,6 +43,8 @@ from keystoneclient import discover
|
||||
from keystoneclient import session
|
||||
from keystoneclient.auth.identity import v2 as v2_auth
|
||||
from keystoneclient.auth.identity import v3 as v3_auth
|
||||
from keystoneclient.exceptions import DiscoveryFailure
|
||||
import six.moves.urllib.parse as urlparse
|
||||
|
||||
|
||||
DEFAULT_OS_VOLUME_API_VERSION = "1"
|
||||
@ -157,8 +159,7 @@ class OpenStackCinderShell(object):
|
||||
parser.add_argument('--endpoint-type',
|
||||
metavar='<endpoint-type>',
|
||||
default=utils.env('CINDER_ENDPOINT_TYPE',
|
||||
default=
|
||||
DEFAULT_CINDER_ENDPOINT_TYPE),
|
||||
default=DEFAULT_CINDER_ENDPOINT_TYPE),
|
||||
help='Endpoint type, which is publicURL or '
|
||||
'internalURL. '
|
||||
'Default=nova env[CINDER_ENDPOINT_TYPE] or '
|
||||
@ -737,6 +738,36 @@ class OpenStackCinderShell(object):
|
||||
project_domain_id=project_domain_id,
|
||||
)
|
||||
|
||||
def _discover_auth_versions(self, session, auth_url):
|
||||
# discover the API versions the server is supporting based on the
|
||||
# given URL
|
||||
v2_auth_url = None
|
||||
v3_auth_url = None
|
||||
try:
|
||||
ks_discover = discover.Discover(session=session, auth_url=auth_url)
|
||||
v2_auth_url = ks_discover.url_for('2.0')
|
||||
v3_auth_url = ks_discover.url_for('3.0')
|
||||
except DiscoveryFailure:
|
||||
# Discovery response mismatch. Raise the error
|
||||
raise
|
||||
except Exception:
|
||||
# Some public clouds throw some other exception or doesn't support
|
||||
# discovery. In that case try to determine version from auth_url
|
||||
# API version from the original URL
|
||||
url_parts = urlparse.urlparse(auth_url)
|
||||
(scheme, netloc, path, params, query, fragment) = url_parts
|
||||
path = path.lower()
|
||||
if path.startswith('/v3'):
|
||||
v3_auth_url = auth_url
|
||||
elif path.startswith('/v2'):
|
||||
v2_auth_url = auth_url
|
||||
else:
|
||||
raise exc.CommandError('Unable to determine the Keystone'
|
||||
' version to authenticate with '
|
||||
'using the given auth_url.')
|
||||
|
||||
return (v2_auth_url, v3_auth_url)
|
||||
|
||||
def _get_keystone_session(self, **kwargs):
|
||||
# first create a Keystone session
|
||||
cacert = self.options.os_cacert or None
|
||||
@ -747,16 +778,12 @@ class OpenStackCinderShell(object):
|
||||
verify = False
|
||||
else:
|
||||
verify = cacert or True
|
||||
|
||||
ks_session = session.Session(verify=verify, cert=cert)
|
||||
# discover the supported keystone versions using the given url
|
||||
ks_discover = discover.Discover(session=ks_session,
|
||||
auth_url=self.options.os_auth_url)
|
||||
|
||||
# Determine which authentication plugin to use. First inspect the
|
||||
# auth_url to see the supported version. If both v3 and v2 are
|
||||
# supported, then use the highest version if possible.
|
||||
v2_auth_url = ks_discover.url_for('v2.0')
|
||||
v3_auth_url = ks_discover.url_for('v3.0')
|
||||
(v2_auth_url, v3_auth_url) = self._discover_auth_versions(
|
||||
session=ks_session,
|
||||
auth_url=self.options.os_auth_url)
|
||||
|
||||
username = self.options.os_username or None
|
||||
user_domain_name = self.options.os_user_domain_name or None
|
||||
|
@ -49,6 +49,11 @@ V3_VERSION = {'id': 'v3.0',
|
||||
'status': 'stable',
|
||||
'updated': UPDATED}
|
||||
|
||||
WRONG_VERSION_RESPONSE = {'id': 'v2.0',
|
||||
'links': [V2_DESCRIBED_BY_HTML, V2_DESCRIBED_BY_PDF],
|
||||
'status': 'stable',
|
||||
'updated': UPDATED}
|
||||
|
||||
|
||||
def _create_version_list(versions):
|
||||
return json.dumps({'versions': {'values': versions}})
|
||||
@ -206,7 +211,8 @@ def generate_v3_project_scoped_token(**kwargs):
|
||||
|
||||
|
||||
def keystone_request_callback(request, uri, headers):
|
||||
response_headers = {"content-type": "application/json"}
|
||||
response_headers = {"content-type": "application/json",
|
||||
'server': 'Python/HTTPretty', }
|
||||
if uri == BASE_URL:
|
||||
return (200, headers, V3_VERSION_LIST)
|
||||
elif uri == BASE_URL + "/v2.0":
|
||||
@ -216,3 +222,7 @@ def keystone_request_callback(request, uri, headers):
|
||||
token_id, token_data = generate_v3_project_scoped_token()
|
||||
response_headers["X-Subject-Token"] = token_id
|
||||
return (201, response_headers, token_data)
|
||||
elif "WrongDiscoveryResponse.discovery.com" in uri:
|
||||
return (200, response_headers, str(WRONG_VERSION_RESPONSE))
|
||||
else:
|
||||
return (500, response_headers, str(WRONG_VERSION_RESPONSE))
|
||||
|
@ -22,6 +22,9 @@ from testtools import matchers
|
||||
from cinderclient import exceptions
|
||||
from cinderclient import shell
|
||||
from cinderclient.tests import utils
|
||||
from cinderclient.tests.fixture_data import keystone_client
|
||||
from keystoneclient.exceptions import DiscoveryFailure
|
||||
import httpretty
|
||||
|
||||
|
||||
class ShellTest(utils.TestCase):
|
||||
@ -80,8 +83,36 @@ class ShellTest(utils.TestCase):
|
||||
self.assertThat(help_text,
|
||||
matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE))
|
||||
|
||||
def register_keystone_auth_fixture(self, url):
|
||||
httpretty.register_uri(httpretty.GET, url,
|
||||
body=keystone_client.keystone_request_callback)
|
||||
|
||||
@httpretty.activate
|
||||
def test_version_discovery(self):
|
||||
_shell = shell.OpenStackCinderShell()
|
||||
|
||||
os_auth_url = "https://WrongDiscoveryResponse.discovery.com:35357/v2.0"
|
||||
self.register_keystone_auth_fixture(os_auth_url)
|
||||
self.assertRaises(DiscoveryFailure, _shell._discover_auth_versions,
|
||||
None, auth_url=os_auth_url)
|
||||
|
||||
os_auth_url = "https://DiscoveryNotSupported.discovery.com:35357/v2.0"
|
||||
self.register_keystone_auth_fixture(os_auth_url)
|
||||
v2_url, v3_url = _shell._discover_auth_versions(
|
||||
None, auth_url=os_auth_url)
|
||||
self.assertEqual(v2_url, os_auth_url, "Expected v2 url")
|
||||
self.assertEqual(v3_url, None, "Expected no v3 url")
|
||||
|
||||
os_auth_url = "https://DiscoveryNotSupported.discovery.com:35357/v3.0"
|
||||
self.register_keystone_auth_fixture(os_auth_url)
|
||||
v2_url, v3_url = _shell._discover_auth_versions(
|
||||
None, auth_url=os_auth_url)
|
||||
self.assertEqual(v3_url, os_auth_url, "Expected v3 url")
|
||||
self.assertEqual(v2_url, None, "Expected no v2 url")
|
||||
|
||||
|
||||
class CinderClientArgumentParserTest(utils.TestCase):
|
||||
|
||||
def test_ambiguity_solved_for_one_visible_argument(self):
|
||||
parser = shell.CinderClientArgumentParser(add_help=False)
|
||||
parser.add_argument('--test-parameter',
|
||||
@ -94,7 +125,7 @@ class CinderClientArgumentParserTest(utils.TestCase):
|
||||
|
||||
opts = parser.parse_args(['--test'])
|
||||
|
||||
#visible argument must be set
|
||||
# visible argument must be set
|
||||
self.assertTrue(opts.visible_param)
|
||||
self.assertFalse(opts.hidden_param)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user