Initial source drop

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.
This commit is contained in:
Joshua Kwan
2013-12-13 17:02:41 -05:00
committed by Joshua Kwan
parent c03fac748a
commit 26649465c6
23 changed files with 8404 additions and 2 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
*.pyc
build
dist

2
MANIFEST.in Normal file
View File

@@ -0,0 +1,2 @@
include README.md
recursive-include sample *

View File

@@ -1,2 +1,16 @@
pyvomomi
========
pyVmomi is a Python SDK for the VMware vSphere API that allows you to
manipulate ESX, ESXi, and vCenter using scripts.
To get started, check out the examples in `sample/poweronvm.py` and
`sample/getallvms.py`.
You can install this as a package. Just run `python setup.py bdist_egg`
and then use `pip` or `easy_install` to deploy it on your system.
There are other bindings of this API in other languages. See:
* **vijava** (Java): http://vijava.sourceforge.net/
* **rbvmomi** (Ruby): https://github.com/vmware/rbvmomi
* **vSphere SDK for Perl** (non-free): https://my.vmware.com/group/vmware/details?downloadGroup=VSP510-SDKPERL-510&productId=285
Have fun!

12
pyVim/__init__.py Normal file
View File

@@ -0,0 +1,12 @@
## @file pyVim/__init__.py
## @brief A client-side Python API that wraps pyVmomi.
##
##
##
## @mainpage
##
## A client-side Python API that wraps pyVmomi.
##
##

626
pyVim/connect.py Normal file
View File

