
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
196 lines
6.9 KiB
Python
196 lines
6.9 KiB
Python
# 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.
|
|
|
|
import logging
|
|
import json
|
|
|
|
import fixtures
|
|
import mock
|
|
|
|
import cinderclient.client
|
|
import cinderclient.v1.client
|
|
import cinderclient.v2.client
|
|
from cinderclient import exceptions
|
|
from cinderclient.tests.unit.fixture_data import base as fixture_base
|
|
from cinderclient.tests.unit import utils
|
|
from keystoneclient import adapter
|
|
from keystoneclient import exceptions as keystone_exception
|
|
|
|
|
|
class ClientTest(utils.TestCase):
|
|
|
|
def test_get_client_class_v1(self):
|
|
output = cinderclient.client.get_client_class('1')
|
|
self.assertEqual(cinderclient.v1.client.Client, output)
|
|
|
|
def test_get_client_class_v2(self):
|
|
output = cinderclient.client.get_client_class('2')
|
|
self.assertEqual(cinderclient.v2.client.Client, output)
|
|
|
|
def test_get_client_class_unknown(self):
|
|
self.assertRaises(cinderclient.exceptions.UnsupportedVersion,
|
|
cinderclient.client.get_client_class, '0')
|
|
|
|
def test_log_req(self):
|
|
self.logger = self.useFixture(
|
|
fixtures.FakeLogger(
|
|
format="%(message)s",
|
|
level=logging.DEBUG,
|
|
nuke_handlers=True
|
|
)
|
|
)
|
|
|
|
kwargs = {}
|
|
kwargs['headers'] = {"X-Foo": "bar"}
|
|
kwargs['data'] = ('{"auth": {"tenantName": "fakeService",'
|
|
' "passwordCredentials": {"username": "fakeUser",'
|
|
' "password": "fakePassword"}}}')
|
|
|
|
cs = cinderclient.client.HTTPClient("user", None, None,
|
|
"http://127.0.0.1:5000")
|
|
cs.http_log_debug = True
|
|
cs.http_log_req('PUT', kwargs)
|
|
|
|
output = self.logger.output.split('\n')
|
|
|
|
self.assertNotIn("fakePassword", output[1])
|
|
self.assertIn("fakeUser", output[1])
|
|
|
|
def test_versions(self):
|
|
v1_url = fixture_base.VOLUME_V1_URL
|
|
v2_url = fixture_base.VOLUME_V2_URL
|
|
unknown_url = 'http://fakeurl/v9/tenants'
|
|
|
|
self.assertEqual('1',
|
|
cinderclient.client.get_volume_api_from_url(v1_url))
|
|
self.assertEqual('2',
|
|
cinderclient.client.get_volume_api_from_url(v2_url))
|
|
self.assertRaises(cinderclient.exceptions.UnsupportedVersion,
|
|
cinderclient.client.get_volume_api_from_url,
|
|
unknown_url)
|
|
|
|
@mock.patch.object(adapter.Adapter, 'request')
|
|
@mock.patch.object(exceptions, 'from_response')
|
|
def test_sessionclient_request_method(
|
|
self, mock_from_resp, mock_request):
|
|
kwargs = {
|
|
"body": {
|
|
"volume": {
|
|
"status": "creating",
|
|
"imageRef": "username",
|
|
"attach_status": "detached"
|
|
},
|
|
"authenticated": "True"
|
|
}
|
|
}
|
|
|
|
resp = {
|
|
"text": {
|
|
"volume": {
|
|
"status": "creating",
|
|
"id": "431253c0-e203-4da2-88df-60c756942aaf",
|
|
"size": 1
|
|
}
|
|
},
|
|
"code": 202
|
|
}
|
|
|
|
mock_response = utils.TestResponse({
|
|
"status_code": 202,
|
|
"text": json.dumps(resp),
|
|
})
|
|
|
|
# 'request' method of Adaptor will return 202 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=mock_session)
|
|
response, body = session_client.request(fixture_base.VOLUME_V1_URL,
|
|
'POST', **kwargs)
|
|
|
|
# In this case, from_response method will not get called
|
|
# because response status_code is < 400
|
|
self.assertEqual(202, response.status_code)
|
|
self.assertFalse(mock_from_resp.called)
|
|
|
|
@mock.patch.object(adapter.Adapter, 'request')
|
|
def test_sessionclient_request_method_raises_badrequest(
|
|
self, mock_request):
|
|
kwargs = {
|
|
"body": {
|
|
"volume": {
|
|
"status": "creating",
|
|
"imageRef": "username",
|
|
"attach_status": "detached"
|
|
},
|
|
"authenticated": "True"
|
|
}
|
|
}
|
|
|
|
resp = {
|
|
"badRequest": {
|
|
"message": "Invalid image identifier or unable to access "
|
|
"requested image.",
|
|
"code": 400
|
|
}
|
|
}
|
|
|
|
mock_response = utils.TestResponse({
|
|
"status_code": 400,
|
|
"text": json.dumps(resp),
|
|
})
|
|
|
|
# 'request' method of Adaptor will return 400 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=mock_session)
|
|
|
|
# 'from_response' method will raise BadRequest because
|
|
# resp.status_code is 400
|
|
self.assertRaises(exceptions.BadRequest, session_client.request,
|
|
fixture_base.VOLUME_V1_URL, 'POST', **kwargs)
|
|
|
|
@mock.patch.object(exceptions, 'from_response')
|
|
def test_keystone_request_raises_auth_failure_exception(
|
|
self, mock_from_resp):
|
|
|
|
kwargs = {
|
|
"body": {
|
|
"volume": {
|
|
"status": "creating",
|
|
"imageRef": "username",
|
|
"attach_status": "detached"
|
|
},
|
|
"authenticated": "True"
|
|
}
|
|
}
|
|
|
|
with mock.patch.object(adapter.Adapter, 'request',
|
|
side_effect=
|
|
keystone_exception.AuthorizationFailure()):
|
|
mock_session = mock.Mock()
|
|
mock_session.get_endpoint.return_value = fixture_base.VOLUME_V1_URL
|
|
session_client = cinderclient.client.SessionClient(
|
|
session=mock_session)
|
|
self.assertRaises(keystone_exception.AuthorizationFailure,
|
|
session_client.request,
|
|
fixture_base.VOLUME_V1_URL, 'POST', **kwargs)
|
|
|
|
# As keystonesession.request method will raise
|
|
# AuthorizationFailure exception, check exceptions.from_response
|
|
# is not getting called.
|
|
self.assertFalse(mock_from_resp.called)
|