diff --git a/nova/api/ec2/apirequest.py b/nova/api/ec2/apirequest.py index 0854bd7bc50a..83a161ba713f 100644 --- a/nova/api/ec2/apirequest.py +++ b/nova/api/ec2/apirequest.py @@ -23,10 +23,12 @@ import datetime from xml.dom import minidom from lxml import etree +import six from nova.api.ec2 import ec2utils from nova import exception from nova.openstack.common import log as logging +from nova.openstack.common import strutils LOG = logging.getLogger(__name__) @@ -134,6 +136,7 @@ class APIRequest(object): data_el.appendChild( xml.createTextNode(_database_to_isoformat(data))) elif data is not None: - data_el.appendChild(xml.createTextNode(str(data))) + data_el.appendChild(xml.createTextNode( + strutils.safe_encode(six.text_type(data)))) return data_el diff --git a/nova/tests/api/ec2/test_apirequest.py b/nova/tests/api/ec2/test_apirequest.py new file mode 100644 index 000000000000..49048bfa23e3 --- /dev/null +++ b/nova/tests/api/ec2/test_apirequest.py @@ -0,0 +1,73 @@ +# Copyright 2014 Hewlett-Packard Development Company, L.P. +# +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""Unit tests for the API Request internals.""" + +import copy + +from nova.api.ec2 import apirequest +from nova import test + + +class APIRequestTestCase(test.NoDBTestCase): + + def setUp(self): + super(APIRequestTestCase, self).setUp() + self.req = apirequest.APIRequest("FakeController", "FakeAction", + "FakeVersion", {}) + self.resp = { + 'string': 'foo', + 'int': 1, + 'long': long(1), + 'bool': False, + 'dict': { + 'string': 'foo', + 'int': 1, + } + } + + # The previous will produce an output that looks like the + # following (excusing line wrap for 80 cols): + # + # + # uuid + # 1 + # + # 1 + # foo + # + # false + # foo + # + # + # We don't attempt to ever test for the full document because + # hash seed order might impact it's rendering order. The fact + # that running the function doesn't explode is a big part of + # the win. + + def test_render_response_ascii(self): + data = self.req._render_response(self.resp, 'uuid') + self.assertIn('