diff --git a/pyVmomi/SoapAdapter.py b/pyVmomi/SoapAdapter.py index f2380acd7..0bec26e7d 100644 --- a/pyVmomi/SoapAdapter.py +++ b/pyVmomi/SoapAdapter.py @@ -99,6 +99,11 @@ ## Localized MethodFault type LocalizedMethodFault = GetVmodlType("vmodl.LocalizedMethodFault") +def encode(string, encoding): + if PY2: + return string.encode(encoding) + return u(string) + ## Escape <, >, & def XmlEscape(xmlStr): escaped = xmlStr.replace("&", "&").replace(">", ">").replace("<", "<") @@ -316,7 +321,7 @@ def _Serialize(self, val, info, defNS): ns, name = GetQualifiedWsdlName(Type(val)) attr += ' type="{0}"'.format(name) self.writer.write('<{0}{1}>{2}'.format(info.name, attr, - val._moId.encode(self.encoding), + encode(val._moId, self.encoding), info.name)) elif isinstance(val, list): if info.type is object: @@ -399,7 +404,8 @@ def _Serialize(self, val, info, defNS): val = val.decode('UTF-8') result = XmlEscape(val) self.writer.write('<{0}{1}>{2}'.format(info.name, attr, - result.encode(self.encoding))) + encode(result, + self.encoding))) ## Serialize a a data object (internal) # @@ -576,7 +582,11 @@ def StartElementHandler(self, tag, attr): if not self.stack: if self.isFault: ns, name = self.SplitTag(tag) - objType = self.LookupWsdlType(ns, name[:-5]) + try: + objType = self.LookupWsdlType(ns, name[:-5]) + except KeyError: + message = "{0} was not found in the WSDL".format(name[:-5]) + raise VmomiMessageFault(message) # Only top level soap fault should be deserialized as method fault deserializeAsLocalizedMethodFault = False else: diff --git a/tests/fixtures/test_simple_request_serializer.yaml b/tests/fixtures/test_simple_request_serializer.yaml new file mode 100644 index 000000000..23df89432 --- /dev/null +++ b/tests/fixtures/test_simple_request_serializer.yaml @@ -0,0 +1,44 @@ +interactions: +- request: + body: ' + + + + <_this type="ServiceInstance">ServiceInstance + + ' + headers: + Accept-Encoding: ['gzip, deflate'] + Content-Type: [text/xml; charset=UTF-8] + Cookie: [''] + SOAPAction: ['"urn:vim2/2.0"'] + method: POST + uri: https://vcsa:443/sdk + response: + body: {string: "\n\n\ngroup-d1propertyCollectorVMware + vCenter ServerVMware vCenter Server 5.5.0 build-1750787 (Sim)VMware, + Inc.5.5.01750787 (Sim)INTL000linux-x64vpxVirtualCenter5.5VpxSettingsUserDirectorySessionManagerAuthorizationManagerPerfMgrScheduledTaskManagerAlarmManagerEventManagerTaskManagerCustomizationSpecManagerCustomFieldsManagerDiagMgrLicenseManagerSearchIndex\n\n"} + headers: + Cache-Control: [no-cache] + Connection: [Keep-Alive] + Content-Length: ['1948'] + Content-Type: [text/xml; charset=utf-8] + Date: ['Mon, 28 Jul 2014 22:02:17 GMT'] + Set-Cookie: ['vmware_soap_session="52d2bdd9-aec7-5f5c-652e-09737979ce13"; Path=/; + HttpOnly; Secure; '] + status: {code: 200, message: OK} +version: 1 diff --git a/tests/test_serializer.py b/tests/test_serializer.py new file mode 100644 index 000000000..c7c1bf4af --- /dev/null +++ b/tests/test_serializer.py @@ -0,0 +1,54 @@ +# VMware vSphere Python SDK +# Copyright (c) 2008-2014 VMware, Inc. 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. +from tests import fixtures_path +import unittest +import vcr + + +from pyVmomi import SoapStubAdapter +from pyVmomi import vim + +class SerializerTests(unittest.TestCase): + + def test_simple_request_serializer(self): + def request_matcher(r1, r2): + soap_msg = ('' + '' + '<_this type="ServiceInstance">' + 'ServiceInstance' + '' + '' + '') + if soap_msg in r1.body: + return True + raise SystemError('serialization error occurred') + + my_vcr = vcr.VCR() + my_vcr.register_matcher('request_matcher', request_matcher) + + with my_vcr.use_cassette( + 'test_simple_request_serializer.yaml', + cassette_library_dir=fixtures_path, + record_mode='none', + match_on=['request_matcher']) as cass: + host = 'vcsa' + port = 443 + stub = SoapStubAdapter(host, port) + si = vim.ServiceInstance("ServiceInstance", stub) + content = si.RetrieveContent() + self.assertTrue(content is not None) + self.assertTrue( + '<_this type="ServiceInstance">ServiceInstance' + in cass.requests[0].body) \ No newline at end of file