@@ -0,0 +1,626 @@
# 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.
## @file connect.py
## @brief Connect to a VMOMI ServiceInstance.
##
## Detailed description (for Doxygen goes here)
"""
Connect to a VMOMI ServiceInstance.
Detailed description (for [e]pydoc goes here).
"""
import sys
import threading
import thread
import types
import httplib
import socket
import time
import itertools
import re
from pyVmomi import vim, vmodl, SoapStubAdapter, SessionOrientedStub
from pyVmomi.VmomiSupport import nsMap, versionIdMap, versionMap, IsChildVersion
from pyVmomi.VmomiSupport import GetServiceVersions
try:
from xml.etree.ElementTree import ElementTree
except ImportError:
from elementtree.ElementTree import ElementTree
from xml.parsers.expat import ExpatError
import urllib
"""
Global regular expression for parsing host and port connection
See http://www.ietf.org/rfc/rfc3986.txt sec 3.2.2
"""
_rx = re.compile(r"(^\[.+\]|[^:]+)(:\d+)?$")
_si = None
"""
Global (thread-shared) ServiceInstance
@todo: Get rid of me?
"""
class closing(object):
"""
Helper class for using closable objects in a 'with' statement,
similar to the one provided by contextlib.
"""
def __init__(self, obj):
self.obj = obj
def __enter__(self):
return self.obj
def __exit__(self, *exc_info):
self.obj.close()
class VimSessionOrientedStub(SessionOrientedStub):
'''A vim-specific SessionOrientedStub. See the SessionOrientedStub class
in pyVmomi/SoapAdapter.py for more information.'''
# The set of exceptions that should trigger a relogin by the session stub.
SESSION_EXCEPTIONS = (
vim.fault.NotAuthenticated,
)
@staticmethod
def makeUserLoginMethod(username, password, locale=None):
'''Return a function that will call the vim.SessionManager.Login() method
with the given parameters. The result of this function can be passed as
the "loginMethod" to a SessionOrientedStub constructor.'''
def _doLogin(soapStub):
si = vim.ServiceInstance("ServiceInstance", soapStub)
sm = si.content.sessionManager
if not sm.currentSession:
si.content.sessionManager.Login(username, password, locale)
return _doLogin
@staticmethod
def makeExtensionLoginMethod(extensionKey):
'''Return a function that will call the vim.SessionManager.Login() method
with the given parameters. The result of this function can be passed as
the "loginMethod" to a SessionOrientedStub constructor.'''
def _doLogin(soapStub):
si = vim.ServiceInstance("ServiceInstance", soapStub)
sm = si.content.sessionManager
if not sm.currentSession:
si.content.sessionManager.LoginExtensionByCertificate(extensionKey)
return _doLogin
@staticmethod
def makeCertHokTokenLoginMethod(stsUrl, stsCert=None):
'''Return a function that will call the vim.SessionManager.LoginByToken()
after obtaining a HoK SAML token from the STS. The result of this function
can be passed as the "loginMethod" to a SessionOrientedStub constructor.
@param stsUrl: URL of the SAML Token issuing service. (i.e. SSO server).
@param stsCert: public key of the STS service.
'''
assert(stsUrl)
def _doLogin(soapStub):
import sso
cert = soapStub.schemeArgs['cert_file']
key = soapStub.schemeArgs['key_file']
authenticator = sso.SsoAuthenticator(sts_url=stsUrl,
sts_cert=stsCert)
samlAssertion = authenticator.get_hok_saml_assertion(cert,key)
def _requestModifier(request):
return sso.add_saml_context(request, samlAssertion, key)
si = vim.ServiceInstance("ServiceInstance", soapStub)
sm = si.content.sessionManager
if not sm.currentSession:
with soapStub.requestModifier(_requestModifier):
try:
soapStub.samlToken = samlAssertion
si.content.sessionManager.LoginByToken()
finally:
soapStub.samlToken = None
return _doLogin
@staticmethod
def makeCredBearerTokenLoginMethod(username,
password,
stsUrl,
stsCert=None):
'''Return a function that will call the vim.SessionManager.LoginByToken()
after obtaining a Bearer token from the STS. The result of this function
can be passed as the "loginMethod" to a SessionOrientedStub constructor.
@param username: username of the user/service registered with STS.
@param password: password of the user/service registered with STS.
@param stsUrl: URL of the SAML Token issueing service. (i.e. SSO server).
@param stsCert: public key of the STS service.
'''
assert(username)
assert(password)
assert(stsUrl)
def _doLogin(soapStub):
import sso
cert = soapStub.schemeArgs['cert_file']
key = soapStub.schemeArgs['key_file']
authenticator = sso.SsoAuthenticator(sts_url=stsUrl,
sts_cert=stsCert)
samlAssertion = authenticator.get_bearer_saml_assertion(username,
password,
cert,
key)
si = vim.ServiceInstance("ServiceInstance", soapStub)
sm = si.content.sessionManager
if not sm.currentSession:
try:
soapStub.samlToken = samlAssertion
si.content.sessionManager.LoginByToken()
finally:
soapStub.samlToken = None
return _doLogin
def Connect(host='localhost', port=443, user='root', pwd='',
service="hostd", adapter="SOAP", namespace=None, path="/sdk",
version=None, keyFile=None, certFile=None):
"""
Connect to the specified server, login and return the service
instance object.
Throws any exception back to caller. The service instance object is
also saved in the library for easy access.
Clients should modify the service parameter only when connecting to
a VMOMI server other than hostd/vpxd. For both of the latter, the
default value is fine.
@param host: Which host to connect to.
@type host: string
@param port: Port
@type port: int
@param user: User
@type user: string
@param pwd: Password
@type pwd: string
@param service: Service
@type service: string
@param adapter: Adapter
@type adapter: string
@param namespace: Namespace *** Deprecated: Use version instead ***
@type namespace: string
@param path: Path
@type path: string
@param version: Version
@type version: string
@param keyFile: ssl key file path
@type keyFile: string
@param certFile: ssl cert file path
@type certFile: string
"""
try:
info = re.match(_rx, host)
if info is not None:
host = info.group(1)
if host[0] == '[':
host = info.group(1)[1:-1]
if info.group(2) is not None:
port = int(info.group(2)[1:])
except ValueError, ve:
pass
if namespace:
assert(version is None)
version = versionMap[namespace]
elif not version:
version="vim.version.version6"
si, stub = __Login(host, port, user, pwd, service, adapter, version, path,
keyFile, certFile)
SetSi(si)
return si
def Disconnect(si):
"""
Disconnect (logout) service instance
@param si: Service instance (returned from Connect)
"""
# Logout
__Logout(si)
SetSi(None)
## Method that gets a local ticket for the specified user
def GetLocalTicket(si, user):
try:
sessionManager = si.content.sessionManager
except Exception, e:
if type(e).__name__ == 'ExpatError':
msg = 'Malformed response while querying for local ticket: "%s"' % e
raise vim.fault.HostConnectFault(msg=msg)
else:
msg = 'Failed to query for local ticket: "%s"' % e
raise vim.fault.HostConnectFault(msg=msg)
localTicket = sessionManager.AcquireLocalTicket(userName=user)
return (localTicket.userName, file(localTicket.passwordFilePath).read())
## Private method that performs the actual Connect and returns a
## connected service instance object.
def __Login(host, port, user, pwd, service, adapter, version, path,
keyFile, certFile):
"""
Private method that performs the actual Connect and returns a
connected service instance object.
@param host: Which host to connect to.
@type host: string
@param port: Port
@type port: int
@param user: User
@type user: string
@param pwd: Password
@type pwd: string
@param service: Service
@type service: string
@param adapter: Adapter
@type adapter: string
@param version: Version
@type version: string
@param path: Path
@type path: string
@param keyFile: ssl key file path
@type keyFile: string
@param certFile: ssl cert file path
@type certFile: string
"""
# XXX remove the adapter and service arguments once dependent code is fixed
if adapter != "SOAP":
raise ValueError(adapter)
# Create the SOAP stub adapter
stub = SoapStubAdapter(host, port, version=version, path=path,
certKeyFile=keyFile, certFile=certFile)
# Get Service instance
si = vim.ServiceInstance("ServiceInstance", stub)
try:
content = si.RetrieveContent()
except vmodl.MethodFault:
raise
except Exception, e:
raise vim.fault.HostConnectFault(msg=str(e))
# Get a ticket if we're connecting to localhost and password is not specified
if host == 'localhost' and not pwd:
try:
(user, pwd) = GetLocalTicket(si, user)
except:
pass # This is not supported against vCenter, and connecting
# with an empty password is fine in debug builds
# Login
try:
x = content.sessionManager.Login(user, pwd, None)
except vim.fault.InvalidLogin:
raise
except Exception, e:
raise
return si, stub
## Private method that performs the actual Disonnect
def __Logout(si):
"""
Disconnect (logout) service instance
@param si: Service instance (returned from Connect)
"""
try:
if si:
content = si.RetrieveContent()
content.sessionManager.Logout()
except Exception, e:
pass
## Get the saved service instance.
def GetSi():
""" Get the saved service instance. """
return _si
## Set the saved service instance.
def SetSi(si):
""" Set the saved service instance. """
global _si
_si = si
## Get the global saved stub
def GetStub():
""" Get the global saved stub. """
si = GetSi()
if si:
return si._GetStub()
return None;
## RAII-style class for managing connections
class Connection(object):
def __init__(self, *args, **kwargs):
self.args = args
self.kwargs = kwargs
self.si = None
def __enter__(self):
self.si = Connect(*self.args, **self.kwargs)
return self.si
def __exit__(self, *exc_info):
if self.si:
Disconnect(self.si)
self.si = None
class SmartConnection(object):
def __init__(self, *args, **kwargs):
self.args = args
self.kwargs = kwargs
self.si = None
def __enter__(self):
self.si = SmartConnect(*self.args, **self.kwargs)
return self.si
def __exit__(self, *exc_info):
if self.si:
Disconnect(self.si)
self.si = None
## Private method that returns an ElementTree describing the API versions
## supported by the specified server. The result will be vimServiceVersions.xml
## if it exists, otherwise vimService.wsdl if it exists, otherwise None.
def __GetServiceVersionDescription(protocol, server, port, path):
"""
Private method that returns an ElementTree describing the API versions
supported by the specified server. The result will be vimServiceVersions.xml
if it exists, otherwise vimService.wsdl if it exists, otherwise None.
@param protocol: What protocol to use for the connection (e.g. https or http).
@type protocol: string
@param server: Which server to connect to.
@type server: string
@param port: Port
@type port: int
@param path: Path
@type path: string
"""
tree = ElementTree()
url = "%s://%s:%s/%s/vimServiceVersions.xml" % (protocol, server, port, path)
try:
with closing(urllib.urlopen(url)) as sock:
if sock.getcode() == 200:
tree.parse(sock)
return tree
except ExpatError:
pass
url = "%s://%s:%s/%s/vimService.wsdl" % (protocol, server, port, path)
try:
with closing(urllib.urlopen(url)) as sock:
if sock.getcode() == 200:
tree.parse(sock)
return tree
except ExpatError:
pass
return None
## Private method that returns true if the service version description document
## indicates that the desired version is supported
def __VersionIsSupported(desiredVersion, serviceVersionDescription):
"""
Private method that returns true if the service version description document
indicates that the desired version is supported
@param desiredVersion: The version we want to see if the server supports
(eg. vim.version.version2.
@type desiredVersion: string
@param serviceVersionDescription: An ElementTree for vimServiceVersions.xml
or vimService.wsdl.
@type serviceVersionDescription: ElementTree
"""
root = serviceVersionDescription.getroot()
if root.tag == 'namespaces':
# serviceVersionDescription appears to be a vimServiceVersions.xml document
if root.get('version') <> '1.0':
raise RuntimeError('vimServiceVersions.xml has version %s,' \
' which is not understood' % (root.get('version')))
desiredVersionId = versionIdMap[desiredVersion]
supportedVersion = None
for namespace in root.findall('namespace'):
versionId = namespace.findtext('version')
if versionId == desiredVersionId:
return True
else:
for versionId in namespace.findall('priorVersions/version'):
if versionId.text == desiredVersionId:
return True
else:
# serviceVersionDescription must be a vimService.wsdl document
wsdlNS = 'http://schemas.xmlsoap.org/wsdl/'
importElement = serviceVersionDescription.find('.//{%s}import' % wsdlNS)
supportedVersion = versionMap[importElement.get('namespace')[4:]]
if IsChildVersion(supportedVersion, desiredVersion):
return True
return False
## Private method that returns the most preferred API version supported by the
## specified server,
def __FindSupportedVersion(protocol, server, port, path, preferredApiVersions):
"""
Private method that returns the most preferred API version supported by the
specified server,
@param protocol: What protocol to use for the connection (e.g. https or http).
@type protocol: string
@param server: Which server to connect to.
@type server: string
@param port: Port
@type port: int
@param path: Path
@type path: string
@param preferredApiVersions: Acceptable API version(s) (e.g. vim.version.version3)
If a list of versions is specified the versions should
be ordered from most to least preferred.
@type preferredApiVersions: string or string list
"""
serviceVersionDescription = __GetServiceVersionDescription(protocol,
server,
port,
path)
if serviceVersionDescription is None:
return None
if not isinstance(preferredApiVersions, list):
preferredApiVersions = [ preferredApiVersions ]
for desiredVersion in preferredApiVersions:
if __VersionIsSupported(desiredVersion, serviceVersionDescription):
return desiredVersion
return None
def SmartConnect(protocol='https', host='localhost', port=443, user='root', pwd='',
service="hostd", path="/sdk",
preferredApiVersions=None):
"""
Determine the most preferred API version supported by the specified server,
then connect to the specified server using that API version, login and return
the service instance object.
Throws any exception back to caller. The service instance object is
also saved in the library for easy access.
Clients should modify the service parameter only when connecting to
a VMOMI server other than hostd/vpxd. For both of the latter, the
default value is fine.
@param protocol: What protocol to use for the connection (e.g. https or http).
@type protocol: string
@param host: Which host to connect to.
@type host: string
@param port: Port
@type port: int
@param user: User
@type user: string
@param pwd: Password
@type pwd: string
@param service: Service
@type service: string
@param path: Path
@type path: string
@param preferredApiVersions: Acceptable API version(s) (e.g. vim.version.version3)
If a list of versions is specified the versions should
be ordered from most to least preferred. If None is
specified, the list of versions support by pyVmomi will
be used.
@type preferredApiVersions: string or string list
"""
if preferredApiVersions is None:
preferredApiVersions = GetServiceVersions('vim25')
supportedVersion = __FindSupportedVersion(protocol,
host,
port,
path,
preferredApiVersions)
if supportedVersion is None:
raise Exception("%s:%s is not a VIM server" % (host, port))
portNumber = protocol == "http" and -int(port) or int(port)
return Connect(host=host,
port=portNumber,
user=user,
pwd=pwd,
service=service,
adapter='SOAP',
version=supportedVersion,
path=path)
def OpenUrlWithBasicAuth(url, user='root', pwd=''):
"""
Open the specified URL, using HTTP basic authentication to provide
the specified credentials to the server as part of the request.
Returns the response as a file-like object.
"""
import urllib2
pwMgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
pwMgr.add_password(None, url, user, pwd)
handler = urllib2.HTTPBasicAuthHandler(pwMgr)
opener = urllib2.build_opener(handler)
return opener.open(url)
def OpenPathWithStub(path, stub):
"""
Open the specified path using HTTP, using the host/port/protocol
associated with the specified stub. If the stub has a session cookie,
it is included with the HTTP request. Returns the response as a
file-like object.
"""
import httplib
import urllib2
if not hasattr(stub, 'scheme'):
raise vmodl.fault.NotSupported()
elif stub.scheme == httplib.HTTPConnection:
protocol = 'http'
elif stub.scheme == httplib.HTTPSConnection:
protocol = 'https'
else:
raise vmodl.fault.NotSupported()
hostPort = stub.host
url = '%s://%s%s' % (protocol, hostPort, path)
request = urllib2.Request(url)
if stub.cookie:
request.add_header('Cookie', stub.cookie)
return urllib2.urlopen(request)

42
pyVmomi/Cache.py Normal file
View File

