Skip to content

Commit

Permalink
Merge "Fix xml metadata for volumes api in nova-volume."
Browse files Browse the repository at this point in the history
  • Loading branch information
Jenkins authored and openstack-gerrit committed Sep 11, 2012
2 parents 93c7652 + 1f82e30 commit 511807e
Show file tree
Hide file tree
Showing 2 changed files with 181 additions and 9 deletions.
53 changes: 47 additions & 6 deletions nova/api/openstack/volume/volumes.py
Expand Up @@ -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
Expand Down Expand Up @@ -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'] = {}

Expand Down Expand Up @@ -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):
Expand All @@ -152,6 +151,47 @@ def construct(self):
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."""

Expand Down Expand Up @@ -210,6 +250,7 @@ def _items(self, req, entity_maker):
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']
Expand Down
137 changes: 134 additions & 3 deletions nova/tests/api/openstack/volume/test_volumes.py
Expand Up @@ -253,10 +253,10 @@ def _verify_volume(self, vol, tree):
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):
Expand Down Expand Up @@ -339,3 +339,134 @@ def test_volume_index_detail_serializer(self):
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)

0 comments on commit 511807e

Please sign in to comment.