Allow v3.0 volume metadata API calls

Commit I575635258c10f299181b8e4cdb51a7ad1f1be764 added some optimization
to a few of the volume metadata API calls. It added a check incorrectly
for the microversion for those changes such that if you were not using
microversion 3.15 or above, it would fail the API call.

This changes the microversion check to correctly either perform the
new requested functionality or fail back to the base 3.0/2.0 API
behavior.

Change-Id: I09ad8200f73273dae8e5d926939620b71d9210e8
Closes-bug: #1712192
This commit is contained in:
Sean McGinnis 2017-08-21 16:29:05 -05:00
parent 2d929962c0
commit c9c668437e
3 changed files with 37 additions and 28 deletions

View File

@ -24,7 +24,6 @@ import webob
from cinder.api.openstack import wsgi
from cinder.api.v2 import volume_metadata as volume_meta_v2
from cinder import exception
METADATA_MICRO_VERSION = '3.15'
@ -43,36 +42,37 @@ class Controller(volume_meta_v2.Controller):
checksum = hashlib.md5(data).hexdigest()
return checksum in req.if_match.etags
def _ensure_min_version(self, req, allowed_version):
version = req.api_version_request
if not version.matches(allowed_version, None):
raise exception.VersionNotFoundForAPIMethod(version=version)
@wsgi.extends
def index(self, req, volume_id):
self._ensure_min_version(req, METADATA_MICRO_VERSION)
req_version = req.api_version_request
metadata = super(Controller, self).index(req, volume_id)
resp = webob.Response()
data = jsonutils.dumps(metadata)
if six.PY3:
data = data.encode('utf-8')
resp.headers['Etag'] = hashlib.md5(data).hexdigest()
resp.body = data
return resp
if req_version.matches(METADATA_MICRO_VERSION):
data = jsonutils.dumps(metadata)
if six.PY3:
data = data.encode('utf-8')
resp = webob.Response()
resp.headers['Etag'] = hashlib.md5(data).hexdigest()
resp.body = data
return resp
return metadata
@wsgi.extends
def update(self, req, volume_id, id, body):
self._ensure_min_version(req, METADATA_MICRO_VERSION)
if not self._validate_etag(req, volume_id):
return webob.Response(status_int=http_client.PRECONDITION_FAILED)
req_version = req.api_version_request
if req_version.matches(METADATA_MICRO_VERSION):
if not self._validate_etag(req, volume_id):
return webob.Response(
status_int=http_client.PRECONDITION_FAILED)
return super(Controller, self).update(req, volume_id,
id, body)
@wsgi.extends
def update_all(self, req, volume_id, body):
self._ensure_min_version(req, METADATA_MICRO_VERSION)
if not self._validate_etag(req, volume_id):
return webob.Response(status_int=http_client.PRECONDITION_FAILED)
req_version = req.api_version_request
if req_version.matches(METADATA_MICRO_VERSION):
if not self._validate_etag(req, volume_id):
return webob.Response(
status_int=http_client.PRECONDITION_FAILED)
return super(Controller, self).update_all(req, volume_id,
body)

View File

@ -108,10 +108,10 @@ def return_volume_nonexistent(*args, **kwargs):
raise exception.VolumeNotFound('bogus test message')
class volumeMetaDataTest(test.TestCase):
class VolumeMetaDataTest(test.TestCase):
def setUp(self):
super(volumeMetaDataTest, self).setUp()
super(VolumeMetaDataTest, self).setUp()
self.volume_api = volume_api.API()
self.mock_object(volume.api.API, 'get', get_volume)
self.mock_object(db, 'volume_metadata_get',

View File

@ -1,6 +1,3 @@
# Copyright 2016 OpenStack Foundation.
# All Rights Reserved.
#
# 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
@ -28,6 +25,7 @@ from cinder import exception
from cinder import test
from cinder.tests.unit.api import fakes
from cinder.tests.unit.api.v2 import fakes as v2_fakes
from cinder.tests.unit.api.v2 import test_volume_metadata as v2_test
from cinder.tests.unit import fake_constants as fake
from cinder.tests.unit import fake_volume
from cinder import volume
@ -119,10 +117,10 @@ def fake_update_volume_metadata(self, context, volume, diff):
pass
class volumeMetaDataTest(test.TestCase):
class VolumeMetaDataTest(test.TestCase):
def setUp(self):
super(volumeMetaDataTest, self).setUp()
super(VolumeMetaDataTest, self).setUp()
self.volume_api = volume_api.API()
self.mock_object(volume.api.API, 'get', get_volume)
self.mock_object(db, 'volume_metadata_get',
@ -139,7 +137,7 @@ class volumeMetaDataTest(test.TestCase):
self.volume_controller = volumes.VolumeController(self.ext_mgr)
self.controller = volume_metadata.Controller()
self.req_id = str(uuid.uuid4())
self.url = '/v2/%s/volumes/%s/metadata' % (
self.url = '/v3/%s/volumes/%s/metadata' % (
fake.PROJECT_ID, self.req_id)
vol = {"size": 100,
@ -255,3 +253,14 @@ class volumeMetaDataTest(test.TestCase):
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.create, req, self.req_id, body)
class VolumeMetaDataTestNoMicroversion(v2_test.VolumeMetaDataTest):
"""Volume metadata tests with no microversion provided."""
def setUp(self):
super(VolumeMetaDataTestNoMicroversion, self).setUp()
self.volume_controller = volumes.VolumeController(self.ext_mgr)
self.controller = volume_metadata.Controller()
self.url = '/v3/%s/volumes/%s/metadata' % (
fake.PROJECT_ID, self.req_id)