@@ -0,0 +1,42 @@
# 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.
"""
This module implements the cache decorator
"""
__author__ = "VMware, Inc."
def Cache(fn):
""" Function cache decorator """
def fnCache(*args, **kwargs):
""" Cache function """
key = (args and tuple(args) or None,
kwargs and frozenset(kwargs.items()) or None)
if key not in fn.__cached__:
fn.__cached__[key] = cache = fn(*args, **kwargs)
else:
cache = fn.__cached__[key]
return cache
def ResetCache():
""" Reset cache """
fn.__cached__ = {}
setattr(fn, "__cached__", {})
setattr(fn, "__resetcache__", ResetCache)
fnCache.__name__ = fn.__name__
fnCache.__doc__ = fn.__doc__
fnCache.__dict__.update(fn.__dict__)
return fnCache

79
pyVmomi/CoreTypes.py Normal file
View File

@@ -0,0 +1,79 @@
# 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.
# ******* WARNING - AUTO GENERATED CODE - DO NOT EDIT *******
from VmomiSupport import CreateDataType, CreateManagedType, CreateEnumType, AddVersion, AddVersionParent, F_LINK, F_LINKABLE, F_OPTIONAL
AddVersion("vmodl.query.version.version1", "", "", 0, "vim25")
AddVersion("vmodl.query.version.version2", "", "", 0, "vim25")
AddVersion("vmodl.query.version.version3", "", "", 0, "vim25")
AddVersion("vmodl.version.version0", "", "", 0, "vim25")
AddVersion("vmodl.version.version1", "", "", 0, "vim25")
AddVersionParent("vmodl.query.version.version1", "vmodl.query.version.version1")
AddVersionParent("vmodl.query.version.version1", "vmodl.version.version0")
AddVersionParent("vmodl.query.version.version2", "vmodl.query.version.version1")
AddVersionParent("vmodl.query.version.version2", "vmodl.query.version.version2")
AddVersionParent("vmodl.query.version.version2", "vmodl.version.version0")
AddVersionParent("vmodl.query.version.version2", "vmodl.version.version1")
AddVersionParent("vmodl.query.version.version3", "vmodl.query.version.version1")
AddVersionParent("vmodl.query.version.version3", "vmodl.query.version.version2")
AddVersionParent("vmodl.query.version.version3", "vmodl.query.version.version3")
AddVersionParent("vmodl.query.version.version3", "vmodl.version.version0")
AddVersionParent("vmodl.query.version.version3", "vmodl.version.version1")
AddVersionParent("vmodl.version.version0", "vmodl.version.version0")
AddVersionParent("vmodl.version.version1", "vmodl.version.version0")
AddVersionParent("vmodl.version.version1", "vmodl.version.version1")
CreateDataType("vmodl.DynamicArray", "DynamicArray", "vmodl.DataObject", "vmodl.version.version0", [("dynamicType", "string", "vmodl.version.version0", F_OPTIONAL), ("val", "anyType[]", "vmodl.version.version0", 0)])
CreateDataType("vmodl.DynamicData", "DynamicData", "vmodl.DataObject", "vmodl.version.version0", [("dynamicType", "string", "vmodl.version.version0", F_OPTIONAL), ("dynamicProperty", "vmodl.DynamicProperty[]", "vmodl.version.version0", F_OPTIONAL)])
CreateDataType("vmodl.DynamicProperty", "DynamicProperty", "vmodl.DataObject", "vmodl.version.version0", [("name", "vmodl.PropertyPath", "vmodl.version.version0", 0), ("val", "anyType", "vmodl.version.version0", 0)])
CreateDataType("vmodl.KeyAnyValue", "KeyAnyValue", "vmodl.DynamicData", "vmodl.version.version1", [("key", "string", "vmodl.version.version1", 0), ("value", "anyType", "vmodl.version.version1", 0)])
CreateDataType("vmodl.LocalizableMessage", "LocalizableMessage", "vmodl.DynamicData", "vmodl.version.version1", [("key", "string", "vmodl.version.version1", 0), ("arg", "vmodl.KeyAnyValue[]", "vmodl.version.version1", F_OPTIONAL), ("message", "string", "vmodl.version.version1", F_OPTIONAL)])
CreateDataType("vmodl.fault.HostCommunication", "HostCommunication", "vmodl.RuntimeFault", "vmodl.version.version0", None)
CreateDataType("vmodl.fault.HostNotConnected", "HostNotConnected", "vmodl.fault.HostCommunication", "vmodl.version.version0", None)
CreateDataType("vmodl.fault.HostNotReachable", "HostNotReachable", "vmodl.fault.HostCommunication", "vmodl.version.version0", None)
CreateDataType("vmodl.fault.InvalidArgument", "InvalidArgument", "vmodl.RuntimeFault", "vmodl.version.version0", [("invalidProperty", "vmodl.PropertyPath", "vmodl.version.version0", F_OPTIONAL)])
CreateDataType("vmodl.fault.InvalidRequest", "InvalidRequest", "vmodl.RuntimeFault", "vmodl.version.version0", None)
CreateDataType("vmodl.fault.InvalidType", "InvalidType", "vmodl.fault.InvalidRequest", "vmodl.version.version0", [("argument", "vmodl.PropertyPath", "vmodl.version.version0", F_OPTIONAL)])
CreateDataType("vmodl.fault.ManagedObjectNotFound", "ManagedObjectNotFound", "vmodl.RuntimeFault", "vmodl.version.version0", [("obj", "vmodl.ManagedObject", "vmodl.version.version0", 0)])
CreateDataType("vmodl.fault.MethodNotFound", "MethodNotFound", "vmodl.fault.InvalidRequest", "vmodl.version.version0", [("receiver", "vmodl.ManagedObject", "vmodl.version.version0", 0), ("method", "string", "vmodl.version.version0", 0)])
CreateDataType("vmodl.fault.NotEnoughLicenses", "NotEnoughLicenses", "vmodl.RuntimeFault", "vmodl.version.version0", None)
CreateDataType("vmodl.fault.NotImplemented", "NotImplemented", "vmodl.RuntimeFault", "vmodl.version.version0", None)
CreateDataType("vmodl.fault.NotSupported", "NotSupported", "vmodl.RuntimeFault", "vmodl.version.version0", None)
CreateDataType("vmodl.fault.RequestCanceled", "RequestCanceled", "vmodl.RuntimeFault", "vmodl.version.version0", None)
CreateDataType("vmodl.fault.SecurityError", "SecurityError", "vmodl.RuntimeFault", "vmodl.version.version0", None)
CreateDataType("vmodl.fault.SystemError", "SystemError", "vmodl.RuntimeFault", "vmodl.version.version0", [("reason", "string", "vmodl.version.version0", 0)])
CreateDataType("vmodl.fault.UnexpectedFault", "UnexpectedFault", "vmodl.RuntimeFault", "vmodl.version.version0", [("faultName", "vmodl.TypeName", "vmodl.version.version0", 0), ("fault", "vmodl.MethodFault", "vmodl.version.version0", F_OPTIONAL)])
CreateDataType("vmodl.query.InvalidCollectorVersion", "InvalidCollectorVersion", "vmodl.MethodFault", "vmodl.query.version.version1", None)
CreateDataType("vmodl.query.InvalidProperty", "InvalidProperty", "vmodl.MethodFault", "vmodl.query.version.version1", [("name", "vmodl.PropertyPath", "vmodl.query.version.version1", 0)])
CreateManagedType("vmodl.query.PropertyCollector", "PropertyCollector", "vmodl.ManagedObject", "vmodl.query.version.version1", [("filter", "vmodl.query.PropertyCollector.Filter[]", "vmodl.query.version.version1", F_OPTIONAL, "System.View")], [("createFilter", "CreateFilter", "vmodl.query.version.version1", (("spec", "vmodl.query.PropertyCollector.FilterSpec", "vmodl.query.version.version1", 0, None),("partialUpdates", "boolean", "vmodl.query.version.version1", 0, None),), (0, "vmodl.query.PropertyCollector.Filter", "vmodl.query.PropertyCollector.Filter"), "System.View", ["vmodl.query.InvalidProperty", ]), ("retrieveContents", "RetrieveProperties", "vmodl.query.version.version1", (("specSet", "vmodl.query.PropertyCollector.FilterSpec[]", "vmodl.query.version.version1", 0, None),), (F_OPTIONAL, "vmodl.query.PropertyCollector.ObjectContent[]", "vmodl.query.PropertyCollector.ObjectContent[]"), "System.Anonymous", ["vmodl.query.InvalidProperty", ]), ("checkForUpdates", "CheckForUpdates", "vmodl.query.version.version1", (("version", "string", "vmodl.query.version.version1", F_OPTIONAL, None),), (F_OPTIONAL, "vmodl.query.PropertyCollector.UpdateSet", "vmodl.query.PropertyCollector.UpdateSet"), "System.View", ["vmodl.query.InvalidCollectorVersion", ]), ("waitForUpdates", "WaitForUpdates", "vmodl.query.version.version1", (("version", "string", "vmodl.query.version.version1", F_OPTIONAL, None),), (0, "vmodl.query.PropertyCollector.UpdateSet", "vmodl.query.PropertyCollector.UpdateSet"), "System.View", ["vmodl.query.InvalidCollectorVersion", ]), ("cancelWaitForUpdates", "CancelWaitForUpdates", "vmodl.query.version.version1", (), (0, "void", "void"), "System.View", None), ("waitForUpdatesEx", "WaitForUpdatesEx", "vmodl.query.version.version3", (("version", "string", "vmodl.query.version.version3", F_OPTIONAL, None),("options", "vmodl.query.PropertyCollector.WaitOptions", "vmodl.query.version.version3", F_OPTIONAL, None),), (F_OPTIONAL, "vmodl.query.PropertyCollector.UpdateSet", "vmodl.query.PropertyCollector.UpdateSet"), "System.View", ["vmodl.query.InvalidCollectorVersion", ]), ("retrievePropertiesEx", "RetrievePropertiesEx", "vmodl.query.version.version3", (("specSet", "vmodl.query.PropertyCollector.FilterSpec[]", "vmodl.query.version.version3", 0, None),("options", "vmodl.query.PropertyCollector.RetrieveOptions", "vmodl.query.version.version3", 0, None),), (F_OPTIONAL, "vmodl.query.PropertyCollector.RetrieveResult", "vmodl.query.PropertyCollector.RetrieveResult"), "System.Anonymous", ["vmodl.query.InvalidProperty", ]), ("continueRetrievePropertiesEx", "ContinueRetrievePropertiesEx", "vmodl.query.version.version3", (("token", "string", "vmodl.query.version.version3", 0, None),), (0, "vmodl.query.PropertyCollector.RetrieveResult", "vmodl.query.PropertyCollector.RetrieveResult"), "System.Anonymous", ["vmodl.query.InvalidProperty", ]), ("cancelRetrievePropertiesEx", "CancelRetrievePropertiesEx", "vmodl.query.version.version3", (("token", "string", "vmodl.query.version.version3", 0, None),), (0, "void", "void"), "System.Anonymous", ["vmodl.query.InvalidProperty", ]), ("createPropertyCollector", "CreatePropertyCollector", "vmodl.query.version.version3", (), (0, "vmodl.query.PropertyCollector", "vmodl.query.PropertyCollector"), "System.View", None), ("destroy", "DestroyPropertyCollector", "vmodl.query.version.version3", (), (0, "void", "void"), "System.View", None)])
CreateDataType("vmodl.query.PropertyCollector.FilterSpec", "PropertyFilterSpec", "vmodl.DynamicData", "vmodl.query.version.version1", [("propSet", "vmodl.query.PropertyCollector.PropertySpec[]", "vmodl.query.version.version1", 0), ("objectSet", "vmodl.query.PropertyCollector.ObjectSpec[]", "vmodl.query.version.version1", 0), ("reportMissingObjectsInResults", "boolean", "vmodl.query.version.version3", F_OPTIONAL)])
CreateDataType("vmodl.query.PropertyCollector.PropertySpec", "PropertySpec", "vmodl.DynamicData", "vmodl.query.version.version1", [("type", "vmodl.TypeName", "vmodl.query.version.version1", 0), ("all", "boolean", "vmodl.query.version.version1", F_OPTIONAL), ("pathSet", "vmodl.PropertyPath[]", "vmodl.query.version.version1", F_OPTIONAL)])
CreateDataType("vmodl.query.PropertyCollector.ObjectSpec", "ObjectSpec", "vmodl.DynamicData", "vmodl.query.version.version1", [("obj", "vmodl.ManagedObject", "vmodl.query.version.version1", 0), ("skip", "boolean", "vmodl.query.version.version1", F_OPTIONAL), ("selectSet", "vmodl.query.PropertyCollector.SelectionSpec[]", "vmodl.query.version.version1", F_OPTIONAL)])
CreateDataType("vmodl.query.PropertyCollector.SelectionSpec", "SelectionSpec", "vmodl.DynamicData", "vmodl.query.version.version1", [("name", "string", "vmodl.query.version.version1", F_OPTIONAL)])
CreateDataType("vmodl.query.PropertyCollector.TraversalSpec", "TraversalSpec", "vmodl.query.PropertyCollector.SelectionSpec", "vmodl.query.version.version1", [("type", "vmodl.TypeName", "vmodl.query.version.version1", 0), ("path", "vmodl.PropertyPath", "vmodl.query.version.version1", 0), ("skip", "boolean", "vmodl.query.version.version1", F_OPTIONAL), ("selectSet", "vmodl.query.PropertyCollector.SelectionSpec[]", "vmodl.query.version.version1", F_OPTIONAL)])
CreateManagedType("vmodl.query.PropertyCollector.Filter", "PropertyFilter", "vmodl.ManagedObject", "vmodl.query.version.version1", [("spec", "vmodl.query.PropertyCollector.FilterSpec", "vmodl.query.version.version1", 0, None), ("partialUpdates", "boolean", "vmodl.query.version.version1", 0, None)], [("destroy", "DestroyPropertyFilter", "vmodl.query.version.version1", (), (0, "void", "void"), None, None)])
CreateDataType("vmodl.query.PropertyCollector.ObjectContent", "ObjectContent", "vmodl.DynamicData", "vmodl.query.version.version1", [("obj", "vmodl.ManagedObject", "vmodl.query.version.version1", 0), ("propSet", "vmodl.DynamicProperty[]", "vmodl.query.version.version1", F_OPTIONAL), ("missingSet", "vmodl.query.PropertyCollector.MissingProperty[]", "vmodl.query.version.version1", F_OPTIONAL)])
CreateDataType("vmodl.query.PropertyCollector.UpdateSet", "UpdateSet", "vmodl.DynamicData", "vmodl.query.version.version1", [("version", "string", "vmodl.query.version.version1", 0), ("filterSet", "vmodl.query.PropertyCollector.FilterUpdate[]", "vmodl.query.version.version1", F_OPTIONAL), ("truncated", "boolean", "vmodl.query.version.version3", F_OPTIONAL)])
CreateDataType("vmodl.query.PropertyCollector.FilterUpdate", "PropertyFilterUpdate", "vmodl.DynamicData", "vmodl.query.version.version1", [("filter", "vmodl.query.PropertyCollector.Filter", "vmodl.query.version.version1", 0), ("objectSet", "vmodl.query.PropertyCollector.ObjectUpdate[]", "vmodl.query.version.version1", F_OPTIONAL), ("missingSet", "vmodl.query.PropertyCollector.MissingObject[]", "vmodl.query.version.version1", F_OPTIONAL)])
CreateDataType("vmodl.query.PropertyCollector.ObjectUpdate", "ObjectUpdate", "vmodl.DynamicData", "vmodl.query.version.version1", [("kind", "vmodl.query.PropertyCollector.ObjectUpdate.Kind", "vmodl.query.version.version1", 0), ("obj", "vmodl.ManagedObject", "vmodl.query.version.version1", 0), ("changeSet", "vmodl.query.PropertyCollector.Change[]", "vmodl.query.version.version1", F_OPTIONAL), ("missingSet", "vmodl.query.PropertyCollector.MissingProperty[]", "vmodl.query.version.version1", F_OPTIONAL)])
CreateEnumType("vmodl.query.PropertyCollector.ObjectUpdate.Kind", "ObjectUpdateKind", "vmodl.query.version.version1", ["modify", "enter", "leave"])
CreateDataType("vmodl.query.PropertyCollector.Change", "PropertyChange", "vmodl.DynamicData", "vmodl.query.version.version1", [("name", "vmodl.PropertyPath", "vmodl.query.version.version1", 0), ("op", "vmodl.query.PropertyCollector.Change.Op", "vmodl.query.version.version1", 0), ("val", "anyType", "vmodl.query.version.version1", F_OPTIONAL)])
CreateEnumType("vmodl.query.PropertyCollector.Change.Op", "PropertyChangeOp", "vmodl.query.version.version1", ["add", "remove", "assign", "indirectRemove"])
CreateDataType("vmodl.query.PropertyCollector.MissingProperty", "MissingProperty", "vmodl.DynamicData", "vmodl.query.version.version1", [("path", "vmodl.PropertyPath", "vmodl.query.version.version1", 0), ("fault", "vmodl.MethodFault", "vmodl.query.version.version1", 0)])
CreateDataType("vmodl.query.PropertyCollector.MissingObject", "MissingObject", "vmodl.DynamicData", "vmodl.query.version.version1", [("obj", "vmodl.ManagedObject", "vmodl.query.version.version1", 0), ("fault", "vmodl.MethodFault", "vmodl.query.version.version1", 0)])
CreateDataType("vmodl.query.PropertyCollector.WaitOptions", "WaitOptions", "vmodl.DynamicData", "vmodl.query.version.version3", [("maxWaitSeconds", "int", "vmodl.query.version.version3", F_OPTIONAL), ("maxObjectUpdates", "int", "vmodl.query.version.version3", F_OPTIONAL)])
CreateDataType("vmodl.query.PropertyCollector.RetrieveOptions", "RetrieveOptions", "vmodl.DynamicData", "vmodl.query.version.version3", [("maxObjects", "int", "vmodl.query.version.version3", F_OPTIONAL)])
CreateDataType("vmodl.query.PropertyCollector.RetrieveResult", "RetrieveResult", "vmodl.DynamicData", "vmodl.query.version.version3", [("token", "string", "vmodl.query.version.version3", F_OPTIONAL), ("objects", "vmodl.query.PropertyCollector.ObjectContent[]", "vmodl.query.version.version3", 0)])

