Call to_primitive on volumes.rpcapi.create_volume

cinder.volume.rpcapi.create_volume does not convert the request_spec to
primitive before casting the request. This makes requests containing non
primitive types to fail. For example:

cinder create --metadata=Type=test --source-volid $VOLID 1

This will create a new database record and call create_volume on
volume.rpcapi.  This will fail because VolumeMetadata won't be
serialized correctly when calling cast. This, however, is not True when
--source-volid is not passed because in such case,
scheduler.rpcpai.create_volume will be called, which converts
request_spec to primitive correctly.

Closes-Bug: #1213964
Change-Id: I096d815254c9782390fba05ea9cd9af925635402
This commit is contained in:
Flaper Fesp
2013-09-04 13:29:22 +02:00
committed by Flavio Percoco
parent e7168b85e8
commit 587eb5a6b9
2 changed files with 25 additions and 1 deletions

View File

@@ -42,6 +42,7 @@ class VolumeRpcAPITestCase(test.TestCase):
vol['availability_zone'] = CONF.storage_availability_zone vol['availability_zone'] = CONF.storage_availability_zone
vol['status'] = "available" vol['status'] = "available"
vol['attach_status'] = "detached" vol['attach_status'] = "detached"
vol['metadata'] = {"test_key": "test_val"}
volume = db.volume_create(self.context, vol) volume = db.volume_create(self.context, vol)
snpshot = { snpshot = {
@@ -53,6 +54,7 @@ class VolumeRpcAPITestCase(test.TestCase):
'display_description': 'fake_description'} 'display_description': 'fake_description'}
snapshot = db.snapshot_create(self.context, snpshot) snapshot = db.snapshot_create(self.context, snpshot)
self.fake_volume = jsonutils.to_primitive(volume) self.fake_volume = jsonutils.to_primitive(volume)
self.fake_volume_metadata = volume["volume_metadata"]
self.fake_snapshot = jsonutils.to_primitive(snapshot) self.fake_snapshot = jsonutils.to_primitive(snapshot)
def test_serialized_volume_has_id(self): def test_serialized_volume_has_id(self):
@@ -70,6 +72,11 @@ class VolumeRpcAPITestCase(test.TestCase):
expected_retval = 'foo' if method == 'call' else None expected_retval = 'foo' if method == 'call' else None
expected_version = kwargs.pop('version', rpcapi.BASE_RPC_API_VERSION) expected_version = kwargs.pop('version', rpcapi.BASE_RPC_API_VERSION)
if 'request_spec' in kwargs:
spec = jsonutils.to_primitive(kwargs['request_spec'])
kwargs['request_spec'] = spec
expected_msg = rpcapi.make_msg(method, **kwargs) expected_msg = rpcapi.make_msg(method, **kwargs)
if 'volume' in expected_msg['args']: if 'volume' in expected_msg['args']:
volume = expected_msg['args']['volume'] volume = expected_msg['args']['volume']
@@ -131,6 +138,20 @@ class VolumeRpcAPITestCase(test.TestCase):
source_volid='fake_src_id', source_volid='fake_src_id',
version='1.4') version='1.4')
def test_create_volume_serialization(self):
request_spec = {"metadata": self.fake_volume_metadata}
self._test_volume_api('create_volume',
rpc_method='cast',
volume=self.fake_volume,
host='fake_host1',
request_spec=request_spec,
filter_properties='fake_properties',
allow_reschedule=True,
snapshot_id='fake_snapshot_id',
image_id='fake_image_id',
source_volid='fake_src_id',
version='1.4')
def test_delete_volume(self): def test_delete_volume(self):
self._test_volume_api('delete_volume', self._test_volume_api('delete_volume',
rpc_method='cast', rpc_method='cast',

View File

@@ -20,6 +20,7 @@ Client side of the volume RPC API.
from oslo.config import cfg from oslo.config import cfg
from cinder.openstack.common import jsonutils
from cinder.openstack.common import rpc from cinder.openstack.common import rpc
import cinder.openstack.common.rpc.proxy import cinder.openstack.common.rpc.proxy
@@ -61,10 +62,12 @@ class VolumeAPI(cinder.openstack.common.rpc.proxy.RpcProxy):
allow_reschedule=True, allow_reschedule=True,
snapshot_id=None, image_id=None, snapshot_id=None, image_id=None,
source_volid=None): source_volid=None):
request_spec_p = jsonutils.to_primitive(request_spec)
self.cast(ctxt, self.cast(ctxt,
self.make_msg('create_volume', self.make_msg('create_volume',
volume_id=volume['id'], volume_id=volume['id'],
request_spec=request_spec, request_spec=request_spec_p,
filter_properties=filter_properties, filter_properties=filter_properties,
allow_reschedule=allow_reschedule, allow_reschedule=allow_reschedule,
snapshot_id=snapshot_id, snapshot_id=snapshot_id,