VimWrap

From IronPython Cookbook

Revision as of 14:20, 14 July 2009 by MichaelFoord (Talk | contribs)

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

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

#########################################################
#                     VimException
#########################################################
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'

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

#########################################################
#                    ServiceWrapper
#########################################################
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

        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)

#########################################################
#                    ManagedObject
#########################################################
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)

    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


Back to Contents.

TOOLBOX
LANGUAGES