229
pyVmomi/Differ.py Normal file
View File

@@ -0,0 +1,229 @@
# 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)

View File

@@ -0,0 +1,290 @@
#!/usr/bin/env 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.
"""
This module is a converter from dynamic type to pyVmomi type
"""
__author__ = "VMware, Inc."
from pyVmomi import VmomiSupport, vmodl
from Cache import Cache
## Dynamic type importer
#
class DynamicTypeImporter:
""" Dynamic type importer """
## Constructor
#
# @param stub Server stub
def __init__(self, stub, hostSystem=None):
self.stub = stub
self.hostSystem = hostSystem
## Get dynamic type manager
#
# @return moRef to dynamic type manager
@Cache
def GetTypeManager(self):
""" Get dynamic type manager """
dynTypeMgr = None
if self.hostSystem:
try:
dynTypeMgr = self.hostSystem.RetrieveDynamicTypeManager()
except vmodl.fault.MethodNotFound, err:
pass
if not dynTypeMgr:
# Older host not support RetrieveDynamicTypeManager
cmdlineTypesMoId = "ha-dynamic-type-manager"
dynTypeMgr = vmodl.reflect.DynamicTypeManager(cmdlineTypesMoId,
self.stub)
return dynTypeMgr
## Import dynamic types
#
# @param prefix Only types with the specified prefix are imported
# @return dynamic types
@Cache
def ImportTypes(self, prefix=''):
""" Build dynamic types """
# Use QueryTypeInfo to get all types
dynTypeMgr = self.GetTypeManager()
filterSpec = None
if prefix != '':
filterSpec = vmodl.reflect.DynamicTypeManager.TypeFilterSpec(
typeSubstr=prefix)
allTypes = dynTypeMgr.QueryTypeInfo(filterSpec)
## Convert dynamic types to pyVmomi types
#
DynamicTypeConstructor().CreateTypes(allTypes)
return allTypes
## Construct pyVmomi types from dynamic types definition
#
class DynamicTypeConstructor:
""" Dynamic type constructor """
_mapFlags = { "optional": VmomiSupport.F_OPTIONAL,
"linkable": VmomiSupport.F_LINKABLE,
"link": VmomiSupport.F_LINK }
## Constructor
#
def __init__(self):
""" Constructor """
pass
## Create pyVmomi types from vmodl.reflect.DynamicTypeManager.AllTypeInfo
#
# @param allTypes vmodl.reflect.DynamicTypeManager.AllTypeInfo
def CreateTypes(self, allTypes):
"""
Create pyVmomi types from vmodl.reflect.DynamicTypeManager.AllTypeInfo
"""
enumTypes, dataTypes, managedTypes = self._ConvertAllTypes(allTypes)
self._CreateAllTypes(enumTypes, dataTypes, managedTypes)
## Convert all dynamic types to pyVmomi type definitions
#
# @param allTypes vmodl.reflect.DynamicTypeManager.AllTypeInfo
# @return a tuple of (enumTypes, dataTypes, managedTypes)
def _ConvertAllTypes(self, allTypes):
""" Convert all dynamic types to pyVmomi type definitions """
# Generate lists good for VmomiSupport.CreateXYZType
enumTypes = self._Filter(self._ConvertEnumType, allTypes.enumTypeInfo)
dataTypes = self._Filter(self._ConvertDataType, allTypes.dataTypeInfo)
managedTypes = self._Filter(self._ConvertManagedType,
allTypes.managedTypeInfo)
retAllTypes = (enumTypes, dataTypes, managedTypes)
return retAllTypes
## Create pyVmomi types from pyVmomi type definitions
#
# @param enumTypes pyVmomi enum type definitions
# @param dataTypes pyVmomi data type definitions
# @param managedTypes pyVmomi managed type definitions
def _CreateAllTypes(self, enumTypes, dataTypes, managedTypes):
""" Create pyVmomi types from pyVmomi type definitions """
# Create versions
for typeInfo in managedTypes:
name = typeInfo[0]
version = typeInfo[3]
VmomiSupport.AddVersion(version, '', '1.0', 0, name)
VmomiSupport.AddVersionParent(version, 'vmodl.version.version0')
VmomiSupport.AddVersionParent(version, 'vmodl.version.version1')
VmomiSupport.AddVersionParent(version, version)
# Create partial types
for fn, infos in (VmomiSupport.CreateEnumType, enumTypes), \
(VmomiSupport.CreateDataType, dataTypes), \
(VmomiSupport.CreateManagedType, managedTypes):
for typeInfo in infos:
try:
fn(*typeInfo)
except Exception, err:
#Ignore errors due to duplicate importing
pass
def _ConvertAnnotations(self, annotations):
""" Convert annotations to pyVmomi flags """
flags = 0
if annotations:
for annotation in annotations:
flags |= self._mapFlags.get(annotation.name, 0)
return flags
@staticmethod
def _Filter(fn, types):
""" Call fn for each non null element in types. Similiar to filter """
if types:
return [fn(prop) for prop in types if prop is not None]
else:
return []
def _ConvertParamType(self, paramType):
"""
Convert vmodl.reflect.DynamicTypeManager.ParamTypeInfo to pyVmomi param
definition
"""
if paramType:
name = paramType.name
version = paramType.version
aType = paramType.type
flags = self._ConvertAnnotations(paramType.annotation)
privId = paramType.privId
param = (name, aType, version, flags, privId)
else:
param = None
return param
def _ConvertMethodType(self, methodType):
"""
Convert vmodl.reflect.DynamicTypeManager.MethodTypeInfo to pyVmomi method
definition
"""
if methodType:
name = methodType.name
wsdlName = methodType.wsdlName
version = methodType.version
params = self._Filter(self._ConvertParamType, methodType.paramTypeInfo)
privId = methodType.privId
faults = methodType.fault
# Figure out reture info
if methodType.returnTypeInfo:
returnTypeInfo = methodType.returnTypeInfo
retFlags = self._ConvertAnnotations(returnTypeInfo.annotation)
methodRetType = returnTypeInfo.type
else:
retFlags = 0
methodRetType = "void"
if wsdlName.endswith("_Task"):
# TODO: Need a seperate task return type for task, instead of
# hardcode vim.Task as return type
retType = "vim.Task"
else:
retType = methodRetType
retInfo = (retFlags, retType, methodRetType)
method = (name, wsdlName, version, params, retInfo, privId, faults)
else:
method = None
return method
def _ConvertManagedPropertyType(self, propType):
"""
Convert vmodl.reflect.DynamicTypeManager.PropertyTypeInfo to pyVmomi
managed property definition
"""
if propType:
name = propType.name
version = propType.version
aType = propType.type
flags = self._ConvertAnnotations(propType.annotation)
privId = propType.privId
prop = (name, aType, version, flags, privId)
else:
prop = None
return prop
def _ConvertManagedType(self, managedType):
"""
Convert vmodl.reflect.DynamicTypeManager.ManagedTypeInfo to pyVmomi
managed type definition
"""
if managedType:
vmodlName = managedType.name
wsdlName = managedType.wsdlName
version = managedType.version
parent = managedType.base[0]
props = self._Filter(self._ConvertManagedPropertyType, managedType.property)
methods = self._Filter(self._ConvertMethodType, managedType.method)
moType = (vmodlName, wsdlName, parent, version, props, methods)
else:
moType = None
return moType
def _ConvertDataPropertyType(self, propType):
"""
Convert vmodl.reflect.DynamicTypeManager.PropertyTypeInfo to pyVmomi
data property definition
"""
if propType:
name = propType.name
version = propType.version
aType = propType.type
flags = self._ConvertAnnotations(propType.annotation)
prop = (name, aType, version, flags)
else:
prop = None
return prop
def _ConvertDataType(self, dataType):
"""
Convert vmodl.reflect.DynamicTypeManager.DataTypeInfo to pyVmomi data
type definition
"""
if dataType:
vmodlName = dataType.name
wsdlName = dataType.wsdlName
version = dataType.version
parent = dataType.base[0]
props = self._Filter(self._ConvertDataPropertyType, dataType.property)
doType = (vmodlName, wsdlName, parent, version, props)
else:
doType = None
return doType
def _ConvertEnumType(self, enumType):
"""
Convert vmodl.reflect.DynamicTypeManager.EnumTypeInfo to pyVmomi enum
type definition
"""
if enumType:
vmodlName = enumType.name
wsdlName = enumType.wsdlName
version = enumType.version
values = enumType.value
enumType = (vmodlName, wsdlName, version, values)
else:
enumType = None
return enumType

