This is the initial version of pyVmomi which represents vSphere API 5.1. Going forward, expect only the 'Objects' and 'Types' generated source files to need updating via official OSS drops.
230 lines
8.9 KiB
Python
230 lines
8.9 KiB
Python
# VMware vSphere Python SDK
|
|
# Copyright (c) 2008-2013 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.
|
|
|
|
## Diff any two objects
|
|
|
|
from pyVmomi import VmomiSupport, types
|
|
import itertools
|
|
import logging
|
|
from VmomiSupport import GetWsdlName, Type
|
|
|
|
__Log__ = logging.getLogger('ObjDiffer')
|
|
|
|
def LogIf(condition, message):
|
|
"""Log a message if the condition is met"""
|
|
if condition:
|
|
__Log__.debug(message)
|
|
|
|
def IsPrimitiveType(obj):
|
|
"""See if the passed in type is a Primitive Type"""
|
|
return (isinstance(obj, types.bool) or isinstance(obj, types.byte) or
|
|
isinstance(obj, types.short) or isinstance(obj, types.int) or
|
|
isinstance(obj, types.double) or isinstance(obj, types.float) or
|
|
isinstance(obj, types.long) or isinstance(obj, types.str) or
|
|
isinstance(obj, unicode) or
|
|
isinstance(obj, types.PropertyPath) or
|
|
isinstance(obj, types.ManagedMethod) or
|
|
isinstance(obj, types.datetime) or
|
|
isinstance(obj, types.URI) or isinstance(obj, type))
|
|
|
|
|
|
class Differ:
|
|
"""Class for comparing two Objects"""
|
|
def __init__(self, looseMatch=False, ignoreArrayOrder=True):
|
|
self._looseMatch = looseMatch
|
|
self._ignoreArrayOrder = ignoreArrayOrder
|
|
|
|
def DiffAnyObjects(self, oldObj, newObj, isObjLink=False):
|
|
"""Diff any two Objects"""
|
|
if oldObj == newObj:
|
|
return True
|
|
if not oldObj or not newObj:
|
|
__Log__.debug('DiffAnyObjects: One of the objects is unset.')
|
|
return self._looseMatch
|
|
oldObjInstance = oldObj
|
|
newObjInstance = newObj
|
|
if isinstance(oldObj, list):
|
|
oldObjInstance = oldObj[0]
|
|
if isinstance(newObj, list):
|
|
newObjInstance = newObj[0]
|
|
# Need to see if it is a primitive type first since type information
|
|
# will not be available for them.
|
|
if (IsPrimitiveType(oldObj) and IsPrimitiveType(newObj)
|
|
and oldObj.__class__.__name__ == newObj.__class__.__name__):
|
|
if oldObj == newObj:
|
|
return True
|
|
elif oldObj == None or newObj == None:
|
|
__Log__.debug('DiffAnyObjects: One of the objects in None')
|
|
return False
|
|
oldType = Type(oldObjInstance)
|
|
newType = Type(newObjInstance)
|
|
if oldType != newType:
|
|
__Log__.debug('DiffAnyObjects: Types do not match %s != %s' %
|
|
(repr(GetWsdlName(oldObjInstance.__class__)),
|
|
repr(GetWsdlName(newObjInstance.__class__))))
|
|
return False
|
|
elif isinstance(oldObj, list):
|
|
return self.DiffArrayObjects(oldObj, newObj, isObjLink)
|
|
elif isinstance(oldObjInstance, types.ManagedObject):
|
|
return (not oldObj and not newObj) or (oldObj and newObj
|
|
and oldObj._moId == newObj._moId)
|
|
elif isinstance(oldObjInstance, types.DataObject):
|
|
if isObjLink:
|
|
bMatch = oldObj.GetKey() == newObj.GetKey()
|
|
LogIf(not bMatch, 'DiffAnyObjects: Keys do not match %s != %s'
|
|
% (oldObj.GetKey(), newObj.GetKey()))
|
|
return bMatch
|
|
return self.DiffDataObjects(oldObj, newObj)
|
|
|
|
else:
|
|
raise TypeError("Unknown type: "+repr(GetWsdlName(oldObj.__class__)))
|
|
|
|
def DiffDoArrays(self, oldObj, newObj, isElementLinks):
|
|
"""Diff two DataObject arrays"""
|
|
if len(oldObj) != len(newObj):
|
|
__Log__.debug('DiffDoArrays: Array lengths do not match %d != %d'
|
|
% (len(oldObj), len(newObj)))
|
|
return False
|
|
for i, j in itertools.izip(oldObj, newObj):
|
|
if isElementLinks:
|
|
if i.GetKey() != j.GetKey():
|
|
__Log__.debug('DiffDoArrays: Keys do not match %s != %s'
|
|
% (i.GetKey(), j.GetKey()))
|
|
return False
|
|
else:
|
|
if not self.DiffDataObjects(i, j):
|
|
__Log__.debug(
|
|
'DiffDoArrays: one of the elements do not match')
|
|
return False
|
|
return True
|
|
|
|
def DiffAnyArrays(self, oldObj, newObj, isElementLinks):
|
|
"""Diff two arrays which contain Any objects"""
|
|
if len(oldObj) != len(newObj):
|
|
__Log__.debug('DiffAnyArrays: Array lengths do not match. %d != %d'
|
|
% (len(oldObj), len(newObj)))
|
|
return False
|
|
for i, j in itertools.izip(oldObj, newObj):
|
|
if not self.DiffAnyObjects(i, j, isElementLinks):
|
|
__Log__.debug('DiffAnyArrays: One of the elements do not match.')
|
|
return False
|
|
return True
|
|
|
|
def DiffPrimitiveArrays(self, oldObj, newObj):
|
|
"""Diff two primitive arrays"""
|
|
if len(oldObj) != len(newObj):
|
|
__Log__.debug('DiffDoArrays: Array lengths do not match %d != %d'
|
|
% (len(oldObj), len(newObj)))
|
|
return False
|
|
match = True
|
|
if self._ignoreArrayOrder:
|
|
oldSet = oldObj and frozenset(oldObj) or frozenset()
|
|
newSet = newObj and frozenset(newObj) or frozenset()
|
|
match = (oldSet == newSet)
|
|
else:
|
|
for i, j in itertools.izip(oldObj, newObj):
|
|
if i != j:
|
|
match = False
|
|
break
|
|
if not match:
|
|
__Log__.debug(
|
|
'DiffPrimitiveArrays: One of the elements do not match.')
|
|
return False
|
|
return True
|
|
|
|
|
|
def DiffArrayObjects(self, oldObj, newObj, isElementLinks=False):
|
|
"""Method which deligates the diffing of arrays based on the type"""
|
|
if oldObj == newObj:
|
|
return True
|
|
if not oldObj or not newObj:
|
|
return False
|
|
if len(oldObj) != len(newObj):
|
|
__Log__.debug('DiffArrayObjects: Array lengths do not match %d != %d'
|
|
% (len(oldObj), len(newObj)))
|
|
return False
|
|
firstObj = oldObj[0]
|
|
if IsPrimitiveType(firstObj):
|
|
return self.DiffPrimitiveArrays(oldObj, newObj)
|
|
elif isinstance(firstObj, types.ManagedObject):
|
|
return self.DiffAnyArrays(oldObj, newObj, isElementLinks)
|
|
elif isinstance(firstObj, types.DataObject):
|
|
return self.DiffDoArrays(oldObj, newObj, isElementLinks)
|
|
else:
|
|
raise TypeError("Unknown type: %s" % oldObj.__class__)
|
|
|
|
|
|
def DiffDataObjects(self, oldObj, newObj):
|
|
"""Diff Data Objects"""
|
|
if oldObj == newObj:
|
|
return True
|
|
if not oldObj or not newObj:
|
|
__Log__.debug('DiffDataObjects: One of the objects in None')
|
|
return False
|
|
oldType = Type(oldObj)
|
|
newType = Type(newObj)
|
|
if oldType != newType:
|
|
__Log__.debug(
|
|
'DiffDataObjects: Types do not match for dataobjects. %s != %s'
|
|
% (oldObj._wsdlName, newObj._wsdlName))
|
|
return False
|
|
for prop in oldObj._GetPropertyList():
|
|
oldProp = getattr(oldObj, prop.name)
|
|
newProp = getattr(newObj, prop.name)
|
|
propType = oldObj._GetPropertyInfo(prop.name).type
|
|
if not oldProp and not newProp:
|
|
continue
|
|
elif ((prop.flags & VmomiSupport.F_OPTIONAL) and
|
|
self._looseMatch and (not newProp or not oldProp)):
|
|
continue
|
|
elif not oldProp or not newProp:
|
|
__Log__.debug(
|
|
'DiffDataObjects: One of the objects has property %s unset'
|
|
% prop.name)
|
|
return False
|
|
|
|
bMatch = True
|
|
if IsPrimitiveType(oldProp):
|
|
bMatch = oldProp == newProp
|
|
elif isinstance(oldProp, types.ManagedObject):
|
|
bMatch = self.DiffAnyObjects(oldProp, newProp, prop.flags
|
|
& VmomiSupport.F_LINK)
|
|
elif isinstance(oldProp, types.DataObject):
|
|
if prop.flags & VmomiSupport.F_LINK:
|
|
bMatch = oldObj.GetKey() == newObj.GetKey()
|
|
LogIf(not bMatch, 'DiffDataObjects: Key match failed %s != %s'
|
|
% (oldObj.GetKey(), newObj.GetKey()))
|
|
else:
|
|
bMatch = self.DiffAnyObjects(oldProp, newProp, prop.flags
|
|
& VmomiSupport.F_LINK)
|
|
elif isinstance(oldProp, list):
|
|
bMatch = self.DiffArrayObjects(oldProp, newProp, prop.flags
|
|
& VmomiSupport.F_LINK)
|
|
else:
|
|
raise TypeError("Unknown type: "+repr(propType))
|
|
|
|
if not bMatch:
|
|
__Log__.debug('DiffDataObjects: Objects differ in property %s'
|
|
% prop.name)
|
|
return False
|
|
return True
|
|
|
|
|
|
def DiffAnys(obj1, obj2, looseMatch=False, ignoreArrayOrder=True):
|
|
"""Diff any two objects. Objects can either be primitive type
|
|
or DataObjects"""
|
|
differ = Differ(looseMatch = looseMatch, ignoreArrayOrder = ignoreArrayOrder)
|
|
return differ.DiffAnyObjects(obj1, obj2)
|