Enable version discovery

The service catalog can now have the cinder endpoint x.x.x.x:8776 with
service_type volume, without needing to specify a version in the
endpoint. Keystone will do discovery of the root / GET of the Cinder API
to discover the versions that can be talked to.

This also provides backwards compatibility for the previous solution of
having v1 enabled on service_type volume and v2 on service_type
volumev2.

Change-Id: Id0347f8370dbc8fd7fa8096cd5859e10b0c5d67c
This commit is contained in:
Mike Perez
2015-01-07 14:29:48 -08:00
parent c8f670eec1
commit ae03d2a721
7 changed files with 381 additions and 34 deletions

View File

@@ -28,6 +28,7 @@ from keystoneclient.auth.identity import base
import requests import requests
from cinderclient import exceptions from cinderclient import exceptions
from cinderclient.openstack.common.gettextutils import _
from cinderclient.openstack.common import importutils from cinderclient.openstack.common import importutils
from cinderclient.openstack.common import strutils from cinderclient.openstack.common import strutils
@@ -71,12 +72,25 @@ def get_volume_api_from_url(url):
class SessionClient(adapter.LegacyJsonAdapter): class SessionClient(adapter.LegacyJsonAdapter):
def request(self, *args, **kwargs): def request(self, url, method, **kwargs):
kwargs.setdefault('authenticated', False) kwargs.setdefault('authenticated', False)
# NOTE(thingee): v1 and v2 require the project id in the url. Prepend
# it if we're doing discovery. We figure out if we're doing discovery
# if there is no project id already specified in the path. parts is
# a list where index 1 is the version discovered and index 2 might be
# an empty string or a project id.
endpoint = self.get_endpoint()
parts = urlparse.urlsplit(endpoint).path.split('/')
project_id = self.get_project_id()
if (parts[1] in ['v1', 'v2'] and parts[2] == ''
and project_id is not None):
url = '{0}{1}{2}'.format(endpoint, project_id, url)
# Note(tpatil): The standard call raises errors from # Note(tpatil): The standard call raises errors from
# keystoneclient, here we need to raise the cinderclient errors. # keystoneclient, here we need to raise the cinderclient errors.
raise_exc = kwargs.pop('raise_exc', True) raise_exc = kwargs.pop('raise_exc', True)
resp, body = super(SessionClient, self).request(*args, resp, body = super(SessionClient, self).request(url, method,
raise_exc=False, raise_exc=False,
**kwargs) **kwargs)
if raise_exc and resp.status_code >= 400: if raise_exc and resp.status_code >= 400:
@@ -102,7 +116,14 @@ class SessionClient(adapter.LegacyJsonAdapter):
return self._cs_request(url, 'DELETE', **kwargs) return self._cs_request(url, 'DELETE', **kwargs)
def get_volume_api_version_from_endpoint(self): def get_volume_api_version_from_endpoint(self):
return get_volume_api_from_url(self.get_endpoint()) endpoint = self.get_endpoint()
if not endpoint:
msg = _('The Cinder server does not support %s. Check your '
'providers supported versions and try again with '
'setting --os-volume-api-version or the environment '
'variable OS_VOLUME_API_VERSION.') % self.version
raise exceptions.InvalidAPIVersion(msg)
return get_volume_api_from_url(endpoint)
def authenticate(self, auth=None): def authenticate(self, auth=None):
self.invalidate(auth) self.invalidate(auth)
@@ -540,4 +561,4 @@ def get_client_class(version):
def Client(version, *args, **kwargs): def Client(version, *args, **kwargs):
client_class = get_client_class(version) client_class = get_client_class(version)
return client_class(*args, **kwargs) return client_class(*args, version=version, **kwargs)

View File

