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['status'] = "available"
vol['attach_status'] = "detached"
vol['metadata'] = {"test_key": "test_val"}
volume = db.volume_create(self.context, vol)
snpshot = {
@@ -53,6 +54,7 @@ class VolumeRpcAPITestCase(test.TestCase):
'display_description': 'fake_description'}
snapshot = db.snapshot_create(self.context, snpshot)
self.fake_volume = jsonutils.to_primitive(volume)
self.fake_volume_metadata = volume["volume_metadata"]
self.fake_snapshot = jsonutils.to_primitive(snapshot)
def test_serialized_volume_has_id(self):
@@ -70,6 +72,11 @@ class VolumeRpcAPITestCase(test.TestCase):
expected_retval = 'foo' if method == 'call' else None
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)
if 'volume' in expected_msg['args']:
volume = expected_msg['args']['volume']
@@ -131,6 +138,20 @@ class VolumeRpcAPITestCase(test.TestCase):
source_volid='fake_src_id',
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):
self._test_volume_api('delete_volume',
rpc_method='cast',

View File

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