Merge "Fix xml metadata for volumes api in nova-volume."
This commit is contained in:
commit
511807ed24
@ -17,6 +17,7 @@
|
||||
|
||||
import webob
|
||||
from webob import exc
|
||||
from xml.dom import minidom
|
||||
|
||||
from nova.api.openstack import common
|
||||
from nova.api.openstack import wsgi
|
||||
@ -100,10 +101,8 @@ def _translate_volume_summary_view(context, vol):
|
||||
LOG.audit(_("vol=%s"), vol, context=context)
|
||||
|
||||
if vol.get('volume_metadata'):
|
||||
meta_dict = {}
|
||||
for i in vol['volume_metadata']:
|
||||
meta_dict[i['key']] = i['value']
|
||||
d['metadata'] = meta_dict
|
||||
metadata = vol.get('volume_metadata')
|
||||
d['metadata'] = dict((item['key'], item['value']) for item in metadata)
|
||||
else:
|
||||
d['metadata'] = {}
|
||||
|
||||
@ -133,8 +132,8 @@ def make_volume(elem):
|
||||
selector='attachments')
|
||||
make_attachment(attachment)
|
||||
|
||||
metadata = xmlutil.make_flat_dict('metadata')
|
||||
elem.append(metadata)
|
||||
# Attach metadata node
|
||||
elem.append(common.MetadataTemplate())
|
||||
|
||||
|
||||
class VolumeTemplate(xmlutil.TemplateBuilder):
|
||||
@ -152,6 +151,47 @@ class VolumesTemplate(xmlutil.TemplateBuilder):
|
||||
return xmlutil.MasterTemplate(root, 1)
|
||||
|
||||
|
||||
class CommonDeserializer(wsgi.MetadataXMLDeserializer):
|
||||
"""Common deserializer to handle xml-formatted volume requests.
|
||||
|
||||
Handles standard volume attributes as well as the optional metadata
|
||||
attribute
|
||||
"""
|
||||
|
||||
metadata_deserializer = common.MetadataXMLDeserializer()
|
||||
|
||||
def _extract_volume(self, node):
|
||||
"""Marshal the volume attribute of a parsed request."""
|
||||
volume = {}
|
||||
volume_node = self.find_first_child_named(node, 'volume')
|
||||
|
||||
attributes = ['display_name', 'display_description', 'size',
|
||||
'volume_type', 'availability_zone']
|
||||
for attr in attributes:
|
||||
if volume_node.getAttribute(attr):
|
||||
volume[attr] = volume_node.getAttribute(attr)
|
||||
|
||||
metadata_node = self.find_first_child_named(volume_node, 'metadata')
|
||||
if metadata_node is not None:
|
||||
volume['metadata'] = self.extract_metadata(metadata_node)
|
||||
|
||||
return volume
|
||||
|
||||
|
||||
class CreateDeserializer(CommonDeserializer):
|
||||
"""Deserializer to handle xml-formatted create volume requests.
|
||||
|
||||
Handles standard volume attributes as well as the optional metadata
|
||||
attribute
|
||||
"""
|
||||
|
||||
def default(self, string):
|
||||
"""Deserialize an xml-formatted volume create request."""
|
||||
dom = minidom.parseString(string)
|
||||
volume = self._extract_volume(dom)
|
||||
return {'body': {'volume': volume}}
|
||||
|
||||
|
||||
class VolumeController(object):
|
||||
"""The Volumes API controller for the OpenStack API."""
|
||||
|
||||
@ -210,6 +250,7 @@ class VolumeController(object):
|
||||
return {'volumes': res}
|
||||
|
||||
@wsgi.serializers(xml=VolumeTemplate)
|
||||
@wsgi.deserializers(xml=CreateDeserializer)
|
||||
def create(self, req, body):
|
||||
"""Creates a new volume."""
|
||||
context = req.environ['nova.context']
|
||||
|
@ -253,10 +253,10 @@ class VolumeSerializerTest(test.TestCase):
|
||||
elif child.tag == 'metadata':
|
||||
not_seen = set(vol['metadata'].keys())
|
||||
for gr_child in child:
|
||||
self.assertTrue(gr_child.tag in not_seen)
|
||||
self.assertEqual(str(vol['metadata'][gr_child.tag]),
|
||||
self.assertTrue(gr_child.get("key") in not_seen)
|
||||
self.assertEqual(str(vol['metadata'][gr_child.get("key")]),
|
||||
gr_child.text)
|
||||
not_seen.remove(gr_child.tag)
|
||||
not_seen.remove(gr_child.get("key"))
|
||||
self.assertEqual(0, len(not_seen))
|
||||
|
||||
def test_volume_show_create_serializer(self):
|
||||
@ -339,3 +339,134 @@ class VolumeSerializerTest(test.TestCase):
|
||||
self.assertEqual(len(raw_volumes), len(tree))
|
||||
for idx, child in enumerate(tree):
|
||||
self._verify_volume(raw_volumes[idx], child)
|
||||
|
||||
|
||||
class TestVolumeCreateRequestXMLDeserializer(test.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestVolumeCreateRequestXMLDeserializer, self).setUp()
|
||||
self.deserializer = volumes.CreateDeserializer()
|
||||
|
||||
def test_minimal_volume(self):
|
||||
self_request = """
|
||||
<volume xmlns="http://docs.openstack.org/compute/api/v1.1"
|
||||
size="1"></volume>"""
|
||||
request = self.deserializer.deserialize(self_request)
|
||||
expected = {
|
||||
"volume": {
|
||||
"size": "1",
|
||||
},
|
||||
}
|
||||
self.assertEquals(request['body'], expected)
|
||||
|
||||
def test_display_name(self):
|
||||
self_request = """
|
||||
<volume xmlns="http://docs.openstack.org/compute/api/v1.1"
|
||||
size="1"
|
||||
display_name="Volume-xml"></volume>"""
|
||||
request = self.deserializer.deserialize(self_request)
|
||||
expected = {
|
||||
"volume": {
|
||||
"size": "1",
|
||||
"display_name": "Volume-xml",
|
||||
},
|
||||
}
|
||||
self.assertEquals(request['body'], expected)
|
||||
|
||||
def test_display_description(self):
|
||||
self_request = """
|
||||
<volume xmlns="http://docs.openstack.org/compute/api/v1.1"
|
||||
size="1"
|
||||
display_name="Volume-xml"
|
||||
display_description="description"></volume>"""
|
||||
request = self.deserializer.deserialize(self_request)
|
||||
expected = {
|
||||
"volume": {
|
||||
"size": "1",
|
||||
"display_name": "Volume-xml",
|
||||
"display_description": "description",
|
||||
},
|
||||
}
|
||||
self.assertEquals(request['body'], expected)
|
||||
|
||||
def test_volume_type(self):
|
||||
self_request = """
|
||||
<volume xmlns="http://docs.openstack.org/compute/api/v1.1"
|
||||
size="1"
|
||||
display_name="Volume-xml"
|
||||
display_description="description"
|
||||
volume_type="289da7f8-6440-407c-9fb4-7db01ec49164"></volume>"""
|
||||
request = self.deserializer.deserialize(self_request)
|
||||
expected = {
|
||||
"volume": {
|
||||
"display_name": "Volume-xml",
|
||||
"size": "1",
|
||||
"display_name": "Volume-xml",
|
||||
"display_description": "description",
|
||||
"volume_type": "289da7f8-6440-407c-9fb4-7db01ec49164",
|
||||
},
|
||||
}
|
||||
self.assertEquals(request['body'], expected)
|
||||
|
||||
def test_availability_zone(self):
|
||||
self_request = """
|
||||
<volume xmlns="http://docs.openstack.org/compute/api/v1.1"
|
||||
size="1"
|
||||
display_name="Volume-xml"
|
||||
display_description="description"
|
||||
volume_type="289da7f8-6440-407c-9fb4-7db01ec49164"
|
||||
availability_zone="us-east1"></volume>"""
|
||||
request = self.deserializer.deserialize(self_request)
|
||||
expected = {
|
||||
"volume": {
|
||||
"size": "1",
|
||||
"display_name": "Volume-xml",
|
||||
"display_description": "description",
|
||||
"volume_type": "289da7f8-6440-407c-9fb4-7db01ec49164",
|
||||
"availability_zone": "us-east1",
|
||||
},
|
||||
}
|
||||
self.assertEquals(request['body'], expected)
|
||||
|
||||
def test_metadata(self):
|
||||
self_request = """
|
||||
<volume xmlns="http://docs.openstack.org/compute/api/v1.1"
|
||||
display_name="Volume-xml"
|
||||
size="1">
|
||||
<metadata><meta key="Type">work</meta></metadata></volume>"""
|
||||
request = self.deserializer.deserialize(self_request)
|
||||
expected = {
|
||||
"volume": {
|
||||
"display_name": "Volume-xml",
|
||||
"size": "1",
|
||||
"metadata": {
|
||||
"Type": "work",
|
||||
},
|
||||
},
|
||||
}
|
||||
self.assertEquals(request['body'], expected)
|
||||
|
||||
def test_full_volume(self):
|
||||
self_request = """
|
||||
<volume xmlns="http://docs.openstack.org/compute/api/v1.1"
|
||||
size="1"
|
||||
display_name="Volume-xml"
|
||||
display_description="description"
|
||||
volume_type="289da7f8-6440-407c-9fb4-7db01ec49164"
|
||||
availability_zone="us-east1">
|
||||
<metadata><meta key="Type">work</meta></metadata></volume>"""
|
||||
request = self.deserializer.deserialize(self_request)
|
||||
expected = {
|
||||
"volume": {
|
||||
"size": "1",
|
||||
"display_name": "Volume-xml",
|
||||
"display_description": "description",
|
||||
"volume_type": "289da7f8-6440-407c-9fb4-7db01ec49164",
|
||||
"availability_zone": "us-east1",
|
||||
"metadata": {
|
||||
"Type": "work",
|
||||
},
|
||||
},
|
||||
}
|
||||
self.maxDiff = None
|
||||
self.assertEquals(request['body'], expected)
|
||||
|
Loading…
x
Reference in New Issue
Block a user