@@ -43,11 +43,12 @@ from cinderclient.openstack.common.gettextutils import _
from cinderclient.v1 import shell as shell_v1 from cinderclient.v1 import shell as shell_v1
from cinderclient.v2 import shell as shell_v2 from cinderclient.v2 import shell as shell_v2
from keystoneclient import adapter
from keystoneclient import discover from keystoneclient import discover
from keystoneclient import session from keystoneclient import session
from keystoneclient.auth.identity import v2 as v2_auth from keystoneclient.auth.identity import v2 as v2_auth
from keystoneclient.auth.identity import v3 as v3_auth from keystoneclient.auth.identity import v3 as v3_auth
from keystoneclient.exceptions import DiscoveryFailure from keystoneclient import exceptions as keystoneclient_exc
import six.moves.urllib.parse as urlparse import six.moves.urllib.parse as urlparse
osprofiler_profiler = importutils.try_import("osprofiler.profiler") osprofiler_profiler = importutils.try_import("osprofiler.profiler")
@@ -542,6 +543,7 @@ class OpenStackCinderShell(object):
(options, args) = parser.parse_known_args(argv) (options, args) = parser.parse_known_args(argv)
self.setup_debugging(options.debug) self.setup_debugging(options.debug)
api_version_input = True api_version_input = True
service_type_input = True
self.options = options self.options = options
if not options.os_volume_api_version: if not options.os_volume_api_version:
@@ -551,6 +553,8 @@ class OpenStackCinderShell(object):
options.os_volume_api_version = DEFAULT_OS_VOLUME_API_VERSION options.os_volume_api_version = DEFAULT_OS_VOLUME_API_VERSION
api_version_input = False api_version_input = False
version = (options.os_volume_api_version,)
# build available subcommands based on version # build available subcommands based on version
self.extensions = self._discover_extensions( self.extensions = self._discover_extensions(
options.os_volume_api_version) options.os_volume_api_version)
@@ -599,6 +603,7 @@ class OpenStackCinderShell(object):
if not service_type: if not service_type:
service_type = DEFAULT_CINDER_SERVICE_TYPE service_type = DEFAULT_CINDER_SERVICE_TYPE
service_type = utils.get_service_type(args.func) or service_type service_type = utils.get_service_type(args.func) or service_type
service_type_input = False
# FIXME(usrleon): Here should be restrict for project id same as # FIXME(usrleon): Here should be restrict for project id same as
# for os_username or os_password but for compatibility it is not. # for os_username or os_password but for compatibility it is not.
@@ -676,22 +681,75 @@ class OpenStackCinderShell(object):
"through --os-auth-url or env[OS_AUTH_URL].") "through --os-auth-url or env[OS_AUTH_URL].")
auth_session = self._get_keystone_session() auth_session = self._get_keystone_session()
if not service_type_input or not api_version_input:
# NOTE(thingee): Unfortunately the v2 shell is tied to volumev2
# service_type. If the service_catalog just contains service_type
# volume with x.x.x.x:8776 for discovery, and the user sets version
# 2 for the client, it'll default to volumev2 and raise
# EndpointNotFound. This is a workaround until we feel comfortable
# with removing the volumev2 assumption.
keystone_adapter = adapter.Adapter(auth_session)
try:
# Try just the client's defaults
endpoint = keystone_adapter.get_endpoint(
service_type=service_type,
version=version,
interface='public')
self.cs = client.Client(options.os_volume_api_version, os_username, # Service was found, but wrong version. Lets try a different
os_password, os_tenant_name, os_auth_url, # version, if the user did not specify one.
insecure, region_name=os_region_name, if not endpoint and not api_version_input:
if version == ('1',):
version = ('2',)
else:
version = ('1',)
endpoint = keystone_adapter.get_endpoint(
service_type=service_type, version=version,
interface='public')
except keystoneclient_exc.EndpointNotFound as e:
# No endpoint found with that service_type, lets fall back to
# other service_types if the user did not specify one.
if not service_type_input:
if service_type == 'volume':
service_type = 'volumev2'
else:
service_type = 'volume'
try:
endpoint = keystone_adapter.get_endpoint(
version=version,
service_type=service_type, interface='public')
# Service was found, but wrong version. Lets try
# a different version, if the user did not specify one.
if not endpoint and not api_version_input:
if version == ('1',):
version = ('2',)
else:
version = ('1',)
endpoint = keystone_adapter.get_endpoint(
service_type=service_type, version=version,
interface='public')
except keystoneclient_exc.EndpointNotFound:
raise e
self.cs = client.Client(version[0], os_username, os_password,
os_tenant_name, os_auth_url,
region_name=os_region_name,
tenant_id=os_tenant_id, tenant_id=os_tenant_id,
endpoint_type=endpoint_type, endpoint_type=endpoint_type,
extensions=self.extensions, extensions=self.extensions,
service_type=service_type, service_type=service_type,
service_name=service_name, service_name=service_name,
volume_service_name=volume_service_name, volume_service_name=volume_service_name,
bypass_url=bypass_url, bypass_url=bypass_url, retries=options.retries,
retries=options.retries, http_log_debug=args.debug, cacert=cacert,
http_log_debug=args.debug, auth_system=os_auth_system,
cacert=cacert, auth_system=os_auth_system, auth_plugin=auth_plugin, session=auth_session)
auth_plugin=auth_plugin,
session=auth_session)
try: try:
if not utils.isunauthenticated(args.func): if not utils.isunauthenticated(args.func):
@@ -709,7 +767,8 @@ class OpenStackCinderShell(object):
try: try:
endpoint_api_version = \ endpoint_api_version = \
self.cs.get_volume_api_version_from_endpoint() self.cs.get_volume_api_version_from_endpoint()
if endpoint_api_version != options.os_volume_api_version: if (endpoint_api_version != options.os_volume_api_version
and api_version_input):
msg = (("OpenStack Block Storage API version is set to %s " msg = (("OpenStack Block Storage API version is set to %s "
"but you are accessing a %s endpoint. " "but you are accessing a %s endpoint. "
"Change its value through --os-volume-api-version " "Change its value through --os-volume-api-version "
@@ -827,7 +886,7 @@ class OpenStackCinderShell(object):
ks_discover = discover.Discover(session=session, auth_url=auth_url) ks_discover = discover.Discover(session=session, auth_url=auth_url)
v2_auth_url = ks_discover.url_for('2.0') v2_auth_url = ks_discover.url_for('2.0')
v3_auth_url = ks_discover.url_for('3.0') v3_auth_url = ks_discover.url_for('3.0')
except DiscoveryFailure: except keystoneclient_exc.DiscoveryFailure:
# Discovery response mismatch. Raise the error # Discovery response mismatch. Raise the error
raise raise
except Exception: except Exception:

View File

@@ -14,6 +14,42 @@ import fixtures
IDENTITY_URL = 'http://identityserver:5000/v2.0' IDENTITY_URL = 'http://identityserver:5000/v2.0'
VOLUME_URL = 'http://volume.host' VOLUME_URL = 'http://volume.host'
TENANT_ID = 'b363706f891f48019483f8bd6503c54b'
VOLUME_V1_URL = '%(volume_url)s/v1/%(tenant_id)s' % {'volume_url': VOLUME_URL,
'tenant_id': TENANT_ID}
VOLUME_V2_URL = '%(volume_url)s/v2/%(tenant_id)s' % {'volume_url': VOLUME_URL,
'tenant_id': TENANT_ID}
def generate_version_output(v1=True, v2=True):
v1_dict = {
"status": "SUPPORTED",
"updated": "2014-06-28T12:20:21Z",
"id": "v1.0",
"links": [{
"href": "http://127.0.0.1:8776/v1/",
"rel": "self"
}]
}
v2_dict = {
"status": "CURRENT",
"updated": "2012-11-21T11:33:21Z",
"id": "v2.0", "links": [{
"href": "http://127.0.0.1:8776/v2/",
"rel": "self"
}]
}
versions = []
if v1:
versions.append(v1_dict)
if v2:
versions.append(v2_dict)
return {"versions": versions}
class Fixture(fixtures.Fixture): class Fixture(fixtures.Fixture):

View File

@@ -21,6 +21,7 @@ import cinderclient.client
import cinderclient.v1.client import cinderclient.v1.client
import cinderclient.v2.client import cinderclient.v2.client
from cinderclient import exceptions from cinderclient import exceptions
from cinderclient.tests.unit.fixture_data import base as fixture_base
from cinderclient.tests.unit import utils from cinderclient.tests.unit import utils
from keystoneclient import adapter from keystoneclient import adapter
from keystoneclient import exceptions as keystone_exception from keystoneclient import exceptions as keystone_exception
@@ -62,14 +63,12 @@ class ClientTest(utils.TestCase):
output = self.logger.output.split('\n') output = self.logger.output.split('\n')
print("JSBRYANT: output is", output)
self.assertNotIn("fakePassword", output[1]) self.assertNotIn("fakePassword", output[1])
self.assertIn("fakeUser", output[1]) self.assertIn("fakeUser", output[1])
def test_versions(self): def test_versions(self):
v1_url = 'http://fakeurl/v1/tenants' v1_url = fixture_base.VOLUME_V1_URL
v2_url = 'http://fakeurl/v2/tenants' v2_url = fixture_base.VOLUME_V2_URL
unknown_url = 'http://fakeurl/v9/tenants' unknown_url = 'http://fakeurl/v9/tenants'
self.assertEqual('1', self.assertEqual('1',
@@ -113,8 +112,11 @@ class ClientTest(utils.TestCase):
# 'request' method of Adaptor will return 202 response # 'request' method of Adaptor will return 202 response
mock_request.return_value = mock_response mock_request.return_value = mock_response
session_client = cinderclient.client.SessionClient(session=mock.Mock()) mock_session = mock.Mock()
response, body = session_client.request(mock.sentinel.url, mock_session.get_endpoint.return_value = fixture_base.VOLUME_V1_URL
session_client = cinderclient.client.SessionClient(
session=mock_session)
response, body = session_client.request(fixture_base.VOLUME_V1_URL,
'POST', **kwargs) 'POST', **kwargs)
# In this case, from_response method will not get called # In this case, from_response method will not get called
@@ -151,13 +153,15 @@ class ClientTest(utils.TestCase):
# 'request' method of Adaptor will return 400 response # 'request' method of Adaptor will return 400 response
mock_request.return_value = mock_response mock_request.return_value = mock_response
mock_session = mock.Mock()
mock_session.get_endpoint.return_value = fixture_base.VOLUME_V1_URL
session_client = cinderclient.client.SessionClient( session_client = cinderclient.client.SessionClient(
session=mock.Mock()) session=mock_session)
# 'from_response' method will raise BadRequest because # 'from_response' method will raise BadRequest because
# resp.status_code is 400 # resp.status_code is 400
self.assertRaises(exceptions.BadRequest, session_client.request, self.assertRaises(exceptions.BadRequest, session_client.request,
mock.sentinel.url, 'POST', **kwargs) fixture_base.VOLUME_V1_URL, 'POST', **kwargs)
@mock.patch.object(exceptions, 'from_response') @mock.patch.object(exceptions, 'from_response')
def test_keystone_request_raises_auth_failure_exception( def test_keystone_request_raises_auth_failure_exception(
@@ -177,11 +181,13 @@ class ClientTest(utils.TestCase):
with mock.patch.object(adapter.Adapter, 'request', with mock.patch.object(adapter.Adapter, 'request',
side_effect= side_effect=
keystone_exception.AuthorizationFailure()): keystone_exception.AuthorizationFailure()):
mock_session = mock.Mock()
mock_session.get_endpoint.return_value = fixture_base.VOLUME_V1_URL
session_client = cinderclient.client.SessionClient( session_client = cinderclient.client.SessionClient(
session=mock.Mock()) session=mock_session)
self.assertRaises(keystone_exception.AuthorizationFailure, self.assertRaises(keystone_exception.AuthorizationFailure,
session_client.request, session_client.request,
mock.sentinel.url, 'POST', **kwargs) fixture_base.VOLUME_V1_URL, 'POST', **kwargs)
# As keystonesession.request method will raise # As keystonesession.request method will raise
# AuthorizationFailure exception, check exceptions.from_response # AuthorizationFailure exception, check exceptions.from_response

View File

@@ -16,6 +16,7 @@ import re
import sys import sys
import fixtures import fixtures
from keystoneclient import fixture as keystone_client_fixture
import mock import mock
import requests_mock import requests_mock
from six import moves from six import moves
@@ -23,8 +24,9 @@ from testtools import matchers
from cinderclient import exceptions from cinderclient import exceptions
from cinderclient import shell from cinderclient import shell
from cinderclient.tests.unit import utils from cinderclient.tests.unit.fixture_data import base as fixture_base
from cinderclient.tests.unit.fixture_data import keystone_client from cinderclient.tests.unit.fixture_data import keystone_client
from cinderclient.tests.unit import utils
import keystoneclient.exceptions as ks_exc import keystoneclient.exceptions as ks_exc
from keystoneclient.exceptions import DiscoveryFailure from keystoneclient.exceptions import DiscoveryFailure
@@ -35,7 +37,7 @@ class ShellTest(utils.TestCase):
'OS_USERNAME': 'username', 'OS_USERNAME': 'username',
'OS_PASSWORD': 'password', 'OS_PASSWORD': 'password',
'OS_TENANT_NAME': 'tenant_name', 'OS_TENANT_NAME': 'tenant_name',
'OS_AUTH_URL': 'http://no.where/v2.0', 'OS_AUTH_URL': '%s/v2.0' % keystone_client.BASE_HOST,
} }
# Patch os.environ to avoid required auth info. # Patch os.environ to avoid required auth info.
@@ -116,6 +118,203 @@ class ShellTest(utils.TestCase):
self.assertEqual(v3_url, os_auth_url, "Expected v3 url") self.assertEqual(v3_url, os_auth_url, "Expected v3 url")
self.assertEqual(v2_url, None, "Expected no v2 url") self.assertEqual(v2_url, None, "Expected no v2 url")
@requests_mock.Mocker()
def test_cinder_version_legacy_endpoint_v1_and_v2(self, mocker):
"""Verify that legacy endpoint settings still work.
Legacy endpoints that are not using version discovery is
<hostname>:<port>/<version>/(tenant_id)s. For this unit test, we fill
in the tenant_id for mocking purposes.
"""
token = keystone_client_fixture.V2Token()
cinder_url = 'http://127.0.0.1:8776/v1/%s' % fixture_base.TENANT_ID
volume_service = token.add_service('volume', 'Cinder v1')
volume_service.add_endpoint(public=cinder_url, region='RegionOne')
volumev2_service = token.add_service('volumev2', 'Cinder v2')
volumev2_service.add_endpoint(public=cinder_url, region='RegionOne')
mocker.post(keystone_client.BASE_HOST + '/v2.0/tokens',
json=token)
mocker.get(cinder_url, json=fixture_base.generate_version_output())
volume_request = mocker.get('http://127.0.0.1:8776/v1/volumes/detail',
json={'volumes': {}})
self.shell('list')
self.assertTrue(volume_request.called)
@requests_mock.Mocker()
def test_cinder_version_legacy_endpoint_only_v1(self, mocker):
"""Verify that v1 legacy endpoint settings still work.
Legacy endpoints that are not using version discovery is
<hostname>:<port>/<version>/(tenant_id)s. For this unit test, we fill
in the tenant_id for mocking purposes.
"""
token = keystone_client_fixture.V2Token()
cinder_url = 'http://127.0.0.1:8776/v1/%s' % fixture_base.TENANT_ID
volume_service = token.add_service('volume', 'Cinder v1')
volume_service.add_endpoint(
public=cinder_url,
region='RegionOne'
)
mocker.get(
cinder_url,
json=fixture_base.generate_version_output(v1=True, v2=False)
)
mocker.post(keystone_client.BASE_HOST + '/v2.0/tokens',
json=token)
volume_request = mocker.get('http://127.0.0.1:8776/v1/volumes/detail',
json={'volumes': {}})
self.shell('list')
self.assertTrue(volume_request.called)
@requests_mock.Mocker()
def test_cinder_version_legacy_endpoint_only_v2(self, mocker):
"""Verify that v2 legacy endpoint settings still work.
Legacy endpoints that are not using version discovery is
<hostname>:<port>/<version>/(tenant_id)s. For this unit test, we fill
in the tenant_id for mocking purposes.
"""
token = keystone_client_fixture.V2Token()
cinder_url = 'http://127.0.0.1:8776/v2/%s' % fixture_base.TENANT_ID
volumev2_service = token.add_service('volumev2', 'Cinder v2')
volumev2_service.add_endpoint(
public=cinder_url,
region='RegionOne'
)
mocker.post(keystone_client.BASE_HOST + '/v2.0/tokens',
json=token)
mocker.get(
cinder_url,
json=fixture_base.generate_version_output(v1=False, v2=True)
)
volume_request = mocker.get('http://127.0.0.1:8776/v2/volumes/detail',
json={'volumes': {}})
self.shell('list')
self.assertTrue(volume_request.called)
@requests_mock.Mocker()
def test_cinder_version_discovery(self, mocker):
"""Verify client works two endpoints enabled under one service."""
token = keystone_client_fixture.V2Token()
volume_service = token.add_service('volume', 'Cinder')
volume_service.add_endpoint(public='http://127.0.0.1:8776',
region='RegionOne')
mocker.post(keystone_client.BASE_HOST + '/v2.0/tokens',
json=token)
mocker.get(
'http://127.0.0.1:8776/',
json=fixture_base.generate_version_output(v1=True, v2=True)
)
v1_request = mocker.get('http://127.0.0.1:8776/v1/volumes/detail',
json={'volumes': {}})
v2_request = mocker.get('http://127.0.0.1:8776/v2/volumes/detail',
json={'volumes': {}})
self.shell('list')
self.assertTrue(v1_request.called)
self.shell('--os-volume-api-version 2 list')
self.assertTrue(v2_request.called)
@requests_mock.Mocker()
def test_cinder_version_discovery_only_v1(self, mocker):
"""Verify when v1 is only enabled, the client discovers it."""
token = keystone_client_fixture.V2Token()
volume_service = token.add_service('volume', 'Cinder')
volume_service.add_endpoint(public='http://127.0.0.1:8776',
region='RegionOne')
mocker.post(keystone_client.BASE_HOST + '/v2.0/tokens',
json=token)
mocker.get(
'http://127.0.0.1:8776/',
json=fixture_base.generate_version_output(v1=True, v2=True)
)
volume_request = mocker.get('http://127.0.0.1:8776/v1/volumes/detail',
json={'volumes': {}})
self.shell('list')
self.assertTrue(volume_request.called)
@requests_mock.Mocker()
def test_cinder_version_discovery_only_v2(self, mocker):
"""Verify when v2 is enabled, the client discovers it."""
token = keystone_client_fixture.V2Token()
volumev2_service = token.add_service('volume', 'Cinder')
volumev2_service.add_endpoint(public='http://127.0.0.1:8776',
region='RegionOne')
mocker.post(keystone_client.BASE_HOST + '/v2.0/tokens',
json=token)
mocker.get(
'http://127.0.0.1:8776/',
json=fixture_base.generate_version_output(v1=False, v2=True)
)
volume_request = mocker.get('http://127.0.0.1:8776/v2/volumes/detail',
json={'volumes': {}})
self.shell('list')
self.assertTrue(volume_request.called)
@requests_mock.Mocker()
def test_cinder_version_discovery_fallback(self, mocker):
"""Client defaults to v1, but v2 is only available, fallback to v2."""
token = keystone_client_fixture.V2Token()
volumev2_service = token.add_service('volumev2', 'Cinder v2')
volumev2_service.add_endpoint(public='http://127.0.0.1:8776',
region='RegionOne')
mocker.post(keystone_client.BASE_HOST + '/v2.0/tokens',
json=token)
mocker.get(
'http://127.0.0.1:8776/',
json=fixture_base.generate_version_output(v1=False, v2=True)
)
volume_request = mocker.get('http://127.0.0.1:8776/v2/volumes/detail',
json={'volumes': {}})
self.shell('list')
self.assertTrue(volume_request.called)
@requests_mock.Mocker()
def test_cinder_version_discovery_unsupported_version(self, mocker):
"""Try a version from the client that's not enabled in Cinder."""
token = keystone_client_fixture.V2Token()
volume_service = token.add_service('volume', 'Cinder')
volume_service.add_endpoint(public='http://127.0.0.1:8776',
region='RegionOne')
mocker.post(keystone_client.BASE_HOST + '/v2.0/tokens',
json=token)
mocker.get(
'http://127.0.0.1:8776/',
json=fixture_base.generate_version_output(v1=False, v2=True)
)
self.assertRaises(exceptions.InvalidAPIVersion,
self.shell, '--os-volume-api-version 1 list')
@mock.patch('sys.stdin', side_effect=mock.MagicMock) @mock.patch('sys.stdin', side_effect=mock.MagicMock)
@mock.patch('getpass.getpass', return_value='password') @mock.patch('getpass.getpass', return_value='password')
def test_password_prompted(self, mock_getpass, mock_stdin): def test_password_prompted(self, mock_getpass, mock_stdin):

View File

@@ -16,15 +16,17 @@
# under the License. # under the License.
import fixtures import fixtures
from keystoneclient import fixture as keystone_client_fixture
from requests_mock.contrib import fixture as requests_mock_fixture from requests_mock.contrib import fixture as requests_mock_fixture
from cinderclient import client from cinderclient import client
from cinderclient import exceptions from cinderclient import exceptions
from cinderclient import shell from cinderclient import shell
from cinderclient.v1 import shell as shell_v1 from cinderclient.tests.unit.fixture_data import base as fixture_base
from cinderclient.tests.unit.v1 import fakes
from cinderclient.tests.unit import utils
from cinderclient.tests.unit.fixture_data import keystone_client from cinderclient.tests.unit.fixture_data import keystone_client
from cinderclient.tests.unit import utils
from cinderclient.tests.unit.v1 import fakes
from cinderclient.v1 import shell as shell_v1
class ShellTest(utils.TestCase): class ShellTest(utils.TestCase):
@@ -54,7 +56,18 @@ class ShellTest(utils.TestCase):
self.requests = self.useFixture(requests_mock_fixture.Fixture()) self.requests = self.useFixture(requests_mock_fixture.Fixture())
self.requests.register_uri( self.requests.register_uri(
'GET', keystone_client.BASE_URL, 'GET', keystone_client.BASE_URL,
text=keystone_client.keystone_request_callback) text=keystone_client.keystone_request_callback
)
token = keystone_client_fixture.V2Token()
s = token.add_service('volume', 'cinder')
s.add_endpoint(public='http://127.0.0.1:8776')
self.requests.post(keystone_client.BASE_URL + 'v2.0/tokens',
json=token)
self.requests.get(
'http://127.0.0.1:8776',
json=fixture_base.generate_version_output()
)
def tearDown(self): def tearDown(self):
# For some method like test_image_meta_bad_action we are # For some method like test_image_meta_bad_action we are

View File

@@ -14,6 +14,7 @@
# under the License. # under the License.
import fixtures import fixtures
from keystoneclient import fixture as keystone_client_fixture
import mock import mock
from requests_mock.contrib import fixture as requests_mock_fixture from requests_mock.contrib import fixture as requests_mock_fixture
from six.moves.urllib import parse from six.moves.urllib import parse
@@ -21,9 +22,10 @@ from six.moves.urllib import parse
from cinderclient import client from cinderclient import client
from cinderclient import exceptions from cinderclient import exceptions
from cinderclient import shell from cinderclient import shell
from cinderclient.tests.unit.fixture_data import base as fixture_base
from cinderclient.tests.unit.fixture_data import keystone_client
from cinderclient.tests.unit import utils from cinderclient.tests.unit import utils
from cinderclient.tests.unit.v2 import fakes from cinderclient.tests.unit.v2 import fakes
from cinderclient.tests.unit.fixture_data import keystone_client
class ShellTest(utils.TestCase): class ShellTest(utils.TestCase):
@@ -53,7 +55,18 @@ class ShellTest(utils.TestCase):
self.requests = self.useFixture(requests_mock_fixture.Fixture()) self.requests = self.useFixture(requests_mock_fixture.Fixture())
self.requests.register_uri( self.requests.register_uri(
'GET', keystone_client.BASE_URL, 'GET', keystone_client.BASE_URL,
text=keystone_client.keystone_request_callback) text=keystone_client.keystone_request_callback
)
token = keystone_client_fixture.V2Token()
s = token.add_service('volume', 'cinder')
s.add_endpoint(public='http://127.0.0.1:8776')
self.requests.post(keystone_client.BASE_URL + 'v2.0/tokens',
json=token)
self.requests.get(
'http://127.0.0.1:8776',
json=fixture_base.generate_version_output()
)
def tearDown(self): def tearDown(self):
# For some methods like test_image_meta_bad_action we are # For some methods like test_image_meta_bad_action we are