356
pyVmomi/Iso8601.py Normal file
View File

@@ -0,0 +1,356 @@
#!/usr/bin/env 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.
"""
This module is for ISO 8601 parsing
"""
__author__ = 'VMware, Inc.'
import time
from datetime import datetime, timedelta, tzinfo
import re
""" Regular expression to parse a subset of ISO 8601 format """
_dtExpr = re.compile(
# XMLSchema datetime. Mandatory to have - and :
# See: http://www.w3.org/TR/xmlschema-2/#isoformats
# Note: python datetime cannot handle the following:
# - leap second, ie. 0-60 seconds (not 0-59)
# - BC (negative years)
# year [-]0000..9999
r'(?P<year>-?\d{4})' \
# month 01..12
r'(-(?P<month>(0[1-9]|1[0-2]))' \
# day 01..31
r'(-(?P<day>(0[1-9]|[1-2]\d|3[01])))?)?' \
# time separator 'T'
r'(T' \
# hour 00..24
r'(?P<hour>([01]\d|2[0-4]))' \
# minute 00..59
r'((:(?P<minute>[0-5]\d))' \
# seconds 00..60 (leap second ok)
r'(:(?P<second>([0-5]\d|60))' \
# microsecond. max 16 digits
# - Should not allows trailing zeros. But python isoformat() put zeros
# after microseconds. Oh well, allows trailing zeros, quite harmless
r'(\.(?P<microsecond>\d{1,16}))?)?)?' \
# UTC 'Z', or...
r'((?P<tzutc>Z)' \
# tz [+-]00..13:0..59|14:00
r'|((?P<tzhr>[+-](([0]\d)|(1[0-3])|(?P<tzlimit>)14))' \
r'(:(?P<tzmin>(?(tzlimit)00|([0-5]\d))))?))?' \
r')?$')
""" Default date time val. Key should match the tags in _dtExpr """
_dtExprKeyDefValMap = {'year' : None, 'month' : 1, 'day' : 1,
'hour' : 0, 'minute' : 0, 'second' : 0,
'microsecond' : 0}
class TZInfo(tzinfo):
""" Timezone info class """
timedelta0 = timedelta(hours=0)
timedelta1 = timedelta(hours=1)
def __init__(self, tzname='UTC', utcOffset=None, dst=None):
self._tzname = tzname
if not utcOffset:
utcOffset = self.timedelta0
self._utcOffset = utcOffset
if not dst:
dst = None
self._dst = dst
def utcoffset(self, dt):
return self._utcOffset + self.dst(dt)
def tzname(self, dt):
return self._tzname
def dst(self, dt):
ret = self.timedelta0
if self._dst:
if self._dst[0] <= dt.replace(tzinfo=None) < self._dst[1]:
ret = self.timedelta1
return ret
class TZManager:
""" Time zone manager """
_tzInfos = {}
@staticmethod
def GetTZInfo(tzname='UTC', utcOffset=None, dst=None):
""" Get / Add timezone info """
key = (tzname, utcOffset, dst)
tzInfo = TZManager._tzInfos.get(key)
if not tzInfo:
tzInfo = TZInfo(tzname, utcOffset, dst)
TZManager._tzInfos[key] = tzInfo
return tzInfo
def ParseISO8601(datetimeStr):
"""
Parse ISO 8601 date time from string.
Returns datetime if ok, None otherwise
Note: Allows YYYY / YYYY-MM, but truncate YYYY -> YYYY-01-01,
YYYY-MM -> YYYY-MM-01
Truncate microsecond to most significant 6 digits
"""
datetimeVal = None
match = _dtExpr.match(datetimeStr)
if match:
try:
dt = {}
for key, defaultVal in _dtExprKeyDefValMap.iteritems():
val = match.group(key)
if val:
if key == 'microsecond':
val = val[:6] + '0' * (6 - len(val))
dt[key] = int(val)
elif defaultVal:
dt[key] = defaultVal
# Orig. XMLSchema don't allow all zeros year. But newer draft is ok
#if dt['year'] == 0:
# # Year cannot be all zeros
# raise Exception('Year cannot be all zeros')
# 24 is a special case. It is actually represented as next day 00:00
delta = None
if dt.get('hour', 0) == 24:
# Must be 24:00:00.0
if dt.get('minute', 0) == 0 and dt.get('second', 0) == 0 and \
dt.get('microsecond', 0) == 0:
dt['hour'] = 23
delta = timedelta(hours=1)
else:
return None
# Set tzinfo
# TODO: dst
tzInfo = None
val = match.group('tzutc')
if val:
tzInfo = TZManager.GetTZInfo()
else:
val = match.group('tzhr')
if val:
# tz hours offset
tzhr = int(val)
utcsign = val[0]
# tz minutes offset
tzmin = 0
val = match.group('tzmin')
if val:
tzmin = tzhr >= 0 and int(val) or -int(val)
# Better tzname (map UTC +-00:00 to UTC)
tzname = 'UTC'
if tzhr != 0 or tzmin != 0:
tzname += ' %s%02d:%02d' % (utcsign, abs(tzhr), abs(tzmin))
tzInfo = TZManager.GetTZInfo(tzname=tzname,
utcOffset=timedelta(hours=tzhr,
minutes=tzmin))
if tzInfo:
dt['tzinfo'] = tzInfo
datetimeVal = datetime(**dt)
if delta:
datetimeVal += delta
except Exception, e:
pass
return datetimeVal
def ISO8601Format(dt):
"""
Python datetime isoformat() has the following problems:
- leave trailing 0 at the end of microseconds (violates XMLSchema rule)
- tz print +00:00 instead of Z
- Missing timezone offset for datetime without tzinfo
"""
isoStr = dt.strftime('%Y-%m-%dT%H:%M:%S')
if dt.microsecond:
isoStr += ('.%06d' % dt.microsecond).rstrip('0')
if dt.tzinfo:
tz = dt.strftime('%z')
else:
utcOffset_minutes = -time.altzone / 60
tz = "%+.2d%.2d" % (utcOffset_minutes / 60, (abs(utcOffset_minutes) % 60))
if tz == '+0000':
return isoStr + 'Z'
elif tz:
return isoStr + tz[:3] + ':' + tz[3:]
else:
# Local offset is unknown
return isoStr + '-00:00'
# Testing
if __name__ == '__main__':
# Valid entries
for testStr in [
'1971', # 1971-01-01
'1971-11', # 1971-11-01
'1971-11-02',
'1971-11-02T23',
'1971-11-02T23Z',
'1971-11-02T23:04',
'1971-11-02T23:04Z',
'1971-11-02T23:04:15',
'1971-11-02T23:04:15Z',
'1971-11-02T23:04:15.1',
'1971-11-02T23:04:15.01',
'1971-11-02T23:04:15.023456',
'1971-11-02T23:04:15.103456Z',
'1971-11-02T23:04:15.123456+11',
'1971-11-02T23:04:15.123456-11',
'1971-11-02T23:04:15.123456+11:30',
'1971-11-02T23:04:15.123456-11:30',
'1971-11-02T23:04:15.123456+00:00', # Same as Z
'1971-11-02T23:04:15.123456-00:00', # Same as Z
'1971-01-02T23:04:15+14',
'1971-01-02T23:04:15+14:00',
'1971-01-02T23:04:15-14',
'1971-01-02T23:04:15-14:00',
# Valid: Truncate microsec to 6 digits
'1971-01-02T23:04:15.123456891+11',
'1971-01-02T24', # 24 is valid. It should represent the 00:00 the
# next day
'1971-01-02T24:00',
'1971-01-02T24:00:00',
'1971-01-02T24:00:00.0',
# Should NOT be valid but python isoformat adding trailing zeros
'1971-01-02T23:04:15.123430', # Microseconds ends in zero
'1971-01-02T23:04:15.0', # Microseconds ends in zero
# Should be valid but python datetime don't support it
#'2005-12-31T23:59:60Z', # Leap second
#'-0001', # BC 1
]:
dt = ParseISO8601(testStr)
if dt == None:
print 'Failed to parse (%s)' % testStr
assert(False)
# Make sure we can translate back
isoformat = ISO8601Format(dt)
dt1 = ParseISO8601(isoformat)
if dt.tzinfo is None:
dt = dt.replace(tzinfo=dt1.tzinfo)
if dt1 != dt:
print 'ParseISO8601 -> ISO8601Format -> ParseISO8601 failed (%s)' % testStr
assert(False)
# Make sure we can parse python isoformat()
dt2 = ParseISO8601(dt.isoformat())
if dt2 == None:
print 'ParseISO8601("%s".isoformat()) failed' % testStr
assert(False)
print testStr, '->', dt, isoformat
# Basic form
for testStr in [
'197111', # 1971-11-01
'19711102',
'19711102T23',
'19711102T23Z',
'19711102T2304',
'19711102T2304Z',
'19711102T230415',
'19711102T230415Z',
'19711102T230415.123456',
'19711102T230415.123456Z',
'19711102T230415.123456+11',
'19711102T230415.123456-11',
'19711102T230415.123456+1130',
'19711102T230415.123456-1130',
]:
# Reject for now
dt = ParseISO8601(testStr)
if dt != None:
print 'ParseISO8601 (%s) should fail, but it did not' % testStr
assert(False)
#print testStr, '->', dt
#assert(dt != None)
# Invalid entries
for testStr in [
# Xml schema reject year 0
'0000', # 0 years are not allowed
'+0001', # Leading + is not allowed
'', # Empty datetime str
'09', # Years must be at least 4 digits
'1971-01-02T', # T not follow by time
'1971-01-02TZ', # T not follow by time
'1971-01-02T+10', # T not follow by time
'1971-01-02T-10', # T not follow by time
'1971-01-02T23:', # extra :
'1971-01-02T23:04:', # extra :
'1971-01-02T23:0d', # 0d
'1971-01-02T23:04:15.', # Dot not follows by microsec
'1971-01-02+12', # time without T
'1971Z', # Z without T
'1971-01-02T23:04:15.123456Z+11', # Z follows by +
'1971-01-02T23:04:15.123456Z-11', # Z follows by -
'1971-01-02T23:04:15.123456+:30', # extra :
'1971-01-02T23:04:15.123456+30:', # extra :
'1971-01-02T23:04:15.01234567890123456789', # Too many microseconds digits
# Python isoformat leave trailing zeros in microseconds
# Relax regular expression to accept it
#'1971-01-02T23:04:15.123430', # Microseconds ends in zero
#'1971-01-02T23:04:15.0', # Microseconds ends in zero
# Timezone must be between +14 / -14
'1971-01-02T23:04:15+15',
'1971-01-02T23:04:15-15',
'1971-01-02T23:04:15+14:01',
'1971-01-02T23:04:15-14:01',
# Mix basic form with extended format
'197101-02T23:04:15.123456',
'19710102T23:04:15.123456',
'19710102T230415.123456+11:30',
'1971-01-02T230415.123456',
'1971-01-02T23:04:15.123456+1130',
# Error captured by datetime class
'1971-00-02', # Less than 1 month
'1971-13-02', # Larger than 12 months
'1971-01-00', # Less than 1 day
'1971-11-32', # Larger than 30 days for Nov
'1971-12-32', # Larger than 31 days
'1971-01-02T24:01', # Larger than 23 hr
'1971-01-02T23:61', # Larger than 60 min
'1971-01-02T23:60:61', # Larger than 61 sec
]:
dt = ParseISO8601(testStr)
if dt != None:
print 'ParseISO8601 (%s) should fail, but it did not' % testStr
assert(False)

