Implement volume update operation
Controller retrieves the routing entry according to the volume ID and sends updating request to the correct bottom pod. If controller gets a 404 error when updating the volume in the bottom pod, meaning that the bottom volume no longer exists, controller will remove the routing entry. Change-Id: I119b0ec31c869179c7c921245c9e06963aa6f866
This commit is contained in:
parent
7961f642ea
commit
e380fa85ae
@ -268,6 +268,73 @@ class VolumeController(rest.RestController):
|
|||||||
ret.extend(b_ret_body['volumes'])
|
ret.extend(b_ret_body['volumes'])
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
@expose(generic=True, template='json')
|
||||||
|
def put(self, _id, **kw):
|
||||||
|
context = t_context.extract_context_from_environ()
|
||||||
|
|
||||||
|
# TODO(joehuang): Implement API multi-version compatibility
|
||||||
|
# currently _convert_header and _convert_object are both dummy
|
||||||
|
# functions and API versions are hard coded. After multi-version
|
||||||
|
# compatibility is implemented, API versions will be retrieved from
|
||||||
|
# top and bottom API server, also, _convert_header and _convert_object
|
||||||
|
# will do the real job to convert the request header and body
|
||||||
|
# according to the API versions.
|
||||||
|
t_release = cons.R_MITAKA
|
||||||
|
b_release = cons.R_MITAKA
|
||||||
|
|
||||||
|
s_ctx = self._get_res_routing_ref(context, _id, request.url)
|
||||||
|
if not s_ctx:
|
||||||
|
return Response(_('Resource not found'), 404)
|
||||||
|
|
||||||
|
if s_ctx['b_url'] == '':
|
||||||
|
return Response(_('Bottom pod endpoint incorrect'), 404)
|
||||||
|
|
||||||
|
b_headers = self._convert_header(t_release,
|
||||||
|
b_release,
|
||||||
|
request.headers)
|
||||||
|
|
||||||
|
t_vol = kw['volume']
|
||||||
|
|
||||||
|
# add or remove key-value in the request for diff. version
|
||||||
|
b_vol_req = self._convert_object(t_release, b_release, t_vol,
|
||||||
|
res_type=cons.RT_VOLUME)
|
||||||
|
|
||||||
|
b_body = jsonutils.dumps({'volume': b_vol_req})
|
||||||
|
|
||||||
|
resp = hclient.forward_req(context, 'PUT',
|
||||||
|
b_headers,
|
||||||
|
s_ctx['b_url'],
|
||||||
|
b_body)
|
||||||
|
|
||||||
|
b_status = resp.status_code
|
||||||
|
b_ret_body = jsonutils.loads(resp.content)
|
||||||
|
response.status = b_status
|
||||||
|
|
||||||
|
if b_status == 200:
|
||||||
|
if b_ret_body.get('volume') is not None:
|
||||||
|
b_vol_ret = b_ret_body['volume']
|
||||||
|
ret_vol = self._convert_object(b_release, t_release,
|
||||||
|
b_vol_ret,
|
||||||
|
res_type=cons.RT_VOLUME)
|
||||||
|
|
||||||
|
pod = self._get_pod_by_top_id(context, _id)
|
||||||
|
if pod:
|
||||||
|
ret_vol['availability_zone'] = pod['az_name']
|
||||||
|
|
||||||
|
return {'volume': ret_vol}
|
||||||
|
|
||||||
|
# resource not found but routing exist, remove the routing
|
||||||
|
if b_status == 404:
|
||||||
|
filters = [{'key': 'top_id', 'comparator': 'eq', 'value': _id},
|
||||||
|
{'key': 'resource_type',
|
||||||
|
'comparator': 'eq',
|
||||||
|
'value': cons.RT_VOLUME}]
|
||||||
|
with context.session.begin():
|
||||||
|
core.delete_resources(context,
|
||||||
|
models.ResourceRouting,
|
||||||
|
filters)
|
||||||
|
return b_ret_body
|
||||||
|
|
||||||
@expose(generic=True, template='json')
|
@expose(generic=True, template='json')
|
||||||
def delete(self, _id):
|
def delete(self, _id):
|
||||||
context = t_context.extract_context_from_environ()
|
context = t_context.extract_context_from_environ()
|
||||||
|
@ -115,6 +115,19 @@ def fake_volumes_forward_req(ctx, action, b_header, b_url, b_req_body):
|
|||||||
fake_volumes.remove(vol)
|
fake_volumes.remove(vol)
|
||||||
resp.status_code = 202
|
resp.status_code = 202
|
||||||
return resp
|
return resp
|
||||||
|
if action == 'PUT':
|
||||||
|
b_body = jsonutils.loads(b_req_body)
|
||||||
|
update_vol = b_body.get('volume', {})
|
||||||
|
if op != '':
|
||||||
|
if op[0] == '/':
|
||||||
|
_id = op[1:]
|
||||||
|
for vol in fake_volumes:
|
||||||
|
if vol['volume']['id'] == _id:
|
||||||
|
vol['volume'].update(update_vol)
|
||||||
|
vol_dict = {'volume': vol['volume']}
|
||||||
|
resp._content = jsonutils.dumps(vol_dict)
|
||||||
|
resp.status_code = 200
|
||||||
|
return resp
|
||||||
else:
|
else:
|
||||||
resp.status_code = 404
|
resp.status_code = 404
|
||||||
|
|
||||||
@ -489,6 +502,44 @@ class TestVolumeController(CinderVolumeFunctionalTest):
|
|||||||
ret_vols = json_body.get('volumes')
|
ret_vols = json_body.get('volumes')
|
||||||
self.assertEqual(len(ret_vols), 1)
|
self.assertEqual(len(ret_vols), 1)
|
||||||
|
|
||||||
|
@patch.object(hclient, 'forward_req',
|
||||||
|
new=fake_volumes_forward_req)
|
||||||
|
def test_put(self):
|
||||||
|
volume = {
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
|
||||||
|
tenant_id = 'my_tenant_id'
|
||||||
|
resp = self.app.post_json('/v2/' + tenant_id + '/volumes',
|
||||||
|
dict(volume=volume['volume']),
|
||||||
|
expect_errors=True)
|
||||||
|
volume_dict = jsonutils.loads(resp.body)
|
||||||
|
volume_id = volume_dict['volume']['id']
|
||||||
|
|
||||||
|
update_dict = {"volume": {"name": 'vol_2'}}
|
||||||
|
resp = self.app.put_json('/v2/' + tenant_id + '/volumes/' + volume_id,
|
||||||
|
dict(volume=update_dict['volume']),
|
||||||
|
expect_errors=True)
|
||||||
|
volume_dict = jsonutils.loads(resp.body)
|
||||||
|
self.assertEqual(resp.status_int, 200)
|
||||||
|
self.assertEqual(volume_dict['volume']['name'], 'vol_2')
|
||||||
|
|
||||||
def _test_and_check(self, volumes, tenant_id):
|
def _test_and_check(self, volumes, tenant_id):
|
||||||
for test_vol in volumes:
|
for test_vol in volumes:
|
||||||
if test_vol.get('volume'):
|
if test_vol.get('volume'):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user