def test_xml_root_key_is_list(self): input_dict = {'servers': ['test-pass']} serializer = wsgi.XMLDictSerializer(xmlns="fake") result = serializer.default(input_dict) result = result.replace('\n', '').replace(' ', '') expected = ('<?xmlversion=\'1.0\'encoding=\'UTF-8\'?>' '<serversxmlns="fake"xmlns:quantum="fake"' 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' '<server>test-pass</server></servers>') self.assertEqual(result, expected)
def test_xml_with_unicode(self): data = {'servers': u'\u7f51\u7edc'} serializer = wsgi.XMLDictSerializer() expected = ('<?xmlversion=\'1.0\'encoding=\'UTF-8\'?>' '<serversxmlns="http://openstack.org/quantum/api/v2.0"' 'xmlns:quantum="http://openstack.org/quantum/api/v2.0"' 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' '\xe7\xbd\x91\xe7\xbb\x9c</servers>') result = serializer(data) result = result.replace('\n', '').replace(' ', '') self.assertEqual(expected, result)
def test_call(self): data = {'servers': {'a': {'2': '3'}}} serializer = wsgi.XMLDictSerializer() expected = ('<?xmlversion=\'1.0\'encoding=\'UTF-8\'?>' '<serversxmlns="http://openstack.org/quantum/api/v2.0"' 'xmlns:quantum="http://openstack.org/quantum/api/v2.0"' 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' '<a><2>3</2></a></servers>') result = serializer(data) result = result.replace('\n', '').replace(' ', '') self.assertEqual(expected, result)
def test_xml_meta_contains_node_name_list(self): input_dict = {'servers': ['test-pass']} servers = {'nodename': 'test', 'item_name': 'test', 'item_key': 'test'} metadata = {'list_collections': {'servers': servers}} serializer = wsgi.XMLDictSerializer(xmlns="fake", metadata=metadata) result = serializer.default(input_dict) result = result.replace('\n', '').replace(' ', '') expected = ('<?xmlversion=\'1.0\'encoding=\'UTF-8\'?>' '<serversxmlns="fake"xmlns:quantum="fake"' 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' '<server>test-pass</server></servers>') self.assertEqual(result, expected)
def test_non_root_one_item_dic_xml(self): data = {'test1': 1} # We have a key in this dict, and its value is an integer. # XML is: # <test1 quantum:type="int" # xmlns="http://openstack.org/quantum/api/v2.0" # xmlns:quantum="http://openstack.org/quantum/api/v2.0" # xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> # 1</test1> serializer = wsgi.XMLDictSerializer(attributes.get_attr_metadata()) result = serializer.serialize(data) deserializer = wsgi.XMLDeserializer(attributes.get_attr_metadata()) new_data = deserializer.deserialize(result)['body'] self.assertEqual(data, new_data)
def test_empty_dic_xml(self): data = {} # Since it is an empty dict, we use quantum:type='dict' and # an empty XML element to represent it. In addition, we use an # virtual XML root _v_root to wrap the XML doc. # XML is: # <_v_root quantum:type="dict" # xmlns="http://openstack.org/quantum/api/v2.0" # xmlns:quantum="http://openstack.org/quantum/api/v2.0" # xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" /> serializer = wsgi.XMLDictSerializer(attributes.get_attr_metadata()) result = serializer.serialize(data) deserializer = wsgi.XMLDeserializer(attributes.get_attr_metadata()) new_data = deserializer.deserialize(result)['body'] self.assertEqual(data, new_data)
def test_None(self): data = None # Since it is None, we use xsi:nil='true'. # In addition, we use an # virtual XML root _v_root to wrap the XML doc. # XML is: # <_v_root xsi:nil="true" # xmlns="http://openstack.org/quantum/api/v2.0" # xmlns:quantum="http://openstack.org/quantum/api/v2.0" # xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" /> serializer = wsgi.XMLDictSerializer(attributes.get_attr_metadata()) result = serializer.serialize(data) deserializer = wsgi.XMLDeserializer(attributes.get_attr_metadata()) new_data = deserializer.deserialize(result)['body'] self.assertIsNone(new_data)
def test_non_root_two_items_dic_xml(self): data = {'test1': 1, 'test2': '2'} # We have no root element in this data, We will use a virtual # root element _v_root to wrap the doct. # The XML is: # <_v_root xmlns="http://openstack.org/quantum/api/v2.0" # xmlns:quantum="http://openstack.org/quantum/api/v2.0" # xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> # <test1 quantum:type="int">1</test1><test2>2</test2> # </_v_root> serializer = wsgi.XMLDictSerializer(attributes.get_attr_metadata()) result = serializer.serialize(data) deserializer = wsgi.XMLDeserializer(attributes.get_attr_metadata()) new_data = deserializer.deserialize(result)['body'] self.assertEqual(data, new_data)
def create_resource(version, controller_dict): """ Generic function for creating a wsgi resource The function takes as input: - desired version - controller and metadata dictionary e.g.: {'1.0': [ctrl_v10, meta_v10, xml_ns], '1.1': [ctrl_v11, meta_v11, xml_ns]} """ # the first element of the iterable is expected to be the controller controller = controller_dict[version][0] # the second element should be the metadata metadata = controller_dict[version][1] # and the third element the xml namespace xmlns = controller_dict[version][2] # and also the function for building the fault body fault_body_function = faults.fault_body_function(version) headers_serializers = { '1.0': HeaderSerializer10(), '1.1': HeaderSerializer11() } xml_serializer = wsgi.XMLDictSerializer(metadata, xmlns) json_serializer = wsgi.JSONDictSerializer() xml_deserializer = wsgi.XMLDeserializer(metadata) json_deserializer = wsgi.JSONDeserializer() body_serializers = { 'application/xml': xml_serializer, 'application/json': json_serializer, } body_deserializers = { 'application/xml': xml_deserializer, 'application/json': json_deserializer, } serializer = wsgi.ResponseSerializer(body_serializers, headers_serializers[version]) deserializer = wsgi.RequestDeserializer(body_deserializers) return wsgi.Resource(controller, fault_body_function, deserializer, serializer)
def Resource(controller, faults=None, deserializers=None, serializers=None): """Represents an API entity resource and the associated serialization and deserialization logic """ xml_deserializer = wsgi.XMLDeserializer(attributes.get_attr_metadata()) default_deserializers = {'application/xml': xml_deserializer, 'application/json': wsgi.JSONDeserializer()} xml_serializer = wsgi.XMLDictSerializer(attributes.get_attr_metadata()) default_serializers = {'application/xml': xml_serializer, 'application/json': wsgi.JSONDictSerializer()} format_types = {'xml': 'application/xml', 'json': 'application/json'} action_status = dict(create=201, delete=204) default_deserializers.update(deserializers or {}) default_serializers.update(serializers or {}) deserializers = default_deserializers serializers = default_serializers faults = faults or {} @webob.dec.wsgify(RequestClass=Request) def resource(request): route_args = request.environ.get('wsgiorg.routing_args') if route_args: args = route_args[1].copy() else: args = {} # NOTE(jkoelker) by now the controller is already found, remove # it from the args if it is in the matchdict args.pop('controller', None) fmt = args.pop('format', None) action = args.pop('action', None) content_type = format_types.get(fmt, request.best_match_content_type()) deserializer = deserializers.get(content_type) serializer = serializers.get(content_type) try: if request.body: args['body'] = deserializer.deserialize(request.body)['body'] method = getattr(controller, action) result = method(request=request, **args) except (exceptions.QuantumException, netaddr.AddrFormatError) as e: LOG.exception(_('%s failed'), action) body = serializer.serialize({'QuantumError': e}) kwargs = {'body': body, 'content_type': content_type} for fault in faults: if isinstance(e, fault): raise faults[fault](**kwargs) raise webob.exc.HTTPInternalServerError(**kwargs) except webob.exc.HTTPException as e: LOG.exception(_('%s failed'), action) e.body = serializer.serialize({'QuantumError': e}) e.content_type = content_type raise except Exception as e: # NOTE(jkoelker) Everyting else is 500 LOG.exception(_('%s failed'), action) # Do not expose details of 500 error to clients. msg = _('Request Failed: internal server error while ' 'processing your request.') body = serializer.serialize({'QuantumError': msg}) kwargs = {'body': body, 'content_type': content_type} raise webob.exc.HTTPInternalServerError(**kwargs) status = action_status.get(action, 200) body = serializer.serialize(result) # NOTE(jkoelker) Comply with RFC2616 section 9.7 if status == 204: content_type = '' body = None return webob.Response(request=request, status=status, content_type=content_type, body=body) return resource
# <test xsi:nil="true" /> # None # <tenant_id>test-tenant</tenant_id> # # We must have a namespace defined in root for prefix:external # <prefix:external quantum:type="bool">True</prefix:external> # <tests> # List # <test><test1>value1</test1></test> # <test><test3 quantum:type="int">3</test3> # <test2 quantum:type="int">2</test2> # </test></tests> # </network> metadata = attributes.get_attr_metadata() ns = {'prefix': 'http://xxxx.yy.com'} metadata[constants.EXT_NS] = ns metadata['plurals'] = {'tests': 'test'} serializer = wsgi.XMLDictSerializer(metadata) result = serializer.serialize(NETWORK) deserializer = wsgi.XMLDeserializer(metadata) new_net = deserializer.deserialize(result)['body'] self.assertEqual(NETWORK, new_net) def test_None(self): data = None # Since it is None, we use xsi:nil='true'. # In addition, we use an # virtual XML root _v_root to wrap the XML doc. # XML is: # <_v_root xsi:nil="true" # xmlns="http://openstack.org/quantum/api/v2.0" # xmlns:quantum="http://openstack.org/quantum/api/v2.0" # xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
def Resource(controller, faults=None, deserializers=None, serializers=None): """Represents an API entity resource and the associated serialization and deserialization logic """ default_deserializers = { 'application/xml': wsgi.XMLDeserializer(), 'application/json': lambda x: json.loads(x) } default_serializers = { 'application/xml': wsgi.XMLDictSerializer(), 'application/json': lambda x: json.dumps(x) } format_types = {'xml': 'application/xml', 'json': 'application/json'} action_status = dict(create=201, delete=204) default_deserializers.update(deserializers or {}) default_serializers.update(serializers or {}) deserializers = default_deserializers serializers = default_serializers faults = faults or {} @webob.dec.wsgify(RequestClass=Request) def resource(request): route_args = request.environ.get('wsgiorg.routing_args') if route_args: args = route_args[1].copy() else: args = {} # NOTE(jkoelker) by now the controller is already found, remove # it from the args if it is in the matchdict args.pop('controller', None) fmt = args.pop('format', None) action = args.pop('action', None) content_type = format_types.get(fmt, request.best_match_content_type()) deserializer = deserializers.get(content_type) serializer = serializers.get(content_type) try: if request.body: args['body'] = deserializer(request.body) method = getattr(controller, action) result = method(request=request, **args) except exceptions.QuantumException as e: LOG.exception('%s failed' % action) body = serializer({'QuantumError': str(e)}) kwargs = {'body': body, 'content_type': content_type} for fault in faults: if isinstance(e, fault): raise faults[fault](**kwargs) raise webob.exc.HTTPInternalServerError(**kwargs) except webob.exc.HTTPException as e: LOG.exception('%s failed' % action) e.body = serializer({'QuantumError': str(e)}) e.content_type = content_type raise except Exception as e: # NOTE(jkoelker) Everyting else is 500 LOG.exception('%s failed' % action) body = serializer({'QuantumError': str(e)}) kwargs = {'body': body, 'content_type': content_type} raise webob.exc.HTTPInternalServerError(**kwargs) status = action_status.get(action, 200) body = serializer(result) # NOTE(jkoelker) Comply with RFC2616 section 9.7 if status == 204: content_type = '' body = None return webob.Response(request=request, status=status, content_type=content_type, body=body) return resource