View File

@@ -0,0 +1,120 @@
#!/usr/bin/env 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.
"""
This module provides convinent fns related to ManagedMethodExecutor
"""
__author__ = "VMware, Inc."
from pyVmomi import VmomiSupport, SoapAdapter, vmodl
from SoapAdapter import SoapStubAdapterBase, Serialize, Deserialize
## ManagedMethodExecutor soap stub adapter
#
class MMESoapStubAdapter(SoapStubAdapterBase):
""" Managed method executor stub adapter """
## Constructor
#
# The endpoint can be specified individually as either a host/port
# combination, or with a URL (using a url= keyword).
#
# @param self self
# @param mme managed method executor
def __init__(self, mme):
stub = mme._stub
SoapStubAdapterBase.__init__(self, version=stub.version)
self.mme = mme
## Compute the version information for the specified namespace
#
# @param ns the namespace
def ComputeVersionInfo(self, version):
SoapStubAdapterBase.ComputeVersionInfo(self, version)
self.versionId = self.versionId[1:-1]
## Invoke a managed method, with _ExecuteSoap. Wohooo!
#
# @param self self
# @param mo the 'this'
# @param info method info
# @param args arguments
def InvokeMethod(self, mo, info, args):
# Serialize parameters to soap parameters
methodArgs = None
if info.params:
methodArgs = vmodl.Reflect.ManagedMethodExecutor.SoapArgument.Array()
for param, arg in zip(info.params, args):
if arg is not None:
# Serialize parameters to soap snippets
soapVal = Serialize(val=arg, info=param, version=self.version)
# Insert argument
soapArg = vmodl.Reflect.ManagedMethodExecutor.SoapArgument(
name=param.name, val=soapVal)
methodArgs.append(soapArg)
moid = mo._GetMoId()
version = self.versionId
methodName = VmomiSupport.GetVmodlName(info.type) + "." + info.name
# Execute method
result = self.mme.ExecuteSoap(moid=moid,
version=version,
method=methodName,
argument=methodArgs)
return self._DeserializeExecutorResult(result, info.result)
## Invoke a managed property accessor
#
# @param self self
# @param mo the 'this'
# @param info property info
def InvokeAccessor(self, mo, info):
moid = mo._GetMoId()
version = self.versionId
prop = info.name
# Fetch property
result = self.mme.FetchSoap(moid=moid, version=version, prop=prop)
return self._DeserializeExecutorResult(result, info.type)
## Deserialize result from ExecuteSoap / FetchSoap
#
# @param self self
# @param result result from ExecuteSoap / FetchSoap
# @param resultType Expected result type
def _DeserializeExecutorResult(self, result, resultType):
obj = None
if result:
# Parse the return soap snippet. If fault, raise exception
if result.response:
# Deserialize back to result
obj = Deserialize(result.response, resultType, stub=self)
elif result.fault:
# Deserialize back to fault (or vmomi fault)
fault = Deserialize(result.fault.faultDetail,
object,
stub=self)
# Silent pylint
raise fault # pylint: disable-msg=E0702
else:
# Unexpected: result should have either response or fault
msg = "Unexpected execute/fetchSoap error"
reason = "execute/fetchSoap did not return response or fault"
raise vmodl.Fault.SystemError(msg=msg, reason=reason)
return obj

