VimWrap

The code for VMware convenience wrapper. see description in my blog for more details.

The code works with API versions 2.0 and 2.5 (ESX 3.0 and 3.5 respectively) - just make sure you use the right version of the VimService2005 assembly (part of the SDK).

import clr clr.AddReference('VimService2005') import VimApi

clr.AddReference('System.Web.Services') import System.Web.Services clr.AddReference('System.Xml') import System.Xml

from System.Net import CookieContainer

class VimException(Exception): """Extracts the relevant information from the soap exception thrown natively by VimApi""" def __init__(self,e): try: self.msg = e.Message self.name = 'GenericError' self.element = None for c in e.Detail.ChildNodes: if isinstance(c,System.Xml.XmlElement): self.name = c.Name if self.name.endswith('Fault'): self.name = self.name[:-5] self.element = c                   break except Exception,err: self.name = 'UnexpectedExceptionError'
 * 1)                     VimException
 * 1)                     VimException

def __str__(self): return 'VimException(%s: %s)' % (self.name,self.msg)

class ServiceWrapper(object): """Convenience wrapper over VMware's VimService and ServiceContent classes.      Also designed to work naturally with the ManagedObject class.    """ def __init__(self,url,user,pswd): self.url = url self.user = user self.pswd = pswd self.b_connected = False
 * 1)                    ServiceWrapper
 * 1)                    ServiceWrapper

self.service = VimApi.VimService(           Url = self.url,            CookieContainer = CookieContainer,        )

self.service_instance = self.wrap(VimApi.ManagedObjectReference( type="ServiceInstance", Value="ServiceInstance", ))

def wrap(self,x): if isinstance(x,VimApi.ManagedObjectReference): return ManagedObject(x,self) if isinstance(x,System.Array): # XXX - seems this is the only sequence type we need to handle return [self.wrap(i) for i in x]       return x

def unwrap(self,x): if isinstance(x,ManagedObject): return x.moref if isinstance(x,tuple): # XXX - seems this is the only sequence type we need to handle return tuple(self.unwrap(i) for i in x)       return x    def connect(self): content = self.service_instance.RetrieveServiceContent for propname in [p.Name for p in clr.GetClrType(VimApi.ServiceContent).GetProperties]: if propname in ['dynamicProperty','dynamicType']: continue # these are boilerplate fields for SOAP protocol. ignore them prop = getattr(content,propname) obj = self.wrap(prop) setattr(self,propname,obj) self.b_connected = True

def login(self): if not self.b_connected: self.connect self.sessionManager.Login(self.user,self.pswd,None) def invoke(self,moref,method_name,*a): mth = getattr(self.service,method_name) a = [self.unwrap(x) for x in a]       try: res = mth(moref,*a) except System.Web.Services.Protocols.SoapException, e:           raise VimException(e) return self.wrap(res) def get_property(self,moref,name): # Create a filter spec with the specified object and property spec fs = VimApi.PropertyFilterSpec

# create a property spec (describes what we want retrieved) ps = VimApi.PropertySpec ps.type = moref.type ps.all = False ps.pathSet = (name,) fs.propSet = (ps,) # the search starting point os = VimApi.ObjectSpec os.obj = moref fs.objectSet = (os,) # run the query raw_res = self.propertyCollector.RetrieveProperties((fs,)) # translate the result if raw_res is None: return None propSet = raw_res[0].propSet if propSet is None: return None res = propSet[0].val return self.wrap(res)

class ManagedObject(object): """Object oriented wrapper over VMware's ManagedObjectReference (an opaque handle)""" def __init__(self,moref,service): self.moref = moref self.service = service # service wrapper def __repr__(self): return '%s(%s)' % (self.moref.type,self.moref.Value)
 * 1)                    ManagedObject
 * 1)                    ManagedObject

def __getattr__(self,name): if hasattr(self.service.service,name): # it's a method def wrapped(*a): return self.service.invoke(self.moref,name,*a) wrapped.__name__ = name return wrapped else: # not a method - assume it's a property try: return self.service.get_property(self.moref,name) except VimException, e:               if e.name == 'InvalidProperty': raise AttributeError(name) else: raise

Here's an example usage: from vimwrap import ServiceWrapper svc = ServiceWrapper(url,user,pswd) svc.login

f = svc.searchIndex.FindByInventoryPath('.../my_folder') print 'Folder: %s' % f print 'Children:' for child in f.childEntity: print '\t%s: %s' % (child.name,child)

Here's another example - powering on a machine, and checking task progress: vm = svc.searchIndex.FindByInventoryPath('.../test_machine') task = vm.PowerOnVM_Task(None) ti = task.info # call VMware to get updated task info print 'powering on... state=%s, progress=%s' % (ti.stat

note of caution:

This is great for exploration and basic tasks. However, once you need to go over larger configurations, you will need to use methods like RetrieveProperties directly to get only the data you need and get all of it in one call. I suggest writing a wrapper for that API too - it's still much more complex and boilerplate than it needs to be.

Back to Contents.