Skip to content

Commit

Permalink
Merge pull request #398 from tianhao64/master
Browse files Browse the repository at this point in the history
Temporarily workaround issue #182 by creating dummy managed method
  • Loading branch information
tianhao64 committed Jun 15, 2016
2 parents 6be4fd1 + 0f4a4e5 commit db3774a
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 4 deletions.
5 changes: 4 additions & 1 deletion pyVmomi/SoapAdapter.py
Expand Up @@ -734,7 +734,10 @@ def EndElementHandler(self, tag):
# val in Method val is not namespace qualified
# However, this doesn't hurt to strip out namespace
ns, name = self.GetNSAndWsdlname(data)
obj = GuessWsdlMethod(name)
try:
obj = GuessWsdlMethod(name)
except KeyError:
obj = UncallableManagedMethod(name)
elif obj is bool:
if data == "0" or data.lower() == "false":
obj = bool(False)
Expand Down
32 changes: 29 additions & 3 deletions pyVmomi/VmomiSupport.py
Expand Up @@ -307,6 +307,8 @@ def FormatObject(val, info=Object(name="", type=object, flags=0), indent=0):
result = "(%s) []" % itemType.__name__
elif isinstance(val, type):
result = val.__name__
elif isinstance(val, UncallableManagedMethod):
result = val.name
elif isinstance(val, ManagedMethod):
result = '%s.%s' % (val.info.type.__name__, val.info.name)
elif isinstance(val, bool):
Expand Down Expand Up @@ -588,6 +590,15 @@ def __init__(self, info):
Curry.__init__(self, ManagedObject._InvokeMethod, info)
self.info = info

# Method used to represent any unknown wsdl method returned by server response.
# Server may return unknown method name due to server defects or newer version.
class UncallableManagedMethod(ManagedMethod):
def __init__(self, name):
self.name = name

def __call__(self, *args, **kwargs):
raise Exception("Managed method {} is not available".format(self.name))

## Create the vmodl.MethodFault type
#
# This type must be generated dynamically because it inherits from
Expand Down Expand Up @@ -1038,9 +1049,15 @@ class UnknownWsdlTypeError(KeyError):
# @return type if found in any one of the name spaces else throws KeyError
def GuessWsdlType(name):
with _lazyLock:
# Because the types are lazily loaded, if some name is present
# in multiple namespaces, we will load the first type that we
# encounter and return it.
# Some types may exist in multiple namespaces, and returning
# the wrong one will cause a deserialization error.
# Since in python3 the order of entries in set is not deterministic,
# we will try to get the type from vim25 namespace first.
try:
return GetWsdlType(XMLNS_VMODL_BASE, name)
except KeyError:
pass

for ns in _wsdlTypeMapNSs:
try:
return GetWsdlType(ns, name)
Expand Down Expand Up @@ -1231,6 +1248,15 @@ def GetWsdlMethod(ns, wsdlName):
# KeyError
def GuessWsdlMethod(name):
with _lazyLock:
# Some methods may exist in multiple namespaces, and returning
# the wrong one will cause a deserialization error.
# Since in python3 the order of entries in set is not deterministic,
# we will try to get the method from vim25 namespace first.
try:
return GetWsdlMethod(XMLNS_VMODL_BASE, name)
except KeyError:
pass

for ns in _wsdlMethodNSs:
try:
return GetWsdlMethod(ns, name)
Expand Down
78 changes: 78 additions & 0 deletions tests/files/unknown_method.xml
@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ReadNextTasksResponse xmlns="urn:vim25">
<returnval>
<key>task-3996443</key>
<task type="Task">task-3996443</task>
<description>
<key>com.vmware.vdp2.task.description</key>
<arg>
<key>workOrderId</key>
<value xsi:type="xsd:string">cp.20141020150650</value>
</arg>
</description>
<descriptionId>com.vmware.vdp2.integritycheck</descriptionId>
<entity type="VirtualMachine">vm-133364</entity>
<entityName>VDP3</entityName>
<state>running</state>
<cancelled>false</cancelled>
<cancelable>true</cancelable>
<reason xsi:type="TaskReasonUser">
<userName>vmware\\sa-vdp3</userName>
</reason>
<queueTime>2014-10-20T15:09:08.789999Z</queueTime>
<startTime>2014-10-20T15:09:09.073Z</startTime>
<eventChainId>21691195</eventChainId>
</returnval>
<returnval>
<key>task-1178117</key>
<task type="Task">task-1178117</task>
<descriptionId>com.vmware.vcIntegrity.CheckNotificationTask</descriptionId>
<entity type="Folder">group-d1</entity>
<entityName>Datacenters</entityName>
<state>queued</state>
<cancelled>false</cancelled>
<cancelable>true</cancelable>
<reason xsi:type="TaskReasonSchedule">
<name>VMware vSphere Update Manager Check Notification</name>
<scheduledTask type="ScheduledTask">schedule-2</scheduledTask>
</reason>
<queueTime>2013-01-08T14:12:01.556999Z</queueTime>
<eventChainId>3410272</eventChainId>
</returnval>
<returnval>
<key>task-746590</key>
<task type="Task">task-746590</task>
<name>LeaseMapDiskRegion</name>
<descriptionId>host.DiskManager.Lease.MapDiskRegion</descriptionId>
<entity type="VirtualMachine">vm-982</entity>
<entityName>Applicure</entityName>
<state>queued</state>
<cancelled>false</cancelled>
<cancelable>false</cancelable>
<reason xsi:type="TaskReasonUser">
<userName>VMWARE\\sa-veeam1</userName>
</reason>
<queueTime>2012-09-27T12:03:03.412999Z</queueTime>
<eventChainId>2325872</eventChainId>
</returnval>
<returnval>
<key>task-56327</key>
<task type="Task">task-56327</task>
<name>LeaseMapDiskRegion</name>
<descriptionId>host.DiskManager.Lease.MapDiskRegion</descriptionId>
<entity type="VirtualMachine">vm-1010</entity>
<entityName>vCD-Oracle</entityName>
<state>queued</state>
<cancelled>false</cancelled>
<cancelable>false</cancelable>
<reason xsi:type="TaskReasonUser">
<userName>VMWARE\\sa-veeam1</userName>
</reason>
<queueTime>2012-02-27T10:56:50.656999Z</queueTime>
<eventChainId>345916</eventChainId>
</returnval>
</ReadNextTasksResponse>
</soapenv:Body>
</soapenv:Envelope>
33 changes: 33 additions & 0 deletions tests/test_deserializer.py
@@ -0,0 +1,33 @@
# VMware vSphere Python SDK
# Copyright (c) 2016 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 pyVmomi import vim
from pyVmomi.SoapAdapter import SoapStubAdapter, SoapResponseDeserializer
import unittest


class DeserializerTests(unittest.TestCase):

def test_deserialize_unknown_managed_method(self):
with open('tests/files/unknown_method.xml', 'rb') as f:
data = f.read()
stub = SoapStubAdapter(version="vim.version.version6")
deserializer = SoapResponseDeserializer(stub)
result = vim.TaskHistoryCollector._GetMethodInfo("ReadNext").result
obj = deserializer.Deserialize(data, result)
print(obj)
with self.assertRaisesRegexp(Exception, "Managed method LeaseMapDiskRegion is not available"):
obj[-1].name()

0 comments on commit db3774a

Please sign in to comment.