2876
pyVmomi/ServerObjects.py Normal file

File diff suppressed because one or more lines are too long

1490
pyVmomi/SoapAdapter.py Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,41 @@
# 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.
from VmomiSupport import GetVmodlType
class StubAdapterAccessorMixin:
def __init__(self):
self._pc = None
self._pcType = GetVmodlType("vmodl.query.PropertyCollector")
self._siType = GetVmodlType("vim.ServiceInstance")
## Retrieve a managed property
#
# @param self self
# @param mo managed object
# @param info property info
def InvokeAccessor(self, mo, info):
filterSpec = self._pcType.FilterSpec(
objectSet=[self._pcType.ObjectSpec(obj=mo, skip=False)],
propSet=[self._pcType.PropertySpec(all=False, type=mo.__class__,
pathSet=[info.name])],
)
## Cache the property collector if it isn't already
# No need to lock _pc since multiple instances of PropertyCollector on
# the client will talk to the same instance on the server.
if not self._pc:
si = self._siType("ServiceInstance", self)
self._pc = si.RetrieveContent().propertyCollector
return self._pc.RetrieveContents([filterSpec])[0].propSet[0].val

36
pyVmomi/Version.py Normal file
View File

@@ -0,0 +1,36 @@
# 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.
from VmomiSupport import nsMap, versionMap, versionIdMap, serviceNsMap, parentMap
## Add an API version
def AddVersion(version, ns, versionId='', isLegacy=0, serviceNs=''):
if not ns:
ns = serviceNs
if not (version in parentMap):
nsMap[version] = ns
if len(versionId) > 0:
versionMap[ns + '/' + versionId] = version
if isLegacy or ns is "":
versionMap[ns] = version
versionIdMap[version] = versionId
if not serviceNs:
serviceNs = ns
serviceNsMap[version] = serviceNs
parentMap[version] = {}
## Check if a version is a child of another
def IsChildVersion(child, parent):
return child == parent or parent in parentMap[child]

1630
pyVmomi/VmomiSupport.py Normal file

File diff suppressed because it is too large Load Diff

227
pyVmomi/__init__.py Normal file
View File

