Merge "Add XML deserializer for qos_manage delete_keys API"

This commit is contained in:
Jenkins 2014-06-18 16:04:25 +00:00 committed by Gerrit Code Review
commit 15aeee5026
6 changed files with 163 additions and 0 deletions

View File

@ -26,6 +26,7 @@ from cinder import exception
from cinder.openstack.common import log as logging from cinder.openstack.common import log as logging
from cinder.openstack.common import strutils from cinder.openstack.common import strutils
from cinder import rpc from cinder import rpc
from cinder import utils
from cinder.volume import qos_specs from cinder.volume import qos_specs
@ -61,6 +62,26 @@ class QoSSpecsTemplate(xmlutil.TemplateBuilder):
return xmlutil.MasterTemplate(root, 1) return xmlutil.MasterTemplate(root, 1)
class QoSSpecsKeyDeserializer(wsgi.XMLDeserializer):
def _extract_keys(self, key_node):
keys = []
for key in key_node.childNodes:
key_name = key.tagName
keys.append(key_name)
return keys
def default(self, string):
dom = utils.safe_minidom_parse_string(string)
key_node = self.find_first_child_named(dom, 'keys')
if not key_node:
LOG.info(_("Unable to parse XML input."))
msg = _("Unable to parse XML request. "
"Please provide XML in correct format.")
raise webob.exc.HTTPBadRequest(explanation=msg)
return {'body': {'keys': self._extract_keys(key_node)}}
class AssociationsTemplate(xmlutil.TemplateBuilder): class AssociationsTemplate(xmlutil.TemplateBuilder):
def construct(self): def construct(self):
root = xmlutil.TemplateElement('qos_associations') root = xmlutil.TemplateElement('qos_associations')
@ -225,6 +246,7 @@ class QoSSpecsController(wsgi.Controller):
return webob.Response(status_int=202) return webob.Response(status_int=202)
@wsgi.deserializers(xml=QoSSpecsKeyDeserializer)
def delete_keys(self, req, id, body): def delete_keys(self, req, id, body):
"""Deletes specified keys in qos specs.""" """Deletes specified keys in qos specs."""
context = req.environ['cinder.context'] context = req.environ['cinder.context']

View File

@ -0,0 +1,8 @@
<element name="associations" xmlns="http://relaxng.org/ns/structure/1.0">
<attribute name="name"> <text/> </attribute>
<attribute name="id"> <text/> </attribute>
<attribute name="association_type"> <text/> </attribute>
<zeroOrMore>
<externalRef href="../atom-link.rng"/>
</zeroOrMore>
</element>

View File

@ -0,0 +1,5 @@
<element name="qos_associations" xmlns="http://relaxng.org/ns/structure/1.0">
<zeroOrMore>
<externalRef href="qos_association.rng"/>
</zeroOrMore>
</element>

View File

@ -0,0 +1,16 @@
<element name="qos_spec" xmlns="http://relaxng.org/ns/structure/1.0">
<attribute name="name"> <text/> </attribute>
<attribute name="id"> <text/> </attribute>
<attribute name="consumer"> <text/> </attribute>
<element name="specs">
<zeroOrMore>
<element>
<anyName/>
<text/>
</element>
</zeroOrMore>
</element>
<zeroOrMore>
<externalRef href="../atom-link.rng"/>
</zeroOrMore>
</element>

View File

@ -0,0 +1,5 @@
<element name="qos_specs" xmlns="http://relaxng.org/ns/structure/1.0">
<zeroOrMore>
<externalRef href="qos_spec.rng"/>
</zeroOrMore>
</element>

View File

@ -14,11 +14,13 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from lxml import etree
from xml.dom import minidom from xml.dom import minidom
import webob import webob
from cinder.api.contrib import qos_specs_manage from cinder.api.contrib import qos_specs_manage
from cinder.api import xmlutil
from cinder import exception from cinder import exception
from cinder import test from cinder import test
from cinder.tests.api import fakes from cinder.tests.api import fakes
@ -598,3 +600,108 @@ class QoSSpecManageApiTest(test.TestCase):
'/v2/fake/qos-specs/222/disassociate_all') '/v2/fake/qos-specs/222/disassociate_all')
self.assertRaises(webob.exc.HTTPInternalServerError, self.assertRaises(webob.exc.HTTPInternalServerError,
self.controller.disassociate_all, req, '222') self.controller.disassociate_all, req, '222')
class TestQoSSpecsTemplate(test.TestCase):
def setUp(self):
super(TestQoSSpecsTemplate, self).setUp()
self.serializer = qos_specs_manage.QoSSpecsTemplate()
def test_qos_specs_serializer(self):
fixture = {
"qos_specs": [
{
"specs": {
"key1": "v1",
"key2": "v2",
},
"consumer": "back-end",
"name": "qos-2",
"id": "61e7b72f-ef15-46d9-b00e-b80f699999d0"
},
{
"specs": {"total_iops_sec": "200"},
"consumer": "front-end",
"name": "qos-1",
"id": "e44bba5e-b629-4b96-9aa3-0404753a619b"
}
]
}
output = self.serializer.serialize(fixture)
root = etree.XML(output)
xmlutil.validate_schema(root, 'qos_specs')
qos_elems = root.findall("qos_spec")
self.assertEqual(len(qos_elems), 2)
for i, qos_elem in enumerate(qos_elems):
qos_dict = fixture['qos_specs'][i]
# check qos_spec attributes
for key in ['name', 'id', 'consumer']:
self.assertEqual(qos_elem.get(key), str(qos_dict[key]))
# check specs
specs = qos_elem.find("specs")
new_dict = {}
for element in specs.iter(tag=etree.Element):
# skip root element for specs
if element.tag == "specs":
continue
new_dict.update({element.tag: element.text})
self.assertDictMatch(new_dict, qos_dict['specs'])
class TestAssociationsTemplate(test.TestCase):
def setUp(self):
super(TestAssociationsTemplate, self).setUp()
self.serializer = qos_specs_manage.AssociationsTemplate()
def test_qos_associations_serializer(self):
fixture = {
"qos_associations": [
{
"association_type": "volume_type",
"name": "type-4",
"id": "14d54d29-51a4-4046-9f6f-cf9800323563"
},
{
"association_type": "volume_type",
"name": "type-2",
"id": "3689ce83-308d-4ba1-8faf-7f1be04a282b"}
]
}
output = self.serializer.serialize(fixture)
root = etree.XML(output)
xmlutil.validate_schema(root, 'qos_associations')
association_elems = root.findall("associations")
self.assertEqual(len(association_elems), 2)
for i, association_elem in enumerate(association_elems):
association_dict = fixture['qos_associations'][i]
# check qos_spec attributes
for key in ['name', 'id', 'association_type']:
self.assertEqual(association_elem.get(key),
str(association_dict[key]))
class TestQoSSpecsKeyDeserializer(test.TestCase):
def setUp(self):
super(TestQoSSpecsKeyDeserializer, self).setUp()
self.deserializer = qos_specs_manage.QoSSpecsKeyDeserializer()
def test_keys(self):
self_request = """
<keys><xyz /><abc /></keys>"""
request = self.deserializer.deserialize(self_request)
expected = {
"keys": ["xyz", "abc"]
}
self.assertEqual(request['body'], expected)
def test_bad_format(self):
self_request = """
<qos_specs><keys><xyz /><abc /></keys></qos_specs>"""
self.assertRaises(webob.exc.HTTPBadRequest,
self.deserializer.deserialize, self_request)