Merge "Implement volume list availability zone filter"
This commit is contained in:
commit
0649d63be4
tricircle
cinder_apigw/controllers
common
tests/functional/cinder_apigw/controllers
@ -13,6 +13,8 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import urlparse
|
||||
|
||||
import pecan
|
||||
from pecan import expose
|
||||
from pecan import request
|
||||
@ -220,6 +222,16 @@ class VolumeController(rest.RestController):
|
||||
if pod['pod_name'] == '':
|
||||
continue
|
||||
|
||||
query = urlparse.urlsplit(request.url).query
|
||||
query_filters = urlparse.parse_qsl(query)
|
||||
skip_pod = False
|
||||
for k, v in query_filters:
|
||||
if k == 'availability_zone' and v != pod['az_name']:
|
||||
skip_pod = True
|
||||
break
|
||||
if skip_pod:
|
||||
continue
|
||||
|
||||
s_ctx = hclient.get_pod_service_ctx(
|
||||
context,
|
||||
request.url,
|
||||
|
@ -13,6 +13,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import urllib
|
||||
import urlparse
|
||||
|
||||
from requests import Request
|
||||
@ -87,7 +88,17 @@ def get_bottom_url(t_ver, t_url, b_ver, b_endpoint):
|
||||
path = '/' + b_ver + '/' + after_ver
|
||||
if b_ver == '':
|
||||
path = '/' + after_ver
|
||||
query = t_parse.query
|
||||
|
||||
# Remove availability_zone filter since it is handled by VolumeController.
|
||||
# VolumeController will send GET request only to bottom pods whose AZ
|
||||
# is specified in availability_zone filter.
|
||||
query_filters = []
|
||||
for k, v in urlparse.parse_qsl(t_parse.query):
|
||||
if k == 'availability_zone':
|
||||
continue
|
||||
query_filters.append((k, v))
|
||||
query = urllib.urlencode(query_filters)
|
||||
|
||||
fragment = t_parse.fragment
|
||||
|
||||
b_url = urlparse.urlunsplit((scheme,
|
||||
|
@ -14,6 +14,7 @@
|
||||
# under the License.
|
||||
|
||||
from mock import patch
|
||||
import urlparse
|
||||
|
||||
import pecan
|
||||
from pecan.configuration import set_config
|
||||
@ -49,6 +50,7 @@ def fake_volumes_forward_req(ctx, action, b_header, b_url, b_req_body):
|
||||
resp = Response()
|
||||
resp.status_code = 404
|
||||
|
||||
parse = urlparse.urlsplit(b_url)
|
||||
if action == 'POST':
|
||||
b_body = jsonutils.loads(b_req_body)
|
||||
if b_body.get('volume'):
|
||||
@ -56,7 +58,7 @@ def fake_volumes_forward_req(ctx, action, b_header, b_url, b_req_body):
|
||||
vol['id'] = uuidutils.generate_uuid()
|
||||
stored_vol = {
|
||||
'volume': vol,
|
||||
'url': b_url
|
||||
'host': parse.hostname
|
||||
}
|
||||
fake_volumes.append(stored_vol)
|
||||
resp.status_code = 202
|
||||
@ -66,17 +68,16 @@ def fake_volumes_forward_req(ctx, action, b_header, b_url, b_req_body):
|
||||
# resp.json = vol_dict
|
||||
return resp
|
||||
|
||||
pos = b_url.rfind('/volumes')
|
||||
b_path = parse.path
|
||||
pos = b_path.rfind('/volumes')
|
||||
op = ''
|
||||
cmp_url = b_url
|
||||
if pos > 0:
|
||||
op = b_url[pos:]
|
||||
cmp_url = b_url[:pos] + '/volumes'
|
||||
op = b_path[pos:]
|
||||
op = op[len('/volumes'):]
|
||||
|
||||
if action == 'GET':
|
||||
if op == '' or op == '/detail':
|
||||
tenant_id = b_url[:pos]
|
||||
tenant_id = b_path[:pos]
|
||||
pos2 = tenant_id.rfind('/')
|
||||
if pos2 > 0:
|
||||
tenant_id = tenant_id[(pos2 + 1):]
|
||||
@ -84,8 +85,9 @@ def fake_volumes_forward_req(ctx, action, b_header, b_url, b_req_body):
|
||||
resp.status_code = 404
|
||||
return resp
|
||||
ret_vols = []
|
||||
cmp_host = parse.hostname
|
||||
for temp_vol in fake_volumes:
|
||||
if temp_vol['url'] != cmp_url:
|
||||
if temp_vol['host'] != cmp_host:
|
||||
continue
|
||||
|
||||
if temp_vol['volume']['project_id'] == tenant_id:
|
||||
@ -210,6 +212,7 @@ class CinderVolumeFunctionalTest(base.TestCase):
|
||||
cfg.CONF.unregister_opts(app.common_opts)
|
||||
pecan.set_config({}, overwrite=True)
|
||||
core.ModelBase.metadata.drop_all(core.get_engine())
|
||||
del fake_volumes[:]
|
||||
|
||||
|
||||
class TestVolumeController(CinderVolumeFunctionalTest):
|
||||
@ -396,6 +399,96 @@ class TestVolumeController(CinderVolumeFunctionalTest):
|
||||
vols = json_body.get('volumes')
|
||||
self.assertEqual(0, len(vols))
|
||||
|
||||
@patch.object(hclient, 'forward_req',
|
||||
new=fake_volumes_forward_req)
|
||||
def test_get_all(self):
|
||||
update_dict = {'pod_az_name': 'fake_pod_az2'}
|
||||
# update pod2 to set pod_az_name
|
||||
db_api.update_pod(self.context, 'fake_pod_id2', update_dict)
|
||||
|
||||
volumes = [
|
||||
# normal volume with correct parameter
|
||||
{
|
||||
"volume":
|
||||
{
|
||||
"name": 'vol_1',
|
||||
"availability_zone": FAKE_AZ,
|
||||
"source_volid": '',
|
||||
"consistencygroup_id": '',
|
||||
"snapshot_id": '',
|
||||
"source_replica": '',
|
||||
"size": 10,
|
||||
"user_id": '',
|
||||
"imageRef": '',
|
||||
"attach_status": "detached",
|
||||
"volume_type": '',
|
||||
"project_id": 'my_tenant_id',
|
||||
"metadata": {}
|
||||
},
|
||||
"expected_error": 202
|
||||
},
|
||||
|
||||
# same tenant, multiple volumes
|
||||
{
|
||||
"volume":
|
||||
{
|
||||
"name": 'vol_2',
|
||||
"availability_zone": FAKE_AZ,
|
||||
"source_volid": '',
|
||||
"consistencygroup_id": '',
|
||||
"snapshot_id": '',
|
||||
"source_replica": '',
|
||||
"size": 20,
|
||||
"user_id": '',
|
||||
"imageRef": '',
|
||||
"attach_status": "detached",
|
||||
"volume_type": '',
|
||||
"project_id": 'my_tenant_id',
|
||||
"metadata": {}
|
||||
},
|
||||
"expected_error": 202
|
||||
},
|
||||
|
||||
# same tenant, different az
|
||||
{
|
||||
"volume":
|
||||
{
|
||||
"name": 'vol_3',
|
||||
"availability_zone": FAKE_AZ + '2',
|
||||
"source_volid": '',
|
||||
"consistencygroup_id": '',
|
||||
"snapshot_id": '',
|
||||
"source_replica": '',
|
||||
"size": 20,
|
||||
"user_id": '',
|
||||
"imageRef": '',
|
||||
"attach_status": "detached",
|
||||
"volume_type": '',
|
||||
"project_id": 'my_tenant_id',
|
||||
"metadata": {}
|
||||
},
|
||||
"expected_error": 202
|
||||
},
|
||||
]
|
||||
tenant_id = 'my_tenant_id'
|
||||
for volume in volumes:
|
||||
self.app.post_json('/v2/' + tenant_id + '/volumes',
|
||||
dict(volume=volume['volume']),
|
||||
expect_errors=True)
|
||||
query_string = '?availability_zone=' + FAKE_AZ
|
||||
resp = self.app.get('/v2/' + tenant_id + '/volumes' + query_string)
|
||||
self.assertEqual(resp.status_int, 200)
|
||||
json_body = jsonutils.loads(resp.body)
|
||||
ret_vols = json_body.get('volumes')
|
||||
self.assertEqual(len(ret_vols), 2)
|
||||
|
||||
query_string = '?availability_zone=' + FAKE_AZ + '2'
|
||||
resp = self.app.get('/v2/' + tenant_id + '/volumes' + query_string)
|
||||
self.assertEqual(resp.status_int, 200)
|
||||
json_body = jsonutils.loads(resp.body)
|
||||
ret_vols = json_body.get('volumes')
|
||||
self.assertEqual(len(ret_vols), 1)
|
||||
|
||||
def _test_and_check(self, volumes, tenant_id):
|
||||
for test_vol in volumes:
|
||||
if test_vol.get('volume'):
|
||||
|
Loading…
x
Reference in New Issue
Block a user