@@ -0,0 +1,227 @@
# 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.
# In VmomiSupport, to support dynamic type loading, all the data types are
# wrapped around using a meta type which can intercept attribute access and
# load the necessary nested classes. This can be implemented only in python 2.5
# version or more.
import sys
if sys.version_info < (2,5):
sys.stderr.write("You need Python 2.5 or later to import pyVmomi module\n")
sys.exit(1)
import VmomiSupport
import CoreTypes
try:
import ReflectTypes
except ImportError:
pass
try:
import ServerObjects
except ImportError:
pass
try:
import InternalServerObjects
except ImportError:
pass
# Import all the known product-specific types
# XXX: Make this search the package for types?
try:
import DrObjects
except ImportError:
pass
try:
import DrextObjects
except ImportError:
pass
try:
import HbrReplicaTypes
except ImportError:
pass
try:
import HmsObjects
except ImportError:
pass
try:
import HostdObjects
except ImportError:
pass
try:
import VpxObjects
except ImportError:
pass
try:
import VorbTypes
except ImportError:
pass
try:
import DodoTypes
except ImportError:
pass
try:
import VmwauthproxyTypes
except ImportError:
pass
try:
import DmsTypes
except ImportError:
pass
try:
import OmsTypes
except ImportError:
pass
try:
import HmoTypes
except ImportError:
pass
try:
import CimsfccTypes
except ImportError:
pass
try:
import TaskupdaterTypes
except ImportError:
pass
try:
import ImgFactTypes
except ImportError:
pass
try:
import VpxapiTypes
except ImportError:
pass
try:
import CsiObjects
except ImportError:
pass
try:
import HostdTypes
except ImportError:
pass
try:
import TaggingObjects
except ImportError:
pass
try:
import NfcTypes
except ImportError:
pass
try:
import SmsObjects
except ImportError:
pass
try:
import SpsObjects
except ImportError:
pass
try:
import DataserviceObjects
except ImportError:
pass
# Start of update manager specific types
try:
import IntegrityObjects
except ImportError:
pass
try:
import SysimageObjects
except ImportError:
pass
# End of update manager specific types
try:
import RbdTypes
except ImportError:
pass
# Import Profile based management specific VMODL
try:
import PbmObjects
except ImportError:
pass
try:
import CisLicenseTypes
except ImportError:
pass
try:
import TestTypes
except ImportError:
pass
try:
import SsoTypes
except ImportError:
pass
try:
import CisCmTypes
except ImportError:
pass
try:
import DataserviceTypes
except ImportError:
pass
# All data object types and fault types have DynamicData as an ancestor
# As well load it proactively.
# Note: This should be done before importing SoapAdapter as it uses
# some fault types
VmomiSupport.GetVmodlType("vmodl.DynamicData")
from SoapAdapter import SoapStubAdapter, StubAdapterBase, SoapCmdStubAdapter, \
SessionOrientedStub
types = VmomiSupport.types
# This will allow files to use Create** functions
# directly from pyVmomi
CreateEnumType = VmomiSupport.CreateEnumType
CreateDataType = VmomiSupport.CreateDataType
CreateManagedType = VmomiSupport.CreateManagedType
# For all the top level names, creating a LazyModule object
# in the global namespace of pyVmomi. Files can just import the
# top level namespace and we will figure out what to load and when
# Examples:
# ALLOWED: from pyVmomi import vim
# NOT ALLOWED: from pyVmomi import vim.host
_globals = globals()
for name in VmomiSupport._topLevelNames:
upperCaseName = VmomiSupport.Capitalize(name)
obj = VmomiSupport.LazyModule(name)
_globals[name] = obj
if VmomiSupport._allowCapitalizedNames:
_globals[upperCaseName] = obj
if not hasattr(VmomiSupport.types, name):
setattr(VmomiSupport.types, name, obj)
if VmomiSupport._allowCapitalizedNames:
setattr(VmomiSupport.types, upperCaseName, obj)
del _globals

View File

@@ -0,0 +1,17 @@
# 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.
allowGetSet = False
allowCapitalizedNames = False

4
pyvmomi.egg-info/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
PKG-INFO
sources.txt
dependency_links.txt
zip-safe

View File

@@ -0,0 +1,2 @@
pyVim
pyVmomi

110
sample/getallvms.py Normal file
View File

@@ -0,0 +1,110 @@
#!/usr/bin/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.
"""
Python program for listing the vms on an ESX / vCenter host
"""
from optparse import OptionParser, make_option
from pyVim.connect import SmartConnect, Disconnect
from pyVmomi import vmodl
import sys
import atexit
def GetOptions():
"""
Supports the command-line arguments listed below.
"""
_CMD_OPTIONS_LIST = [
make_option("-h", "--host",
help="remote host to connect to"),
make_option("-o", "--port",
default=443,
help="Port"),
make_option("-u", "--user",
default="root",
help="User name to use when connecting to host"),
make_option("-p", "--password",
help="Password to use when connecting to host"),
make_option("-?", "--help", action="store_true",
help="Help"),
]
_STR_USAGE = "%prog [options]"
parser = OptionParser(option_list=_CMD_OPTIONS_LIST,
usage=_STR_USAGE,
add_help_option=False)
(options, _) = parser.parse_args()
return options
def PrintVmInfo(vm):
"""
Print information for a particular virtual machine.
"""
summary = vm.summary
print "Name : ", summary.config.name
print "Path : ", summary.config.vmPathName
print "Guest : ", summary.config.guestFullName
annotation = summary.config.annotation
if annotation != None and annotation != "":
print "Annotation : ", annotation
print "State : ", summary.runtime.powerState
if summary.guest != None:
ip = summary.guest.ipAddress
if ip != None and ip != "":
print "IP : ", ip
if summary.runtime.question != None:
print "Question : ", summary.runtime.question.text
print ""
def main():
"""
Simple command-line program for listing the virtual machines on a system.
"""
options = GetOptions()
try:
si = SmartConnect(host=options.host,
user=options.user,
pwd=options.password,
port=int(options.port))
if not si:
print "Could not connect to the specified host"
return -1
atexit.register(Disconnect, si)
content = si.RetrieveContent()
datacenter = content.rootFolder.childEntity[0]
vmFolder = datacenter.vmFolder
vmList = vmFolder.childEntity
for vm in vmList:
PrintVmInfo(vm)
except vmodl.MethodFault, e:
print "Caught vmodl fault : " + e.msg
return -1
except Exception, e:
print "Caught exception : " + str(e)
return -1
return 0
# Start program
if __name__ == "__main__":
main()

154
sample/poweronvm.py Executable file
View File

@@ -0,0 +1,154 @@
#!/usr/bin/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.
"""
Python program for powering on vms on a host on which hostd is running
"""
from optparse import OptionParser, make_option
from pyVim.connect import SmartConnect, Disconnect
from pyVmomi import vim, vmodl
import sys
import atexit
def GetOptions():
"""
Supports the command-line arguments listed below.
"""
_CMD_OPTIONS_LIST = [
make_option("-h", "--host",
help="remote host to connect to"),
make_option("-o", "--port",
default=443,
help="Port"),
make_option("-u", "--user",
default="root",
help="User name to use when connecting to host"),
make_option("-p", "--password",
help="Password to use when connecting to host"),
make_option("-v", "--vmname", default=[], action="append",
help="Name of the Virtual Machine to power on"),
make_option("-?", "--help", action="store_true",
help="Help"),
]
_STR_USAGE = "%prog [options]"
parser = OptionParser(option_list=_CMD_OPTIONS_LIST,
usage=_STR_USAGE,
add_help_option=False)
(options, _) = parser.parse_args()
return options
def WaitForTasks(tasks, si):
"""
Given the service instance si and tasks, it returns after all the
tasks are complete
"""
pc = si.content.propertyCollector
taskList = [str(task) for task in tasks]
# Create filter
objSpecs = [vmodl.query.PropertyCollector.ObjectSpec(obj=task)
for task in tasks]
propSpec = vmodl.query.PropertyCollector.PropertySpec(type=vim.Task,
pathSet=[], all=True)
filterSpec = vmodl.query.PropertyCollector.FilterSpec()
filterSpec.objectSet = objSpecs
filterSpec.propSet = [propSpec]
filter = pc.CreateFilter(filterSpec, True)
try:
version, state = None, None
# Loop looking for updates till the state moves to a completed state.
while len(taskList):
update = pc.WaitForUpdates(version)
for filterSet in update.filterSet:
for objSet in filterSet.objectSet:
task = objSet.obj
for change in objSet.changeSet:
if change.name == 'info':
state = change.val.state
elif change.name == 'info.state':
state = change.val
else:
continue
if not str(task) in taskList:
continue
if state == vim.TaskInfo.State.success:
# Remove task from taskList
taskList.remove(str(task))
elif state == vim.TaskInfo.State.error:
raise task.info.error
# Move to next version
version = update.version
finally:
if filter:
filter.Destroy()
# Start program
def main():
"""
Simple command-line program for powering on virtual machines on a system.
"""
options = GetOptions()
try:
vmnames = options.vmname
if not len(vmnames):
print "No virtual machine specified for poweron"
sys.exit()
si = SmartConnect(host=options.host,
user=options.user,
pwd=options.password,
port=int(options.port))
if not si:
print "Cannot connect to Host"
sys.exit()
atexit.register(Disconnect, si)
# Retreive the list of Virtual Machines from the invetory objects
# under the rootFolder
content = si.content
objView = content.viewManager.CreateContainerView(content.rootFolder,
[vim.VirtualMachine],
True)
vmList = objView.view
objView.Destroy()
# Find the vm and power it on
tasks = [vm.PowerOn() for vm in vmList if vm.name in vmnames]
# Wait for power on to complete
WaitForTasks(tasks, si)
print "Virtual Machine(s) have been powered on successfully"
except vmodl.MethodFault, e:
print "Caught vmodl fault : " + e.msg
except Exception, e:
print "Caught Exception : " + str(e)
# Start program
if __name__ == "__main__":
main()

42
setup.py Normal file
View File

@@ -0,0 +1,42 @@
# VMware vSphere Python SDK
# Copyright (c) 2009-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.
from setuptools import setup
import os
def read(fname):
return open(os.path.join(os.path.dirname(__file__), fname)).read()
setup(
name='pyvmomi',
version='5.1.0',
description='VMware vSphere Python SDK',
author='VMware, Inc.',
author_email='jhu@vmware.com',
url='https://github.com/vmware/pyvmomi',
packages=['pyVmomi', 'pyVim'],
license='Apache',
long_description=read('README.md'),
classifiers=[
"License :: OSI Approved :: Apache Software License",
"Development Status :: 4 - Beta",
"Environment :: No Input/Output (Daemon)",
"Intended Audience :: Information Technology",
"Intended Audience :: System Administrators",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: System :: Distributed Computing"
],
zip_safe=True
)