def test_get_string(self): v1_string = '3.23' v1 = api_version_request.APIVersionRequest(v1_string) self.assertEqual(v1_string, v1.get_string()) self.assertRaises(ValueError, api_version_request.APIVersionRequest().get_string)
def decorator(f): obj_min_ver = api_version.APIVersionRequest(min_ver) if max_ver: obj_max_ver = api_version.APIVersionRequest(max_ver) else: obj_max_ver = api_version.APIVersionRequest() # Add to list of versioned methods registered func_name = f.__name__ new_func = versioned_method.VersionedMethod( func_name, obj_min_ver, obj_max_ver, experimental, f) func_dict = getattr(cls, VER_METHOD_ATTR, {}) if not func_dict: setattr(cls, VER_METHOD_ATTR, func_dict) func_list = func_dict.get(func_name, []) if not func_list: func_dict[func_name] = func_list func_list.append(new_func) # Ensure the list is sorted by minimum version (reversed) # so later when we work through the list in order we find # the method which has the latest version which supports # the version requested. # TODO(cyeoh): Add check to ensure that there are no overlapping # ranges of valid versions as that is ambiguous func_list.sort(reverse=True) return f
def test_get_pools_by_volume_type(self, version, support_volume_type, mock_reject_invalid_filters, mock_get_pools): req = fakes.HTTPRequest.blank('/v3/%s/scheduler-stats/get_pools?' 'volume_type=lvm' % fake.PROJECT_ID) mock_get_pools.return_value = [{ 'name': 'pool1', 'capabilities': { 'foo': 'bar' } }] req.api_version_request = api_version.APIVersionRequest(version) req.environ['cinder.context'] = self.ctxt res = self.controller.get_pools(req) expected = {'pools': [{'name': 'pool1'}]} filters = dict() if support_volume_type: filters = {'volume_type': 'lvm'} filters = webob.multidict.MultiDict(filters) mock_reject_invalid_filters.assert_called_once_with( self.ctxt, filters, 'pool', True) self.assertDictEqual(expected, res) mock_get_pools.assert_called_with(mock.ANY, filters=filters)
def get_api_version(version): """Gets a ``APIVersionRequest`` instance. :param version: The microversion needed. :return: The ``APIVersionRequest`` instance. """ return api_version.APIVersionRequest(version)
def test_version_comparisons(self): v1 = api_version_request.APIVersionRequest('2.0') v2 = api_version_request.APIVersionRequest('2.5') v3 = api_version_request.APIVersionRequest('5.23') v4 = api_version_request.APIVersionRequest('2.0') v_null = api_version_request.APIVersionRequest() self.assertTrue(v1 < v2) self.assertTrue(v1 <= v2) self.assertTrue(v3 > v2) self.assertTrue(v3 >= v2) self.assertTrue(v1 != v2) self.assertTrue(v1 == v4) self.assertTrue(v1 != v_null) self.assertTrue(v_null == v_null) self.assertFalse(v1 == '2.0')
def test_snapshot_show(self, max_ver, snapshot_get_by_id, volume_get_by_id, snapshot_metadata_get): snapshot = { 'id': UUID, 'volume_id': fake.VOLUME_ID, 'status': fields.SnapshotStatus.AVAILABLE, 'volume_size': 100, 'display_name': 'Default name', 'display_description': 'Default description', 'expected_attrs': ['metadata'], 'group_snapshot_id': None, } ctx = context.RequestContext(fake.PROJECT_ID, fake.USER_ID, True) snapshot_obj = fake_snapshot.fake_snapshot_obj(ctx, **snapshot) fake_volume_obj = fake_volume.fake_volume_obj(ctx) snapshot_get_by_id.return_value = snapshot_obj volume_get_by_id.return_value = fake_volume_obj req = fakes.HTTPRequest.blank('/v3/snapshots/%s' % UUID) req.api_version_request = api_version.APIVersionRequest(max_ver) resp_dict = self.controller.show(req, UUID) self.assertIn('snapshot', resp_dict) self.assertEqual(UUID, resp_dict['snapshot']['id']) self.assertIn('updated_at', resp_dict['snapshot']) if max_ver == '3.14': self.assertIn('group_snapshot_id', resp_dict['snapshot']) self.assertNotIn('user_id', resp_dict['snapshot']) elif max_ver == '3.13': self.assertNotIn('group_snapshot_id', resp_dict['snapshot']) self.assertNotIn('user_id', resp_dict['snapshot']) elif max_ver == '3.41': self.assertIn('user_id', resp_dict['snapshot'])
def test_volume_creation_from_snapshot(self, max_ver, create, get_snapshot, volume_type_get, group_get): create.side_effect = stubs.stub_volume_api_create get_snapshot.side_effect = stubs.stub_snapshot_get volume_type_get.side_effect = stubs.stub_volume_type_get fake_group = { 'id': fake.GROUP_ID, 'group_type_id': fake.GROUP_TYPE_ID, 'name': 'fake_group' } group_get.return_value = fake_group snapshot_id = fake.SNAPSHOT_ID vol = self._vol_in_request_body(snapshot_id=snapshot_id, group_id=fake.GROUP_ID) body = {"volume": vol} req = fakes.HTTPRequest.blank('/v3/volumes') req.api_version_request = api_version.APIVersionRequest(max_ver) res_dict = self.controller.create(req, body) ex = self._expected_vol_from_controller( snapshot_id=snapshot_id, req_version=req.api_version_request) self.assertEqual(ex, res_dict) context = req.environ['cinder.context'] get_snapshot.assert_called_once_with(self.controller.volume_api, context, snapshot_id) kwargs = self._expected_volume_api_create_kwargs( stubs.stub_snapshot(snapshot_id), test_group=fake_group, req_version=req.api_version_request) create.assert_called_once_with(self.controller.volume_api, context, vol['size'], stubs.DEFAULT_VOL_NAME, stubs.DEFAULT_VOL_DESCRIPTION, **kwargs)
def test_get_all_messages_with_sort(self): self.create_message_for_tests() url = '/v3/messages?sort=event_id:asc' req = fakes.HTTPRequest.blank(url) req.method = 'GET' req.content_type = 'application/json' req.headers["OpenStack-API-Version"] = "volume 3.5" req.api_version_request = api_version.APIVersionRequest('3.5') req.environ['cinder.context'].is_admin = True res = self.controller.index(req) expect_result = [ "VOLUME_VOLUME_001_002", "VOLUME_VOLUME_002_002", "VOLUME_VOLUME_003_002", "VOLUME_VOLUME_003_002", ] expect_result.sort() self.assertEqual(4, len(res['messages'])) self.assertEqual(expect_result[0], res['messages'][0]['event_id']) self.assertEqual(expect_result[1], res['messages'][1]['event_id']) self.assertEqual(expect_result[2], res['messages'][2]['event_id']) self.assertEqual(expect_result[3], res['messages'][3]['event_id'])
def test_version_comparisons(self): v1 = api_version_request.APIVersionRequest('2.0') v2 = api_version_request.APIVersionRequest('2.5') v3 = api_version_request.APIVersionRequest('5.23') v4 = api_version_request.APIVersionRequest('2.0') v_null = api_version_request.APIVersionRequest() self.assertLess(v1, v2) self.assertLessEqual(v1, v2) self.assertGreater(v3, v2) self.assertGreaterEqual(v3, v2) self.assertNotEqual(v1, v2) self.assertEqual(v1, v4) self.assertNotEqual(v1, v_null) self.assertEqual(v_null, v_null) self.assertNotEqual('2.0', v1)
def test_matches_versioned_method(self): request = api_version_request.APIVersionRequest('2.0') self.assertRaises(exception.InvalidParameterValue, request.matches_versioned_method, 'fake_method')
def test_get_all_messages_with_sort(self): self.create_message_for_tests() url = '/v3/messages?sort=event_id:asc' req = fakes.HTTPRequest.blank(url) req.method = 'GET' req.content_type = 'application/json' req.headers["OpenStack-API-Version"] = "volume 3.5" req.api_version_request = api_version.APIVersionRequest('3.5') req.environ['cinder.context'].is_admin = True res = self.controller.index(req) expect_result = [ defined_messages.EventIds.UNKNOWN_ERROR, defined_messages.EventIds.UNABLE_TO_ALLOCATE, defined_messages.EventIds.IMAGE_FROM_VOLUME_OVER_QUOTA, defined_messages.EventIds.ATTACH_READONLY_VOLUME ] expect_result.sort() self.assertEqual(4, len(res['messages'])) self.assertEqual(expect_result[0], res['messages'][0]['event_id']) self.assertEqual(expect_result[1], res['messages'][1]['event_id']) self.assertEqual(expect_result[2], res['messages'][2]['event_id']) self.assertEqual(expect_result[3], res['messages'][3]['event_id'])
def test_volume_revert_update_status_failed(self, mock_volume, mock_update, mock_latest): fake_volume = self._fake_create_volume() fake_snapshot = self._fake_create_snapshot(fake_volume['id']) mock_volume.return_value = fake_volume mock_latest.return_value = fake_snapshot req = fakes.HTTPRequest.blank('/v3/volumes/%s/revert' % fake_volume['id']) req.headers = { 'OpenStack-API-Version': 'volume %s' % REVERT_TO_SNAPSHOT_VERSION } req.api_version_request = api_version.APIVersionRequest( REVERT_TO_SNAPSHOT_VERSION) # update volume's status failed mock_update.side_effect = [False, True] self.assertRaises(webob.exc.HTTPConflict, self.controller.revert, req, fake_volume['id'], {'revert': { 'snapshot_id': fake_snapshot['id'] }}) # update snapshot's status failed mock_update.side_effect = [True, False] self.assertRaises(webob.exc.HTTPConflict, self.controller.revert, req, fake_volume['id'], {'revert': { 'snapshot_id': fake_snapshot['id'] }})
def set_api_version_request(self, url): """Set API version request based on the request header information. Microversions starts with /v3, so if a client sends a request for version 1.0 or 2.0 with the /v3 endpoint, throw an exception. Sending a header with any microversion to a /v1 or /v2 endpoint will be ignored. Note that a microversion must be set for the legacy endpoints. This will appear as 1.0 and 2.0 for /v1 and /v2. """ if API_VERSION_REQUEST_HEADER in self.headers and 'v3' in url: hdr_string = self.headers[API_VERSION_REQUEST_HEADER] # 'latest' is a special keyword which is equivalent to requesting # the maximum version of the API supported hdr_string_list = hdr_string.split(",") volume_version = None for hdr in hdr_string_list: if VOLUME_SERVICE in hdr: service, volume_version = hdr.split() break if not volume_version: raise exception.VersionNotFoundForAPIMethod( version=volume_version) if volume_version == 'latest': self.api_version_request = api_version.max_api_version() else: self.api_version_request = api_version.APIVersionRequest( volume_version) # Check that the version requested is within the global # minimum/maximum of supported API versions if not self.api_version_request.matches( api_version.min_api_version(), api_version.max_api_version()): raise exception.InvalidGlobalAPIVersion( req_ver=self.api_version_request.get_string(), min_ver=api_version.min_api_version().get_string(), max_ver=api_version.max_api_version().get_string()) else: if 'v1' in url: self.api_version_request = api_version.legacy_api_version1() elif 'v2' in url: self.api_version_request = api_version.legacy_api_version2() else: self.api_version_request = api_version.APIVersionRequest( api_version._MIN_API_VERSION)
def test_str(self, major, minor): request_input = '%s.%s' % (major, minor) request = api_version_request.APIVersionRequest(request_input) request_string = six.text_type(request) self.assertEqual( 'API Version Request ' 'Major: %s, Minor: %s' % (major, minor), request_string)
def _fake_update_request(self, backup_id, version=mv.BACKUP_UPDATE): req = fakes.HTTPRequest.blank('/v3/%s/backups/%s/update' % (fake.PROJECT_ID, backup_id)) req.environ['cinder.context'].is_admin = True req.headers['Content-Type'] = 'application/json' req.headers['OpenStack-API-Version'] = 'volume ' + version req.api_version_request = api_version.APIVersionRequest(version) return req
def test__set_log_invalid_level(self, level, exceptions): body = {'level': level} url = '/v3/%s/os-services/set-log' % fake.PROJECT_ID req = fakes.HTTPRequest.blank(url) req.api_version_request = api_version.APIVersionRequest("3.32") self.assertRaises(exceptions, self.controller._set_log, req, self.context, body=body)
def _fake_volumes_summary_request(self, version='3.12', all_tenant=False, is_admin=False): req_url = '/v3/volumes/summary' if all_tenant: req_url += '?all_tenants=True' req = fakes.HTTPRequest.blank(req_url, use_admin_context=is_admin) req.headers = {'OpenStack-API-Version': 'volume ' + version} req.api_version_request = api_version.APIVersionRequest(version) return req
def create_snapshot_query_with_metadata(metadata_query_string, api_microversion): """Helper to create metadata querystring with microversion""" req = fakes.HTTPRequest.blank('/v3/snapshots?metadata=' + metadata_query_string) req.headers["OpenStack-API-Version"] = "volume " + api_microversion req.api_version_request = api_version.APIVersionRequest(api_microversion) return req
def test_volume_index_filter_by_group_id_in_unsupport_version(self): self._create_volume_with_consistency_group() req = fakes.HTTPRequest.blank( ("/v3/volumes?group_id=%s") % fake.CONSISTENCY_GROUP2_ID) req.headers["OpenStack-API-Version"] = "volume 3.9" req.api_version_request = api_version.APIVersionRequest('3.9') req.environ['cinder.context'] = self.ctxt res_dict = self.controller.index(req) volumes = res_dict['volumes'] self.assertEqual(2, len(volumes))
def test_volume_index_filter_by_glance_metadata_in_unsupport_version(self): self._create_volume_with_glance_metadata() req = fakes.HTTPRequest.blank("/v3/volumes?glance_metadata=" "{'image_name': 'imageTestOne'}") req.headers["OpenStack-API-Version"] = "volume 3.0" req.api_version_request = api_version.APIVersionRequest('3.0') req.environ['cinder.context'] = self.ctxt res_dict = self.controller.index(req) volumes = res_dict['volumes'] self.assertEqual(2, len(volumes))
def test_versions_response_fault(self): version = '3.0' req = self.build_request(header_version=version) req.api_version_request = ( api_version_request.APIVersionRequest(version)) app = wsgi.Fault(webob.exc.HTTPBadRequest(explanation='what?')) response = req.get_response(app) self.assertEqual(HTTPStatus.BAD_REQUEST, response.status_int) self.check_response(response, '3.0')
def _get_resp_create(self, body, version='3.0'): url = '/v3/%s/os-volume-manage' % fake.PROJECT_ID req = webob.Request.blank(url, base_url='http://localhost.com' + url) req.method = 'POST' req.headers['Content-Type'] = 'application/json' req.environ['cinder.context'] = self._admin_ctxt req.body = jsonutils.dump_as_bytes(body) req.headers = {'OpenStack-API-Version': 'volume %s' % version} req.api_version_request = api_version.APIVersionRequest(version) res = self.controller.create(req, body) return res
def _get_resp_post_v3(self, body, version): """Helper to execute a POST os-volume-manage API call.""" req = webob.Request.blank('/v3/%s/os-volume-manage' % fake.PROJECT_ID) req.method = 'POST' req.headers['Content-Type'] = 'application/json' req.environ['cinder.context'] = self._admin_ctxt req.headers["OpenStack-API-Version"] = "volume " + version req.api_version_request = api_version.APIVersionRequest(version) req.body = jsonutils.dump_as_bytes(body) res = req.get_response(app_v3()) return res
def test_copy_volume_to_image_public_not_authorized(self): """Test unauthorized create public image from volume.""" id = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' req = fakes.HTTPRequest.blank('/v3/tenant1/volumes/%s/action' % id) req.environ['cinder.context'].is_admin = False req.headers = {'OpenStack-API-Version': 'volume 3.1'} req.api_version_request = api_version.APIVersionRequest('3.1') body = self._get_os_volume_upload_image() body['os-volume_upload_image']['visibility'] = 'public' self.assertRaises(exception.PolicyNotAuthorized, self.controller._volume_upload_image, req, id, body)
def test_volume_index_filter_by_group_id(self): vols = self._create_volume_with_group() req = fakes.HTTPRequest.blank( ("/v3/volumes?group_id=%s") % fake.GROUP_ID) req.headers["OpenStack-API-Version"] = "volume 3.10" req.api_version_request = api_version.APIVersionRequest('3.10') req.environ['cinder.context'] = self.ctxt res_dict = self.controller.index(req) volumes = res_dict['volumes'] self.assertEqual(1, len(volumes)) self.assertEqual(vols[0].id, volumes[0]['id'])
def test_get_limit_with_project_id(self, ver_project, mock_get_quotas): max_ver, has_project = ver_project req = fakes.HTTPRequest.blank('/v3/limits', use_admin_context=True) if has_project: req = fakes.HTTPRequest.blank('/v3/limits?project_id=%s' % fake.UUID1, use_admin_context=True) req.api_version_request = api_version.APIVersionRequest(max_ver) def get_project_quotas(context, project_id, quota_class=None, defaults=True, usages=True): if project_id == fake.UUID1: return {"gigabytes": {'limit': 5}} return {"gigabytes": {'limit': 10}} mock_get_quotas.side_effect = get_project_quotas resp_dict = self.controller.index(req) # if admin, only LIMITS_FILTER and req contains project_id filter, # cinder returns the specified project's quota. if max_ver == LIMITS_FILTER and has_project: self.assertEqual( 5, resp_dict['limits']['absolute']['maxTotalVolumeGigabytes']) else: self.assertEqual( 10, resp_dict['limits']['absolute']['maxTotalVolumeGigabytes']) # if non-admin, cinder always returns self quota. req = fakes.HTTPRequest.blank('/v3/limits', use_admin_context=False) if has_project: req = fakes.HTTPRequest.blank('/v3/limits?project_id=%s' % fake.UUID1, use_admin_context=False) req.api_version_request = api_version.APIVersionRequest(max_ver) resp_dict = self.controller.index(req) self.assertEqual( 10, resp_dict['limits']['absolute']['maxTotalVolumeGigabytes'])
def __init__(self, is_admin=True, version=mv.CLUSTER_SUPPORT, **kwargs): self.GET = kwargs self.headers = {'OpenStack-API-Version': 'volume ' + version} self.api_version_request = api_version.APIVersionRequest(version) self.environ = { 'cinder.context': context.RequestContext(user_id=None, project_id=None, is_admin=is_admin, read_deleted='no', overwrite=False) }
def test_get_all_messages_with_limit_and_offset(self): self.create_message_for_tests() url = '/v3/messages?limit=2&offset=1' req = fakes.HTTPRequest.blank(url) req.method = 'GET' req.content_type = 'application/json' req.headers["OpenStack-API-Version"] = "volume 3.5" req.api_version_request = api_version.APIVersionRequest('3.5') req.environ['cinder.context'].is_admin = True res = self.controller.index(req) self.assertEqual(2, len(res['messages']))
def test_get_all_messages_with_filter(self): self.create_message_for_tests() url = ('/v3/messages?' 'event_id=%s') % defined_messages.UNKNOWN_ERROR req = fakes.HTTPRequest.blank(url) req.method = 'GET' req.content_type = 'application/json' req.headers["OpenStack-API-Version"] = "volume 3.5" req.api_version_request = api_version.APIVersionRequest('3.5') req.environ['cinder.context'].is_admin = True res = self.controller.index(req) self.assertEqual(1, len(res['messages']))
def test_versions_response_fault(self, version): req = self.build_request(header_version=version) req.api_version_request = ( api_version_request.APIVersionRequest(version)) app = wsgi.Fault(webob.exc.HTTPBadRequest(explanation='what?')) response = req.get_response(app) self.assertEqual(http_client.BAD_REQUEST, response.status_int) if version == '3.0': self.check_response(response, '3.0') else: self.assertNotIn(VERSION_HEADER_NAME, response.headers)