Merge pull request #89 from vmware/python3

Support for Python 3
This commit is contained in:
Shawn Hartsock
2014-07-28 15:06:50 -04:00
17 changed files with 602 additions and 297 deletions

View File

@@ -3,6 +3,8 @@ python:
- "2.6" - "2.6"
- "2.7" - "2.7"
- "pypy" - "pypy"
- "3.3"
- "3.4"
before_install: before_install:
- if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install unittest2; fi - if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install unittest2; fi
@@ -10,6 +12,6 @@ before_install:
- pip install -r test-requirements.txt - pip install -r test-requirements.txt
install: install:
- python setup.py -q install - python setup.py install
script: python setup.py test script: python setup.py test

View File

@@ -25,23 +25,19 @@ Detailed description (for [e]pydoc goes here).
""" """
from six import reraise from six import reraise
import sys import sys
import threading
import thread
import types
import httplib
import socket
import time
import itertools
import re import re
try:
from xml.etree import ElementTree
except ImportError:
from elementtree import ElementTree
from xml.parsers.expat import ExpatError
import requests
from requests.auth import HTTPBasicAuth
from pyVmomi import vim, vmodl, SoapStubAdapter, SessionOrientedStub from pyVmomi import vim, vmodl, SoapStubAdapter, SessionOrientedStub
from pyVmomi.VmomiSupport import nsMap, versionIdMap, versionMap, IsChildVersion from pyVmomi.VmomiSupport import nsMap, versionIdMap, versionMap, IsChildVersion
from pyVmomi.VmomiSupport import GetServiceVersions 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 urllib2
""" """
@@ -57,7 +53,6 @@ Global (thread-shared) ServiceInstance
@todo: Get rid of me? @todo: Get rid of me?
""" """
class closing(object): class closing(object):
""" """
Helper class for using closable objects in a 'with' statement, Helper class for using closable objects in a 'with' statement,
@@ -227,7 +222,7 @@ def Connect(host='localhost', port=443, user='root', pwd='',
host = info.group(1)[1:-1] host = info.group(1)[1:-1]
if info.group(2) is not None: if info.group(2) is not None:
port = int(info.group(2)[1:]) port = int(info.group(2)[1:])
except ValueError, ve: except ValueError as ve:
pass pass
if namespace: if namespace:
@@ -256,7 +251,7 @@ def Disconnect(si):
def GetLocalTicket(si, user): def GetLocalTicket(si, user):
try: try:
sessionManager = si.content.sessionManager sessionManager = si.content.sessionManager
except Exception, e: except Exception as e:
if type(e).__name__ == 'ExpatError': if type(e).__name__ == 'ExpatError':
msg = 'Malformed response while querying for local ticket: "%s"' % e msg = 'Malformed response while querying for local ticket: "%s"' % e
raise vim.fault.HostConnectFault(msg=msg) raise vim.fault.HostConnectFault(msg=msg)
@@ -312,14 +307,17 @@ def __Login(host, port, user, pwd, service, adapter, version, path,
content = si.RetrieveContent() content = si.RetrieveContent()
except vmodl.MethodFault: except vmodl.MethodFault:
raise raise
except Exception, e: except Exception as e:
# NOTE (hartsock): preserve the traceback for diagnostics # NOTE (hartsock): preserve the traceback for diagnostics
# pulling and preserving the traceback makes diagnosing connection # pulling and preserving the traceback makes diagnosing connection
# failures easier since the fault will also include where inside the # failures easier since the fault will also include where inside the
# library the fault occurred. Without the traceback we have no idea # library the fault occurred. Without the traceback we have no idea
# why the connection failed beyond the message string. # why the connection failed beyond the message string.
(type, value, traceback) = sys.exc_info() (type, value, traceback) = sys.exc_info()
if traceback:
reraise(vim.fault.HostConnectFault(msg=str(e)), None, traceback) reraise(vim.fault.HostConnectFault(msg=str(e)), None, traceback)
else:
raise vim.fault.HostConnectFault(msg=str(e))
# Get a ticket if we're connecting to localhost and password is not specified # Get a ticket if we're connecting to localhost and password is not specified
if host == 'localhost' and not pwd: if host == 'localhost' and not pwd:
@@ -334,7 +332,7 @@ def __Login(host, port, user, pwd, service, adapter, version, path,
x = content.sessionManager.Login(user, pwd, None) x = content.sessionManager.Login(user, pwd, None)
except vim.fault.InvalidLogin: except vim.fault.InvalidLogin:
raise raise
except Exception, e: except Exception as e:
raise raise
return si, stub return si, stub
@@ -350,7 +348,7 @@ def __Logout(si):
if si: if si:
content = si.RetrieveContent() content = si.RetrieveContent()
content.sessionManager.Logout() content.sessionManager.Logout()
except Exception, e: except Exception as e:
pass pass
@@ -417,7 +415,7 @@ class SmartConnection(object):
def __GetServiceVersionDescription(protocol, server, port, path): def __GetServiceVersionDescription(protocol, server, port, path):
""" """
Private method that returns an ElementTree describing the API versions Private method that returns a root from an ElementTree describing the API versions
supported by the specified server. The result will be vimServiceVersions.xml supported by the specified server. The result will be vimServiceVersions.xml
if it exists, otherwise vimService.wsdl if it exists, otherwise None. if it exists, otherwise vimService.wsdl if it exists, otherwise None.
@@ -431,26 +429,23 @@ def __GetServiceVersionDescription(protocol, server, port, path):
@type path: string @type path: string
""" """
tree = ElementTree()
url = "%s://%s:%s/%s/vimServiceVersions.xml" % (protocol, server, port, path) url = "%s://%s:%s/%s/vimServiceVersions.xml" % (protocol, server, port, path)
try: try:
with closing(urllib2.urlopen(url)) as sock: sock = requests.get(url, verify=False)
if sock.getcode() == 200: if sock.status_code == 200:
tree.parse(sock) tree = ElementTree.fromstring(sock.content)
return tree return tree
except ExpatError: except ExpatError:
pass pass
url = "%s://%s:%s/%s/vimService.wsdl" % (protocol, server, port, path) url = "%s://%s:%s/%s/vimService.wsdl" % (protocol, server, port, path)
try: try:
with closing(urllib2.urlopen(url)) as sock: sock = requests.get(url, verify=False)
if sock.getcode() == 200: if sock.status_code == 200:
tree.parse(sock) tree = ElementTree.fromstring(sock.content)
return tree return tree
except ExpatError: except ExpatError:
pass pass
return None return None
@@ -465,15 +460,15 @@ def __VersionIsSupported(desiredVersion, serviceVersionDescription):
@param desiredVersion: The version we want to see if the server supports @param desiredVersion: The version we want to see if the server supports
(eg. vim.version.version2. (eg. vim.version.version2.
@type desiredVersion: string @type desiredVersion: string
@param serviceVersionDescription: An ElementTree for vimServiceVersions.xml @param serviceVersionDescription: A root ElementTree for vimServiceVersions.xml
or vimService.wsdl. or vimService.wsdl.
@type serviceVersionDescription: ElementTree @type serviceVersionDescription: root ElementTree
""" """
root = serviceVersionDescription.getroot() root = serviceVersionDescription
if root.tag == 'namespaces': if root.tag == 'namespaces':
# serviceVersionDescription appears to be a vimServiceVersions.xml document # serviceVersionDescription appears to be a vimServiceVersions.xml document
if root.get('version') <> '1.0': if root.get('version') != '1.0':
raise RuntimeError('vimServiceVersions.xml has version %s,' \ raise RuntimeError('vimServiceVersions.xml has version %s,' \
' which is not understood' % (root.get('version'))) ' which is not understood' % (root.get('version')))
desiredVersionId = versionIdMap[desiredVersion] desiredVersionId = versionIdMap[desiredVersion]
@@ -599,11 +594,7 @@ def OpenUrlWithBasicAuth(url, user='root', pwd=''):
the specified credentials to the server as part of the request. the specified credentials to the server as part of the request.
Returns the response as a file-like object. Returns the response as a file-like object.
""" """
pwMgr = urllib2.HTTPPasswordMgrWithDefaultRealm() return requests.get(url, auth=HTTPBasicAuth(user, pwd), verify=False)
pwMgr.add_password(None, url, user, pwd)
handler = urllib2.HTTPBasicAuthHandler(pwMgr)
opener = urllib2.build_opener(handler)
return opener.open(url)
def OpenPathWithStub(path, stub): def OpenPathWithStub(path, stub):
""" """
@@ -623,8 +614,8 @@ def OpenPathWithStub(path, stub):
raise vmodl.fault.NotSupported() raise vmodl.fault.NotSupported()
hostPort = stub.host hostPort = stub.host
url = '%s://%s%s' % (protocol, hostPort, path) url = '%s://%s%s' % (protocol, hostPort, path)
request = urllib2.Request(url) headers = {}
if stub.cookie: if stub.cookie:
request.add_header('Cookie', stub.cookie) headers["Cookie"] = stub.cookie
return urllib2.urlopen(request) return requests.get(url, headers=headers, verify=False)

View File

@@ -12,9 +12,10 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from __future__ import absolute_import
# ******* WARNING - AUTO GENERATED CODE - DO NOT EDIT ******* # ******* WARNING - AUTO GENERATED CODE - DO NOT EDIT *******
from VmomiSupport import CreateDataType, CreateManagedType, CreateEnumType, AddVersion, AddVersionParent, F_LINK, F_LINKABLE, F_OPTIONAL from pyVmomi.VmomiSupport import CreateDataType, CreateManagedType, CreateEnumType, AddVersion, AddVersionParent, F_LINK, F_LINKABLE, F_OPTIONAL
AddVersion("vmodl.query.version.version1", "", "", 0, "vim25") AddVersion("vmodl.query.version.version1", "", "", 0, "vim25")
AddVersion("vmodl.query.version.version2", "", "", 0, "vim25") AddVersion("vmodl.query.version.version2", "", "", 0, "vim25")

View File

@@ -14,6 +14,8 @@
# limitations under the License. # limitations under the License.
## Diff any two objects ## Diff any two objects
from six import text_type
from six import u
from pyVmomi import VmomiSupport, types from pyVmomi import VmomiSupport, types
import itertools import itertools
@@ -33,7 +35,7 @@ def IsPrimitiveType(obj):
isinstance(obj, types.short) or isinstance(obj, types.int) or isinstance(obj, types.short) or isinstance(obj, types.int) or
isinstance(obj, types.double) or isinstance(obj, types.float) or isinstance(obj, types.double) or isinstance(obj, types.float) or
isinstance(obj, types.long) or isinstance(obj, types.str) or isinstance(obj, types.long) or isinstance(obj, types.str) or
isinstance(obj, unicode) or isinstance(obj, text_type) or
isinstance(obj, types.PropertyPath) or isinstance(obj, types.PropertyPath) or
isinstance(obj, types.ManagedMethod) or isinstance(obj, types.ManagedMethod) or
isinstance(obj, types.datetime) or isinstance(obj, types.datetime) or

View File

@@ -45,7 +45,7 @@ class DynamicTypeImporter:
if self.hostSystem: if self.hostSystem:
try: try:
dynTypeMgr = self.hostSystem.RetrieveDynamicTypeManager() dynTypeMgr = self.hostSystem.RetrieveDynamicTypeManager()
except vmodl.fault.MethodNotFound, err: except vmodl.fault.MethodNotFound as err:
pass pass
if not dynTypeMgr: if not dynTypeMgr:
@@ -139,7 +139,7 @@ class DynamicTypeConstructor:
for typeInfo in infos: for typeInfo in infos:
try: try:
fn(*typeInfo) fn(*typeInfo)
except Exception, err: except Exception as err:
#Ignore errors due to duplicate importing #Ignore errors due to duplicate importing
pass pass

View File

@@ -14,12 +14,14 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from __future__ import print_function
# TODO (hartsocks): Introduce logging to remove the need for print function.
""" """
This module is for ISO 8601 parsing This module is for ISO 8601 parsing
""" """
__author__ = 'VMware, Inc.' __author__ = 'VMware, Inc.'
from six import iteritems
import time import time
from datetime import datetime, timedelta, tzinfo from datetime import datetime, timedelta, tzinfo
import re import re
@@ -118,7 +120,7 @@ def ParseISO8601(datetimeStr):
if match: if match:
try: try:
dt = {} dt = {}
for key, defaultVal in _dtExprKeyDefValMap.iteritems(): for key, defaultVal in iteritems(_dtExprKeyDefValMap):
val = match.group(key) val = match.group(key)
if val: if val:
if key == 'microsecond': if key == 'microsecond':
@@ -176,7 +178,7 @@ def ParseISO8601(datetimeStr):
datetimeVal = datetime(**dt) datetimeVal = datetime(**dt)
if delta: if delta:
datetimeVal += delta datetimeVal += delta
except Exception, e: except Exception as e:
pass pass
return datetimeVal return datetimeVal
@@ -253,7 +255,7 @@ if __name__ == '__main__':
]: ]:
dt = ParseISO8601(testStr) dt = ParseISO8601(testStr)
if dt == None: if dt == None:
print 'Failed to parse (%s)' % testStr print('Failed to parse ({0})'.format(testStr))
assert(False) assert(False)
# Make sure we can translate back # Make sure we can translate back
@@ -262,16 +264,16 @@ if __name__ == '__main__':
if dt.tzinfo is None: if dt.tzinfo is None:
dt = dt.replace(tzinfo=dt1.tzinfo) dt = dt.replace(tzinfo=dt1.tzinfo)
if dt1 != dt: if dt1 != dt:
print 'ParseISO8601 -> ISO8601Format -> ParseISO8601 failed (%s)' % testStr print('ParseISO8601 -> ISO8601Format -> ParseISO8601 failed ({0})'.format(testStr))
assert(False) assert(False)
# Make sure we can parse python isoformat() # Make sure we can parse python isoformat()
dt2 = ParseISO8601(dt.isoformat()) dt2 = ParseISO8601(dt.isoformat())
if dt2 == None: if dt2 == None:
print 'ParseISO8601("%s".isoformat()) failed' % testStr print('ParseISO8601("{0}".isoformat()) failed'.format(testStr))
assert(False) assert(False)
print testStr, '->', dt, isoformat print(testStr, '->', dt, isoformat)
# Basic form # Basic form
for testStr in [ for testStr in [
@@ -293,7 +295,7 @@ if __name__ == '__main__':
# Reject for now # Reject for now
dt = ParseISO8601(testStr) dt = ParseISO8601(testStr)
if dt != None: if dt != None:
print 'ParseISO8601 (%s) should fail, but it did not' % testStr print('ParseISO8601 ({0}) should fail, but it did not'.format(testStr))
assert(False) assert(False)
#print testStr, '->', dt #print testStr, '->', dt
#assert(dt != None) #assert(dt != None)
@@ -352,5 +354,5 @@ if __name__ == '__main__':
]: ]:
dt = ParseISO8601(testStr) dt = ParseISO8601(testStr)
if dt != None: if dt != None:
print 'ParseISO8601 (%s) should fail, but it did not' % testStr print('ParseISO8601 ({0}) should fail, but it did not'.format(testStr))
assert(False) assert(False)

View File

@@ -12,9 +12,10 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from __future__ import absolute_import
# ******* WARNING - AUTO GENERATED CODE - DO NOT EDIT ******* # ******* WARNING - AUTO GENERATED CODE - DO NOT EDIT *******
from VmomiSupport import CreateDataType, CreateManagedType, CreateEnumType, AddVersion, AddVersionParent, F_LINK, F_LINKABLE, F_OPTIONAL from pyVmomi.VmomiSupport import CreateDataType, CreateManagedType, CreateEnumType, AddVersion, AddVersionParent, F_LINK, F_LINKABLE, F_OPTIONAL
AddVersion("vim.version.version1", "vim2", "2.0", 1, "vim25") AddVersion("vim.version.version1", "vim2", "2.0", 1, "vim25")
AddVersion("vim.version.version2", "vim25", "2.5", 0, "vim25") AddVersion("vim.version.version2", "vim25", "2.5", 0, "vim25")

View File

@@ -1,5 +1,5 @@
# VMware vSphere Python SDK # VMware vSphere Python SDK
# Copyright (c) 2008-2014 VMware, Inc. All Rights Reserved. # Copyright (c) 2008-2013 VMware, Inc. All Rights Reserved.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@@ -12,23 +12,35 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from __future__ import absolute_import
from six import PY2
from six import PY3
from six.moves import http_client from six.moves import http_client
if PY3:
long = int
basestring = str
from six import u
import sys import sys
import os import os
import time
import socket import socket
import subprocess import subprocess
import thread import time
import urlparse from six.moves.urllib.parse import urlparse
from datetime import datetime from datetime import datetime
from xml.parsers.expat import ParserCreate from xml.parsers.expat import ParserCreate
# We have our own escape functionality. # We have our own escape functionality.
# from xml.sax.saxutils import escape # from xml.sax.saxutils import escape
if PY2:
from cStringIO import StringIO from cStringIO import StringIO
from VmomiSupport import *
from StubAdapterAccessorImpl import StubAdapterAccessorMixin if PY3:
import Iso8601 from io import StringIO
from pyVmomi.VmomiSupport import *
from pyVmomi.StubAdapterAccessorImpl import StubAdapterAccessorMixin
import pyVmomi.Iso8601
import base64 import base64
from xml.parsers.expat import ExpatError from xml.parsers.expat import ExpatError
import copy import copy
@@ -46,41 +58,41 @@ CONNECTION_POOL_IDLE_TIMEOUT_SEC = 900
NS_SEP = " " NS_SEP = " "
XML_ENCODING = 'UTF-8' XML_ENCODING = 'UTF-8'
XML_HEADER = '<?xml version="1.0" encoding="%s"?>' % XML_ENCODING XML_HEADER = '<?xml version="1.0" encoding="{0}"?>'.format(XML_ENCODING)
XMLNS_SOAPENC = "http://schemas.xmlsoap.org/soap/encoding/" XMLNS_SOAPENC = "http://schemas.xmlsoap.org/soap/encoding/"
XMLNS_SOAPENV = "http://schemas.xmlsoap.org/soap/envelope/" XMLNS_SOAPENV = "http://schemas.xmlsoap.org/soap/envelope/"
XSI_TYPE = XMLNS_XSI + NS_SEP + u'type' XSI_TYPE = XMLNS_XSI + NS_SEP + u('type')
# Note: Must make a copy to use the SOAP_NSMAP # Note: Must make a copy to use the SOAP_NSMAP
# TODO: Change to frozendict, if available # TODO: Change to frozendict, if available
SOAP_NSMAP = { XMLNS_SOAPENC: 'soapenc', XMLNS_SOAPENV: 'soapenv', SOAP_NSMAP = { XMLNS_SOAPENC: 'soapenc', XMLNS_SOAPENV: 'soapenv',
XMLNS_XSI: 'xsi', XMLNS_XSD: 'xsd' } XMLNS_XSI: 'xsi', XMLNS_XSD: 'xsd' }
SOAP_ENVELOPE_TAG="%s:Envelope" % SOAP_NSMAP[XMLNS_SOAPENV] SOAP_ENVELOPE_TAG = "{0}:Envelope".format(SOAP_NSMAP[XMLNS_SOAPENV])
SOAP_HEADER_TAG="%s:Header" % SOAP_NSMAP[XMLNS_SOAPENV] SOAP_HEADER_TAG = "{0}:Header".format(SOAP_NSMAP[XMLNS_SOAPENV])
SOAP_FAULT_TAG="%s:Fault" % SOAP_NSMAP[XMLNS_SOAPENV] SOAP_FAULT_TAG = "{0}:Fault".format(SOAP_NSMAP[XMLNS_SOAPENV])
SOAP_BODY_TAG="%s:Body" % SOAP_NSMAP[XMLNS_SOAPENV] SOAP_BODY_TAG = "{0}:Body".format(SOAP_NSMAP[XMLNS_SOAPENV])
SOAP_ENVELOPE_START = '<%s ' % SOAP_ENVELOPE_TAG + \ SOAP_ENVELOPE_START = '<{0} '.format(SOAP_ENVELOPE_TAG) + \
' '.join(['xmlns:' + prefix + '="' + urn + '"' \ ' '.join(['xmlns:' + prefix + '="' + urn + '"' \
for urn, prefix in SOAP_NSMAP.iteritems()]) + \ for urn, prefix in iteritems(SOAP_NSMAP)]) + \
'>\n' '>\n'
SOAP_ENVELOPE_END = "\n</%s>" % (SOAP_ENVELOPE_TAG) SOAP_ENVELOPE_END = "\n</{0}>".format(SOAP_ENVELOPE_TAG)
SOAP_HEADER_START="<%s>" % SOAP_HEADER_TAG SOAP_HEADER_START = "<{0}>".format(SOAP_HEADER_TAG)
SOAP_HEADER_END="</%s>" % SOAP_HEADER_TAG SOAP_HEADER_END = "</{0}>".format(SOAP_HEADER_TAG)
SOAP_BODY_START="<%s>" % SOAP_BODY_TAG SOAP_BODY_START = "<{0}>".format(SOAP_BODY_TAG)
SOAP_BODY_END="</%s>" % SOAP_BODY_TAG SOAP_BODY_END = "</{0}>".format(SOAP_BODY_TAG)
SOAP_START = SOAP_ENVELOPE_START + SOAP_BODY_START + '\n' SOAP_START = SOAP_ENVELOPE_START + SOAP_BODY_START + '\n'
SOAP_END = '\n' + SOAP_BODY_END + SOAP_ENVELOPE_END SOAP_END = '\n' + SOAP_BODY_END + SOAP_ENVELOPE_END
WSSE_PREFIX = "wsse" WSSE_PREFIX = "wsse"
WSSE_HEADER_TAG="%s:Security" % WSSE_PREFIX WSSE_HEADER_TAG = "{0}:Security".format(WSSE_PREFIX)
WSSE_NS_URL = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" WSSE_NS_URL = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
WSSE_NS='xmlns:%s="%s"' % (WSSE_PREFIX, WSSE_NS_URL) WSSE_NS = 'xmlns:{0}="{1}"'.format(WSSE_PREFIX, WSSE_NS_URL)
WSSE_HEADER_START="<%s %s>" % (WSSE_HEADER_TAG, WSSE_NS) WSSE_HEADER_START = "<{0} {1}>".format(WSSE_HEADER_TAG, WSSE_NS)
WSSE_HEADER_END="</%s>" % WSSE_HEADER_TAG WSSE_HEADER_END = "</{0}>".format(WSSE_HEADER_TAG)
## MethodFault type ## MethodFault type
MethodFault = GetVmodlType("vmodl.MethodFault") MethodFault = GetVmodlType("vmodl.MethodFault")
@@ -152,7 +164,7 @@ def SerializeFaultDetail(val, info=None, version=None, nsMap=None, encoding=None
if version is None: if version is None:
try: try:
if not isinstance(val, MethodFault): if not isinstance(val, MethodFault):
raise TypeError('%s is not a MethodFault' % str(val)) raise TypeError('{0} is not a MethodFault'.format(str(val)))
version = val._version version = val._version
except AttributeError: except AttributeError:
version = BASE_VERSION version = BASE_VERSION
@@ -178,7 +190,7 @@ class SoapSerializer:
self.version = version self.version = version
self.nsMap = nsMap and nsMap or {} self.nsMap = nsMap and nsMap or {}
self.encoding = encoding and encoding or XML_ENCODING self.encoding = encoding and encoding or XML_ENCODING
for ns, prefix in self.nsMap.iteritems(): for ns, prefix in iteritems(self.nsMap):
if prefix == '': if prefix == '':
self.defaultNS = ns self.defaultNS = ns
break break
@@ -194,7 +206,7 @@ class SoapSerializer:
prefix = self.nsMap.get(ns) prefix = self.nsMap.get(ns)
if not prefix: if not prefix:
prefix = nsPrefix prefix = nsPrefix
self.outermostAttrs += ' xmlns:%s="%s"' % (prefix, ns) self.outermostAttrs += ' xmlns:{0}="{1}"'.format(prefix, ns)
self.nsMap = self.nsMap.copy() self.nsMap = self.nsMap.copy()
self.nsMap[ns] = prefix self.nsMap[ns] = prefix
setattr(self, attrName, prefix + ":") setattr(self, attrName, prefix + ":")
@@ -240,7 +252,7 @@ class SoapSerializer:
except KeyError: except KeyError:
# We have not seen this ns before # We have not seen this ns before
prefix = ns.split(':', 1)[-1] prefix = ns.split(':', 1)[-1]
attr = ' xmlns:%s="%s"' % (prefix, ns) attr = ' xmlns:{0}="{1}"'.format(prefix, ns)
return attr, prefix and prefix + ':' + name or name return attr, prefix and prefix + ':' + name or name
## Serialize an object (internal) ## Serialize an object (internal)
@@ -257,17 +269,17 @@ class SoapSerializer:
if info.flags & F_OPTIONAL: if info.flags & F_OPTIONAL:
return return
else: else:
raise TypeError('Field "%s" is not optional' % info.name) raise TypeError('Field "{0}" is not optional'.format(info.name))
elif isinstance(val, list) and len(val) == 0: elif isinstance(val, list) and len(val) == 0:
if info.type is object: if info.type is object:
# Make sure an empty array assigned to Any is typed # Make sure an empty array assigned to Any is typed
if not isinstance(val, Array): if not isinstance(val, Array):
raise TypeError('Field "%s": Cannot assign empty native python array to an Any' % info.name) raise TypeError('Field "{0}": Cannot assign empty native python array to an Any'.format(info.name))
elif info.flags & F_OPTIONAL: elif info.flags & F_OPTIONAL:
# Skip optional non-Any # Skip optional non-Any
return return
else: else:
raise TypeError('Field "%s" is not optional' % info.name) raise TypeError('Field "{0}" not optional'.format(info.name))
if self.outermostAttrs: if self.outermostAttrs:
attr = self.outermostAttrs attr = self.outermostAttrs
@@ -278,7 +290,7 @@ class SoapSerializer:
# Emit default ns if tag ns is not the same # Emit default ns if tag ns is not the same
currTagNS = GetWsdlNamespace(info.version) currTagNS = GetWsdlNamespace(info.version)
if currTagNS != defNS: if currTagNS != defNS:
attr += ' xmlns="%s"' % currTagNS attr += ' xmlns="{0}"'.format(currTagNS)
currDefNS = currTagNS currDefNS = currTagNS
if isinstance(val, DataObject): if isinstance(val, DataObject):
@@ -296,14 +308,14 @@ class SoapSerializer:
elif isinstance(val, ManagedObject): elif isinstance(val, ManagedObject):
if info.type is object: if info.type is object:
nsattr, qName = self._QName(ManagedObject, currDefNS) nsattr, qName = self._QName(ManagedObject, currDefNS)
attr += '%s %stype="%s"' % (nsattr, self.xsiPrefix, qName) attr += '{0} {1}type="{2}"'.format(nsattr, self.xsiPrefix, qName)
if val._serverGuid is not None: if val._serverGuid is not None:
attr += ' serverGuid="%s"' % (val._serverGuid) attr += ' serverGuid="{0}"'.format(val._serverGuid)
# val in vim type attr is not namespace qualified # val in vim type attr is not namespace qualified
# TODO: Add a new "typens" attr? # TODO: Add a new "typens" attr?
ns, name = GetQualifiedWsdlName(Type(val)) ns, name = GetQualifiedWsdlName(Type(val))
attr += ' type="%s"' % (name) attr += ' type="{0}"'.format(name)
self.writer.write('<%s%s>%s</%s>' % (info.name, attr, self.writer.write('<{0}{1}>{2}</{3}>'.format(info.name, attr,
val._moId.encode(self.encoding), val._moId.encode(self.encoding),
info.name)) info.name))
elif isinstance(val, list): elif isinstance(val, list):
@@ -326,14 +338,14 @@ class SoapSerializer:
if qName.endswith("ArrayOfManagedObject"): if qName.endswith("ArrayOfManagedObject"):
qName += "Reference" qName += "Reference"
attr += '%s %stype="%s"' % (nsattr, self.xsiPrefix, qName) attr += '{0} {1}type="{2}"'.format(nsattr, self.xsiPrefix, qName)
self.writer.write('<%s%s>' % (info.name, attr)) self.writer.write('<{0}{1}>'.format(info.name, attr))
itemInfo = Object(name=tag, type=itemType, itemInfo = Object(name=tag, type=itemType,
version=info.version, flags=info.flags) version=info.version, flags=info.flags)
for it in val: for it in val:
self._Serialize(it, itemInfo, currDefNS) self._Serialize(it, itemInfo, currDefNS)
self.writer.write('</%s>' % info.name) self.writer.write('</{0}>'.format(info.name))
else: else:
itemType = info.type.Item itemType = info.type.Item
itemInfo = Object(name=info.name, type=itemType, itemInfo = Object(name=info.name, type=itemType,
@@ -342,54 +354,52 @@ class SoapSerializer:
self._Serialize(it, itemInfo, defNS) self._Serialize(it, itemInfo, defNS)
elif isinstance(val, type) or isinstance(val, type(Exception)): elif isinstance(val, type) or isinstance(val, type(Exception)):
if info.type is object: if info.type is object:
attr += ' %stype="%sstring"' % (self.xsiPrefix, self.xsdPrefix) attr += ' {0}type="{1}string"'.format(self.xsiPrefix, self.xsdPrefix)
self.writer.write('<%s%s>%s</%s>' % self.writer.write('<{0}{1}>{2}</{0}>'.format(
(info.name, attr, GetWsdlName(val), info.name)) info.name, attr, GetWsdlName(val)))
elif isinstance(val, ManagedMethod): elif isinstance(val, ManagedMethod):
if info.type is object: if info.type is object:
attr += ' %stype="%sstring"' % (self.xsiPrefix, self.xsdPrefix) attr += ' {0}type="{1}string"'.format(self.xsiPrefix, self.xsdPrefix)
self.writer.write('<%s%s>%s</%s>' % self.writer.write('<{0}{1}>{2}</{0}>'.format(
(info.name, attr, val.info.wsdlName, info.name)) info.name, attr, val.info.wsdlName))
elif isinstance(val, datetime): elif isinstance(val, datetime):
if info.type is object: if info.type is object:
nsattr, qName = self._QName(Type(val), currDefNS) nsattr, qName = self._QName(Type(val), currDefNS)
attr += '%s %stype="%s"' % (nsattr, self.xsiPrefix, qName) attr += '{0} {1}type="{2}"'.format(nsattr, self.xsiPrefix, qName)
result = Iso8601.ISO8601Format(val) result = Iso8601.ISO8601Format(val)
self.writer.write('<%s%s>%s</%s>' % (info.name, attr, result, self.writer.write('<{0}{1}>{2}</{0}>'.format(info.name, attr, result))
info.name))
elif isinstance(val, binary): elif isinstance(val, binary):
if info.type is object: if info.type is object:
nsattr, qName = self._QName(Type(val), currDefNS) nsattr, qName = self._QName(Type(val), currDefNS)
attr += '%s %stype="%s"' % (nsattr, self.xsiPrefix, qName) attr += '{0} {1}type="{2}"'.format(nsattr, self.xsiPrefix, qName)
result = base64.b64encode(val) result = base64.b64encode(val)
self.writer.write('<%s%s>%s</%s>' % (info.name, attr, result, self.writer.write('<{0}{1}>{2}</{0}>'.format(info.name, attr, result))
info.name))
elif isinstance(val, bool): elif isinstance(val, bool):
if info.type is object: if info.type is object:
nsattr, qName = self._QName(Type(val), currDefNS) nsattr, qName = self._QName(Type(val), currDefNS)
attr += '%s %stype="%s"' % (nsattr, self.xsiPrefix, qName) attr += '{0} {1}type="{2}"'.format(nsattr, self.xsiPrefix, qName)
result = val and "true" or "false" result = val and "true" or "false"
self.writer.write('<%s%s>%s</%s>' % (info.name, attr, result, self.writer.write('<{0}{1}>{2}</{0}>'.format(info.name, attr, result))
info.name))
else: else:
if info.type is object: if info.type is object:
if isinstance(val, PropertyPath): if isinstance(val, PropertyPath):
attr += ' %stype="%sstring"' % (self.xsiPrefix, self.xsdPrefix) attr += ' {0}type="{1}string"'.format(self.xsiPrefix, self.xsdPrefix)
else: else:
nsattr, qName = self._QName(Type(val), currDefNS) nsattr, qName = self._QName(Type(val), currDefNS)
attr += '%s %stype="%s"' % (nsattr, self.xsiPrefix, qName) attr += '{0} {1}type="{2}"'.format(nsattr, self.xsiPrefix, qName)
if not isinstance(val, unicode): if not isinstance(val, text_type):
# Use UTF-8 rather than self.encoding. self.encoding is for # Use UTF-8 rather than self.encoding. self.encoding is for
# output of serializer, while 'val' is our input. And regardless # output of serializer, while 'val' is our input. And regardless
# of what our output is, our input should be always UTF-8. Yes, # of what our output is, our input should be always UTF-8. Yes,
# it means that if you emit output in other encoding than UTF-8, # it means that if you emit output in other encoding than UTF-8,
# you cannot serialize it again once more. That's feature, not # you cannot serialize it again once more. That's feature, not
# a bug. # a bug.
val = str(val).decode('UTF-8') val = str(val)
if PY2:
val = val.decode('UTF-8')
result = XmlEscape(val) result = XmlEscape(val)
self.writer.write('<%s%s>%s</%s>' % (info.name, attr, self.writer.write('<{0}{1}>{2}</{0}>'.format(info.name, attr,
result.encode(self.encoding), result.encode(self.encoding)))
info.name))
## Serialize a a data object (internal) ## Serialize a a data object (internal)
# #
@@ -406,8 +416,8 @@ class SoapSerializer:
dynType = GetCompatibleType(Type(val), self.version) dynType = GetCompatibleType(Type(val), self.version)
if dynType != info.type: if dynType != info.type:
nsattr, qName = self._QName(dynType, currDefNS) nsattr, qName = self._QName(dynType, currDefNS)
attr += '%s %stype="%s"' % (nsattr, self.xsiPrefix, qName) attr += '{0} {1}type="{2}"'.format(nsattr, self.xsiPrefix, qName)
self.writer.write('<%s%s>' % (info.name, attr)) self.writer.write('<{0}{1}>'.format(info.name, attr))
if dynType is LocalizedMethodFault: if dynType is LocalizedMethodFault:
# Serialize a MethodFault as LocalizedMethodFault on wire # Serialize a MethodFault as LocalizedMethodFault on wire
# See PR 670229 # See PR 670229
@@ -423,7 +433,7 @@ class SoapSerializer:
for prop in val._GetPropertyList(): for prop in val._GetPropertyList():
self._Serialize(getattr(val, prop.name), prop, currDefNS) self._Serialize(getattr(val, prop.name), prop, currDefNS)
self.writer.write('</%s>' % info.name) self.writer.write('</{0}>'.format(info.name))
## Deserialize an object from a file or string ## Deserialize an object from a file or string
@@ -582,7 +592,7 @@ class SoapDeserializer(ExpatDeserializerNSHandlers):
if name == "fault" and isinstance(self.stack[-1], LocalizedMethodFault): if name == "fault" and isinstance(self.stack[-1], LocalizedMethodFault):
deserializeAsLocalizedMethodFault = False deserializeAsLocalizedMethodFault = False
else: else:
raise TypeError("Invalid type for tag %s" % tag) raise TypeError("Invalid type for tag {0}".format(tag))
xsiType = attr.get(XSI_TYPE) xsiType = attr.get(XSI_TYPE)
if xsiType: if xsiType:
@@ -604,13 +614,13 @@ class SoapDeserializer(ExpatDeserializerNSHandlers):
if self.version: if self.version:
objType = GetCompatibleType(objType, self.version) objType = GetCompatibleType(objType, self.version)
if issubclass(objType, ManagedObject): if issubclass(objType, ManagedObject):
typeAttr = attr[u'type'] typeAttr = attr[u('type')]
# val in vim type attr is not namespace qualified # val in vim type attr is not namespace qualified
# However, this doesn't hurt to strip out namespace # However, this doesn't hurt to strip out namespace
# TODO: Get the ns from "typens" attr? # TODO: Get the ns from "typens" attr?
ns, name = self.GetNSAndWsdlname(typeAttr) ns, name = self.GetNSAndWsdlname(typeAttr)
if u'serverGuid' in attr: if u('serverGuid') in attr:
self.serverGuid = attr[u'serverGuid'] self.serverGuid = attr[u('serverGuid')]
self.stack.append(GuessWsdlType(name)) self.stack.append(GuessWsdlType(name))
elif issubclass(objType, DataObject) or issubclass(objType, list): elif issubclass(objType, DataObject) or issubclass(objType, list):
if deserializeAsLocalizedMethodFault and issubclass(objType, Exception): if deserializeAsLocalizedMethodFault and issubclass(objType, Exception):
@@ -662,10 +672,10 @@ class SoapDeserializer(ExpatDeserializerNSHandlers):
elif obj is str: elif obj is str:
try: try:
obj = str(data) obj = str(data)
except UnicodeError: except ValueError:
obj = data obj = data
elif obj is datetime: elif obj is datetime:
obj = Iso8601.ParseISO8601(data) obj = pyVmomi.Iso8601.ParseISO8601(data)
if not obj: if not obj:
raise TypeError(data) raise TypeError(data)
# issubclass is very expensive. Test last # issubclass is very expensive. Test last
@@ -772,7 +782,7 @@ class SoapResponseDeserializer(ExpatDeserializerNSHandlers):
if self.isFault and tag == "faultstring": if self.isFault and tag == "faultstring":
try: try:
self.msg = str(self.data) self.msg = str(self.data)
except UnicodeError: except ValueError:
self.msg = self.data self.msg = self.data
## Base class that implements common functionality for stub adapters. ## Base class that implements common functionality for stub adapters.
@@ -789,7 +799,7 @@ class StubAdapterBase(StubAdapterAccessorMixin):
def ComputeVersionInfo(self, version): def ComputeVersionInfo(self, version):
versionNS = GetVersionNamespace(version) versionNS = GetVersionNamespace(version)
if versionNS.find("/") >= 0: if versionNS.find("/") >= 0:
self.versionId = '"urn:%s"' % versionNS self.versionId = '"urn:{0}"'.format(versionNS)
else: else:
self.versionId = '' self.versionId = ''
self.version = version self.version = version
@@ -822,17 +832,17 @@ class SoapStubAdapterBase(StubAdapterBase):
if reqContexts or samlToken: if reqContexts or samlToken:
result.append(SOAP_HEADER_START) result.append(SOAP_HEADER_START)
for key, val in reqContexts.iteritems(): for key, val in iteritems(reqContexts):
# Note: Support req context of string type only # Note: Support req context of string type only
if not isinstance(val, basestring): if not isinstance(val, basestring):
raise TypeError("Request context key (%s) has non-string value (%s) of %s" % (key, val, type(val))) raise TypeError("Request context key ({0}) has non-string value ({1}) of {2}".format(key, val, type(val)))
ret = Serialize(val, ret = Serialize(val,
Object(name=key, type=str, version=self.version), Object(name=key, type=str, version=self.version),
self.version, self.version,
nsMap) nsMap)
result.append(ret) result.append(ret)
if samlToken: if samlToken:
result.append('%s %s %s' % (WSSE_HEADER_START, result.append('{0} {1} {2}'.format(WSSE_HEADER_START,
samlToken, samlToken,
WSSE_HEADER_END)) WSSE_HEADER_END))
result.append(SOAP_HEADER_END) result.append(SOAP_HEADER_END)
@@ -840,7 +850,7 @@ class SoapStubAdapterBase(StubAdapterBase):
# Serialize soap body # Serialize soap body
result.extend([SOAP_BODY_START, result.extend([SOAP_BODY_START,
'<%s xmlns="%s">' % (info.wsdlName, defaultNS), '<{0} xmlns="{1}">'.format(info.wsdlName, defaultNS),
Serialize(mo, Object(name="_this", type=ManagedObject, Serialize(mo, Object(name="_this", type=ManagedObject,
version=self.version), version=self.version),
self.version, nsMap)]) self.version, nsMap)])
@@ -848,7 +858,7 @@ class SoapStubAdapterBase(StubAdapterBase):
# Serialize soap request parameters # Serialize soap request parameters
for (param, arg) in zip(info.params, args): for (param, arg) in zip(info.params, args):
result.append(Serialize(arg, param, self.version, nsMap)) result.append(Serialize(arg, param, self.version, nsMap))
result.extend(['</%s>' % info.wsdlName, SOAP_BODY_END, SOAP_ENVELOPE_END]) result.extend(['</{0}>'.format(info.wsdlName), SOAP_BODY_END, SOAP_ENVELOPE_END])
return ''.join(result) return ''.join(result)
## Subclass of HTTPConnection that connects over a Unix domain socket ## Subclass of HTTPConnection that connects over a Unix domain socket
@@ -894,8 +904,8 @@ try:
sha1.update(derCert) sha1.update(derCert)
sha1Digest = sha1.hexdigest().lower() sha1Digest = sha1.hexdigest().lower()
if sha1Digest != thumbprint: if sha1Digest != thumbprint:
raise Exception("Server has wrong SHA1 thumbprint: %s " raise Exception("Server has wrong SHA1 thumbprint: {0} "
"(required) != %s (server)" % ( "(required) != {1} (server)".format(
thumbprint, sha1Digest)) thumbprint, sha1Digest))
# Function used to wrap sockets with SSL # Function used to wrap sockets with SSL
@@ -1001,7 +1011,7 @@ class SSLTunnelConnection(object):
resp = tunnel.getresponse() resp = tunnel.getresponse()
tunnelSocket = resp.fp tunnelSocket = resp.fp
if resp.status != 200: if resp.status != 200:
raise http_client.HTTPException("%d %s" % (resp.status, resp.reason)) raise httplib.HTTPException("{0} {1}".format(resp.status, resp.reason))
retval = http_client.HTTPSConnection(path) retval = http_client.HTTPSConnection(path)
retval.sock = _SocketWrapper(tunnelSocket, retval.sock = _SocketWrapper(tunnelSocket,
keyfile=key_file, certfile=cert_file) keyfile=key_file, certfile=cert_file)
@@ -1139,13 +1149,13 @@ class SoapStubAdapter(SoapStubAdapterBase):
or (port, HTTPSConnectionWrapper) or (port, HTTPSConnectionWrapper)
if host.find(':') != -1: # is IPv6? if host.find(':') != -1: # is IPv6?
host = '[' + host + ']' host = '[' + host + ']'
self.host = '%s:%d' % (host, port) self.host = '{0}:{1}'.format(host, port)
self.path = path self.path = path
if thumbprint: if thumbprint:
self.thumbprint = thumbprint.replace(":", "").lower() self.thumbprint = thumbprint.replace(":", "").lower()
if len(self.thumbprint) != 40: if len(self.thumbprint) != 40:
raise Exception("Invalid SHA1 thumbprint -- %s" % thumbprint) raise Exception("Invalid SHA1 thumbprint -- {0}".format(thumbprint))
else: else:
self.thumbprint = None self.thumbprint = None
@@ -1158,13 +1168,13 @@ class SoapStubAdapter(SoapStubAdapterBase):
if url: if url:
self.path = url self.path = url
else: else:
self.path = "http://%s/%s" % (self.host, path) self.path = "http://{0}/{1}".format(self.host, path)
# Swap the actual host with the proxy. # Swap the actual host with the proxy.
self.host = "%s:%d" % (httpProxyHost, httpProxyPort) self.host = "{0}:{1}".format(httpProxyHost, httpProxyPort)
self.poolSize = poolSize self.poolSize = poolSize
self.pool = [] self.pool = []
self.connectionPoolTimeout = connectionPoolTimeout self.connectionPoolTimeout = connectionPoolTimeout
self.lock = thread.allocate_lock() self.lock = threading.Lock()
self.schemeArgs = {} self.schemeArgs = {}
if certKeyFile: if certKeyFile:
self.schemeArgs['key_file'] = certKeyFile self.schemeArgs['key_file'] = certKeyFile
@@ -1207,7 +1217,7 @@ class SoapStubAdapter(SoapStubAdapterBase):
headers = {'Cookie' : self.cookie, headers = {'Cookie' : self.cookie,
'SOAPAction' : self.versionId, 'SOAPAction' : self.versionId,
'Content-Type' : 'text/xml; charset=%s' % XML_ENCODING} 'Content-Type': 'text/xml; charset={0}'.format(XML_ENCODING)}
if self._acceptCompressedResponses: if self._acceptCompressedResponses:
headers['Accept-Encoding'] = 'gzip, deflate' headers['Accept-Encoding'] = 'gzip, deflate'
req = self.SerializeRequest(mo, info, args) req = self.SerializeRequest(mo, info, args)
@@ -1251,7 +1261,7 @@ class SoapStubAdapter(SoapStubAdapterBase):
raise obj # pylint: disable-msg=E0702 raise obj # pylint: disable-msg=E0702
else: else:
conn.close() conn.close()
raise http_client.HTTPException("%d %s" % (resp.status, resp.reason)) raise http_client.HTTPException("{0} {1}".format(resp.status, resp.reason))
## Clean up connection pool to throw away idle timed-out connections ## Clean up connection pool to throw away idle timed-out connections
# SoapStubAdapter lock must be acquired before this method is called. # SoapStubAdapter lock must be acquired before this method is called.
@@ -1384,14 +1394,14 @@ class SoapCmdStubAdapter(SoapStubAdapterBase):
(outText, errText) = p.communicate(req) (outText, errText) = p.communicate(req)
if p.returncode < 0: if p.returncode < 0:
# Process died with a signal # Process died with a signal
errText = "Process terminated with signal %d\n%s" % (-p.returncode, errText) errText = "Process terminated with signal {0}\n{1}".format(-p.returncode, errText)
raise self.systemError(msg=errText, reason=errText) raise self.systemError(msg=errText, reason=errText)
try: try:
(responseHeaders, responseBody) = ParseHttpResponse(outText) (responseHeaders, responseBody) = ParseHttpResponse(outText)
obj = SoapResponseDeserializer(self).Deserialize(responseBody, info.result) obj = SoapResponseDeserializer(self).Deserialize(responseBody, info.result)
except: except:
errText = "Failure parsing SOAP response (%s)\n%s" % (outText, errText) errText = "Failure parsing SOAP response ({0})\n{1}}".format(outText, errText)
raise self.systemError(msg=errText, reason=errText) raise self.systemError(msg=errText, reason=errText)
if p.returncode == 0: if p.returncode == 0:
@@ -1491,7 +1501,7 @@ class SessionOrientedStub(StubAdapterBase):
raise obj raise obj
# Raise any socket/httplib errors caught above. # Raise any socket/httplib errors caught above.
raise raise SystemError()
## Retrieve a managed property ## Retrieve a managed property
# #
@@ -1513,7 +1523,7 @@ class SessionOrientedStub(StubAdapterBase):
time.sleep(self.retryDelay) time.sleep(self.retryDelay)
retriesLeft -= 1 retriesLeft -= 1
continue continue
except Exception, e: except Exception as e:
if isinstance(e, self.SESSION_EXCEPTIONS): if isinstance(e, self.SESSION_EXCEPTIONS):
# Our session might've timed out, change our state and retry. # Our session might've timed out, change our state and retry.
self._SetStateUnauthenticated() self._SetStateUnauthenticated()
@@ -1521,7 +1531,7 @@ class SessionOrientedStub(StubAdapterBase):
raise e raise e
return obj return obj
# Raise any socket/httplib errors caught above. # Raise any socket/httplib errors caught above.
raise raise SystemError()
## Handle the login method call ## Handle the login method call
# #

View File

@@ -12,8 +12,8 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from __future__ import absolute_import
from VmomiSupport import GetVmodlType from pyVmomi.VmomiSupport import GetVmodlType
class StubAdapterAccessorMixin: class StubAdapterAccessorMixin:
def __init__(self): def __init__(self):

View File

@@ -12,8 +12,8 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from __future__ import absolute_import
from VmomiSupport import nsMap, versionMap, versionIdMap, serviceNsMap, parentMap from pyVmomi.VmomiSupport import nsMap, versionMap, versionIdMap, serviceNsMap, parentMap
## Add an API version ## Add an API version
def AddVersion(version, ns, versionId='', isLegacy=0, serviceNs=''): def AddVersion(version, ns, versionId='', isLegacy=0, serviceNs=''):

View File

@@ -14,21 +14,34 @@
# limitations under the License. # limitations under the License.
## VMOMI support code ## VMOMI support code
from __future__ import absolute_import
from __future__ import with_statement # 2.5 only from __future__ import with_statement # 2.5 only
from six import iteritems
from six import iterkeys
from six import itervalues
from six import text_type
from six import PY3
from datetime import datetime from datetime import datetime
import Iso8601 import pyVmomi.Iso8601
import base64 import base64
import threading import threading
if PY3:
# python3 removed long, it's the same as int
long = int
# python3 removed basestring, use str instead.
basestring = str
NoneType = type(None) NoneType = type(None)
try: try:
from pyVmomiSettings import allowGetSet from pyVmomi.pyVmomiSettings import allowGetSet
_allowGetSet = allowGetSet _allowGetSet = allowGetSet
except: except:
_allowGetSet = True _allowGetSet = True
try: try:
from pyVmomiSettings import allowCapitalizedNames from pyVmomi.pyVmomiSettings import allowCapitalizedNames
_allowCapitalizedNames = allowCapitalizedNames _allowCapitalizedNames = allowCapitalizedNames
except: except:
_allowCapitalizedNames = True _allowCapitalizedNames = True
@@ -176,13 +189,13 @@ class LazyObject(Object):
else: else:
raise AttributeError(attr) raise AttributeError(attr)
class Link(unicode): class Link(text_type):
def __new__(cls, obj): def __new__(cls, obj):
if isinstance(obj, basestring): if isinstance(obj, basestring):
return unicode.__new__(cls, obj) return text_type.__new__(cls, obj)
elif isinstance(obj, DataObject): elif isinstance(obj, DataObject):
if obj.key: if obj.key:
return unicode.__new__(cls, obj.key) return text_type.__new__(cls, obj.key)
raise AttributeError("DataObject does not have a key to link") raise AttributeError("DataObject does not have a key to link")
else: else:
raise ValueError raise ValueError
@@ -348,7 +361,7 @@ class ManagedObject(object):
args = list(posargs) + [None] * (len(info.params) - len(posargs)) args = list(posargs) + [None] * (len(info.params) - len(posargs))
if len(kwargs) > 0: if len(kwargs) > 0:
paramNames = [param.name for param in info.params] paramNames = [param.name for param in info.params]
for (k, v) in kwargs.items(): for (k, v) in list(kwargs.items()):
try: try:
idx = paramNames.index(k) idx = paramNames.index(k)
except ValueError: except ValueError:
@@ -1026,7 +1039,7 @@ def GetWsdlTypes():
with _lazyLock: with _lazyLock:
for ns, name in _wsdlDefMap: for ns, name in _wsdlDefMap:
GetWsdlType(ns, name) GetWsdlType(ns, name)
return _wsdlTypeMap.itervalues() return itervalues(_wsdlTypeMap)
## Get the qualified XML schema name (ns, name) of a type ## Get the qualified XML schema name (ns, name) of a type
def GetQualifiedWsdlName(type): def GetQualifiedWsdlName(type):
@@ -1113,21 +1126,21 @@ def GetServiceVersions(namespace):
by compatibility (i.e. any version in the list that is compatible with some version by compatibility (i.e. any version in the list that is compatible with some version
v in the list will preceed v) v in the list will preceed v)
""" """
versions = dict((v, True) for (v, n) in serviceNsMap.iteritems() if n == namespace) versions = dict((v, True) for (v, n) in iteritems(serviceNsMap) if n == namespace)
mappings = {} mappings = {}
for v in versions.iterkeys(): for v in iterkeys(versions):
mappings[v] = set(parent for parent in parentMap[v].iterkeys() mappings[v] = set(parent for parent in iterkeys(parentMap[v])
if parent != v and versions.has_key(parent)) if parent != v and parent in versions.keys())
res = [] res = []
while True: while True:
el = [ k for (k, v) in mappings.iteritems() if len(v) == 0 ] el = [ k for (k, v) in iteritems(mappings) if len(v) == 0 ]
if len(el) == 0: if len(el) == 0:
return res return res
el.sort() el.sort()
for k in el: for k in el:
res.insert(0, k) res.insert(0, k)
del mappings[k] del mappings[k]
for values in mappings.itervalues(): for values in itervalues(mappings):
values.discard(k) values.discard(k)
@@ -1218,7 +1231,7 @@ def GetCompatibleType(type, version):
## Invert an injective mapping ## Invert an injective mapping
def InverseMap(map): def InverseMap(map):
return dict([ (v, k) for (k, v) in map.iteritems() ]) return dict([ (v, k) for (k, v) in iteritems(map) ])
types = Object() types = Object()
nsMap = {} nsMap = {}
@@ -1227,7 +1240,7 @@ versionMap = {}
serviceNsMap = { BASE_VERSION : XMLNS_VMODL_BASE.split(":")[-1] } serviceNsMap = { BASE_VERSION : XMLNS_VMODL_BASE.split(":")[-1] }
parentMap = {} parentMap = {}
from Version import AddVersion, IsChildVersion from pyVmomi.Version import AddVersion, IsChildVersion
if not isinstance(bool, type): # bool not a type in python <= 2.2 if not isinstance(bool, type): # bool not a type in python <= 2.2
bool = type("bool", (int,), bool = type("bool", (int,),
@@ -1237,7 +1250,7 @@ short = type("short", (int,), {})
double = type("double", (float,), {}) double = type("double", (float,), {})
URI = type("URI", (str,), {}) URI = type("URI", (str,), {})
binary = type("binary", (str,), {}) binary = type("binary", (str,), {})
PropertyPath = type("PropertyPath", (unicode,), {}) PropertyPath = type("PropertyPath", (text_type,), {})
# _wsdlTypeMapNSs store namespaces added to _wsdlTypeMap in _SetWsdlType # _wsdlTypeMapNSs store namespaces added to _wsdlTypeMap in _SetWsdlType
_wsdlTypeMapNSs = set() _wsdlTypeMapNSs = set()
@@ -1263,7 +1276,7 @@ _wsdlTypeMap = {
} }
_wsdlNameMap = InverseMap(_wsdlTypeMap) _wsdlNameMap = InverseMap(_wsdlTypeMap)
for ((ns, name), typ) in _wsdlTypeMap.items(): for ((ns, name), typ) in iteritems(dict(_wsdlTypeMap)):
if typ is not NoneType: if typ is not NoneType:
setattr(types, typ.__name__, typ) setattr(types, typ.__name__, typ)
_wsdlTypeMapNSs.add(ns) _wsdlTypeMapNSs.add(ns)
@@ -1277,8 +1290,8 @@ del name, typ
# unicode is mapped to wsdl name 'string' (Cannot put in wsdlTypeMap or name # unicode is mapped to wsdl name 'string' (Cannot put in wsdlTypeMap or name
# collision with non-unicode string) # collision with non-unicode string)
_wsdlNameMap[unicode] = (XMLNS_XSD, 'string') _wsdlNameMap[text_type] = (XMLNS_XSD, 'string')
_wsdlNameMap[CreateArrayType(unicode)] = (XMLNS_VMODL_BASE, 'ArrayOfString') _wsdlNameMap[CreateArrayType(text_type)] = (XMLNS_VMODL_BASE, 'ArrayOfString')
# _wsdlMethodNSs store namespaces added to _wsdlMethodMap in _SetWsdlMethod # _wsdlMethodNSs store namespaces added to _wsdlMethodMap in _SetWsdlMethod
_wsdlMethodNSs = set() _wsdlMethodNSs = set()
@@ -1322,7 +1335,7 @@ vmodlTypes = {
vmodlNames = {} vmodlNames = {}
## Add array type into special names ## Add array type into special names
for name, typ in vmodlTypes.copy().iteritems(): for name, typ in vmodlTypes.copy().items():
if typ is not NoneType: if typ is not NoneType:
try: try:
arrayType = typ.Array arrayType = typ.Array
@@ -1454,7 +1467,7 @@ class StringDict(dict):
# Same as dict setdefault, except this will call through our __setitem__ # Same as dict setdefault, except this will call through our __setitem__
def update(self, *args, **kwargs): def update(self, *args, **kwargs):
for k, v in dict(*args, **kwargs).iteritems(): for k, v in iteritems(dict(*args, **kwargs)):
self[k] = v self[k] = v
# Same as dict setdefault, except this will call through our __setitem__ # Same as dict setdefault, except this will call through our __setitem__

View File

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

View File

@@ -1,6 +1,6 @@
#!/usr/bin/python #!/usr/bin/python
# VMware vSphere Python SDK # VMware vSphere Python SDK
# Copyright (c) 2008-2014 VMware, Inc. All Rights Reserved. # Copyright (c) 2008-2013 VMware, Inc. All Rights Reserved.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@@ -18,36 +18,48 @@
Python program for listing the vms on an ESX / vCenter host Python program for listing the vms on an ESX / vCenter host
""" """
from optparse import OptionParser, make_option from __future__ import print_function
import pyVmomi
from pyVmomi import vim
from pyVmomi import vmodl
from pyVim.connect import SmartConnect, Disconnect from pyVim.connect import SmartConnect, Disconnect
from pyVmomi import vmodl from pyVmomi import vmodl
import argparse import argparse
import atexit import atexit
import getpass import getpass
import sys
def GetArgs(): def GetArgs():
""" """
Supports the command-line arguments listed below. Supports the command-line arguments listed below.
""" """
parser = argparse.ArgumentParser(description='Process args for retrieving all the Virtual Machines') parser = argparse.ArgumentParser(
parser.add_argument('-s', '--host', required=True, action='store', help='Remote host to connect to') description='Process args for retrieving all the Virtual Machines')
parser.add_argument('-o', '--port', type=int, default=443, action='store', help='Port to connect on') parser.add_argument('-s', '--host', required=True, action='store',
parser.add_argument('-u', '--user', required=True, action='store', help='User name to use when connecting to host') help='Remote host to connect to')
parser.add_argument('-p', '--password', required=False, action='store', help='Password to use when connecting to host') parser.add_argument('-o', '--port', type=int, default=443, action='store',
help='Port to connect on')
parser.add_argument('-u', '--user', required=True, action='store',
help='User name to use when connecting to host')
parser.add_argument('-p', '--password', required=False, action='store',
help='Password to use when connecting to host')
args = parser.parse_args() args = parser.parse_args()
return args return args
def PrintVmInfo(vm, depth=1): def PrintVmInfo(vm, depth=1):
""" """
Print information for a particular virtual machine or recurse into a folder with depth protection Print information for a particular virtual machine or recurse into a folder
with depth protection
""" """
maxdepth = 10 maxdepth = 10
# if this is a group it will have children. if it does, recurse into them and then return # if this is a group it will have children. if it does, recurse into them
# and then return
if hasattr(vm, 'childEntity'): if hasattr(vm, 'childEntity'):
if depth > maxdepth: if depth > maxdepth:
return return
@@ -57,23 +69,20 @@ def PrintVmInfo(vm, depth=1):
return return
summary = vm.summary summary = vm.summary
print "Name : ", summary.config.name print("Name : ", summary.config.name)
print "Path : ", summary.config.vmPathName print("Path : ", summary.config.vmPathName)
print "Guest : ", summary.config.guestFullName print("Guest : ", summary.config.guestFullName)
print "Instance UUID : ", vm.summary.config.instanceUuid
print "BIOS UUID : ", vm.summary.config.uuid
annotation = summary.config.annotation annotation = summary.config.annotation
if annotation != None and annotation != "": if annotation != None and annotation != "":
print "Annotation : ", annotation print("Annotation : ", annotation)
print "State : ", summary.runtime.powerState print("State : ", summary.runtime.powerState)
if summary.guest != None: if summary.guest != None:
ip = summary.guest.ipAddress ip = summary.guest.ipAddress
if ip != None and ip != "": if ip != None and ip != "":
print "IP : ", ip print("IP : ", ip)
if summary.runtime.question != None: if summary.runtime.question != None:
print "Question : ", summary.runtime.question.text print("Question : ", summary.runtime.question.text)
print "" print("")
def main(): def main():
""" """
@@ -84,36 +93,28 @@ def main():
if args.password: if args.password:
password = args.password password = args.password
else: else:
password = getpass.getpass(prompt='Enter password for host %s and user %s: ' % (args.host,args.user)) password = getpass.getpass(prompt='Enter password for host %s and '
'user %s: ' % (args.host,args.user))
try:
si = None
try:
si = SmartConnect(host=args.host, si = SmartConnect(host=args.host,
user=args.user, user=args.user,
pwd=password, pwd=password,
port=int(args.port)) port=int(args.port))
except IOError, e:
pass
if not si: if not si:
print "Could not connect to the specified host using specified username and password" print("Could not connect to the specified host using specified "
"username and password")
return -1 return -1
atexit.register(Disconnect, si) atexit.register(Disconnect, si)
content = si.RetrieveContent() content = si.RetrieveContent()
datacenter = content.rootFolder.childEntity[0] for child in content.rootFolder.childEntity:
if hasattr(child, 'vmFolder'):
datacenter = child
vmFolder = datacenter.vmFolder vmFolder = datacenter.vmFolder
vmList = vmFolder.childEntity vmList = vmFolder.childEntity
for vm in vmList: for vm in vmList:
PrintVmInfo(vm) 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 return 0
# Start program # Start program

View File

@@ -19,6 +19,8 @@
Python program for powering on vms on a host on which hostd is running Python program for powering on vms on a host on which hostd is running
""" """
from __future__ import print_function
from pyVim.connect import SmartConnect, Disconnect from pyVim.connect import SmartConnect, Disconnect
from pyVmomi import vim, vmodl from pyVmomi import vim, vmodl
@@ -107,7 +109,7 @@ def main():
try: try:
vmnames = args.vmname vmnames = args.vmname
if not len(vmnames): if not len(vmnames):
print "No virtual machine specified for poweron" print("No virtual machine specified for poweron")
sys.exit() sys.exit()
si = None si = None
@@ -116,10 +118,10 @@ def main():
user=args.user, user=args.user,
pwd=password, pwd=password,
port=int(args.port)) port=int(args.port))
except IOError, e: except IOError:
pass pass
if not si: if not si:
print "Cannot connect to specified host using specified username and password" print("Cannot connect to specified host using specified username and password")
sys.exit() sys.exit()
atexit.register(Disconnect, si) atexit.register(Disconnect, si)
@@ -139,11 +141,11 @@ def main():
# Wait for power on to complete # Wait for power on to complete
WaitForTasks(tasks, si) WaitForTasks(tasks, si)
print "Virtual Machine(s) have been powered on successfully" print("Virtual Machine(s) have been powered on successfully")
except vmodl.MethodFault, e: except vmodl.MethodFault as e:
print "Caught vmodl fault : " + e.msg print("Caught vmodl fault : " + e.msg)
except Exception, e: except Exception as e:
print "Caught Exception : " + str(e) print("Caught Exception : " + str(e))
# Start program # Start program
if __name__ == "__main__": if __name__ == "__main__":

View File

@@ -1,4 +1,4 @@
mock contextdecorator
PyYAML>=3.11 PyYAML>=3.11
testtools>=0.9.34 testtools>=0.9.34
vcrpy>=1.0.2 vcrpy

265
tests/fixtures/smart_connection.yaml vendored Normal file
View File

@@ -0,0 +1,265 @@
interactions:
- request:
body: null
headers:
Connection: [close]
Host: ['vcsa:443']
User-Agent: [Python-urllib/2.7]
method: GET
uri: https://vcsa:443//sdk/vimServiceVersions.xml
response:
body: {string: !!python/unicode "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!--\n
\ Copyright 2008-2012 VMware, Inc. All rights reserved.\n-->\n<namespaces
version=\"1.0\">\n <namespace>\n <name>urn:vim25</name>\n <version>5.5</version>\n
\ <priorVersions>\n <version>5.1</version>\n <version>5.0</version>\n
\ <version>4.1</version>\n <version>4.0</version>\n <version>2.5u2</version>\n
\ <version>2.5</version>\n </priorVersions>\n </namespace>\n <namespace>\n
\ <name>urn:vim2</name>\n <version>2.0</version>\n </namespace>\n</namespaces>\n"}
headers:
connection: [close]
content-length: ['530']
content-type: [text/xml]
date: ['Wed, 23 Jul 2014 21:21:18 GMT']
status: {code: 200, message: OK}
- request:
body: '<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body><RetrieveServiceContent xmlns="urn:vim25"><_this type="ServiceInstance">ServiceInstance</_this></RetrieveServiceContent></soapenv:Body>
</soapenv:Envelope>'
headers:
Accept-Encoding: ['gzip, deflate']
Content-Type: [text/xml; charset=UTF-8]
Cookie: ['']
SOAPAction: ['"urn:vim25/5.5"']
method: POST
uri: https://vcsa:443/sdk
response:
body: {string: !!python/unicode "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<soapenv:Envelope
xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"\n xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"\n
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n<soapenv:Body>\n<RetrieveServiceContentResponse
xmlns=\"urn:vim25\"><returnval><rootFolder type=\"Folder\">group-d1</rootFolder><propertyCollector
type=\"PropertyCollector\">propertyCollector</propertyCollector><viewManager
type=\"ViewManager\">ViewManager</viewManager><about><name>VMware vCenter
Server</name><fullName>VMware vCenter Server 5.5.0 build-1750787 (Sim)</fullName><vendor>VMware,
Inc.</vendor><version>5.5.0</version><build>1750787 (Sim)</build><localeVersion>INTL</localeVersion><localeBuild>000</localeBuild><osType>linux-x64</osType><productLineId>vpx</productLineId><apiType>VirtualCenter</apiType><apiVersion>5.5</apiVersion><instanceUuid>EAB4D846-C243-426B-A021-0547644CE59D</instanceUuid><licenseProductName>VMware
VirtualCenter Server</licenseProductName><licenseProductVersion>5.0</licenseProductVersion></about><setting
type=\"OptionManager\">VpxSettings</setting><userDirectory type=\"UserDirectory\">UserDirectory</userDirectory><sessionManager
type=\"SessionManager\">SessionManager</sessionManager><authorizationManager
type=\"AuthorizationManager\">AuthorizationManager</authorizationManager><serviceManager
type=\"ServiceManager\">ServiceMgr</serviceManager><perfManager type=\"PerformanceManager\">PerfMgr</perfManager><scheduledTaskManager
type=\"ScheduledTaskManager\">ScheduledTaskManager</scheduledTaskManager><alarmManager
type=\"AlarmManager\">AlarmManager</alarmManager><eventManager type=\"EventManager\">EventManager</eventManager><taskManager
type=\"TaskManager\">TaskManager</taskManager><extensionManager type=\"ExtensionManager\">ExtensionManager</extensionManager><customizationSpecManager
type=\"CustomizationSpecManager\">CustomizationSpecManager</customizationSpecManager><customFieldsManager
type=\"CustomFieldsManager\">CustomFieldsManager</customFieldsManager><diagnosticManager
type=\"DiagnosticManager\">DiagMgr</diagnosticManager><licenseManager type=\"LicenseManager\">LicenseManager</licenseManager><searchIndex
type=\"SearchIndex\">SearchIndex</searchIndex><fileManager type=\"FileManager\">FileManager</fileManager><datastoreNamespaceManager
type=\"DatastoreNamespaceManager\">DatastoreNamespaceManager</datastoreNamespaceManager><virtualDiskManager
type=\"VirtualDiskManager\">virtualDiskManager</virtualDiskManager><snmpSystem
type=\"HostSnmpSystem\">SnmpSystem</snmpSystem><vmProvisioningChecker type=\"VirtualMachineProvisioningChecker\">ProvChecker</vmProvisioningChecker><vmCompatibilityChecker
type=\"VirtualMachineCompatibilityChecker\">CompatChecker</vmCompatibilityChecker><ovfManager
type=\"OvfManager\">OvfManager</ovfManager><ipPoolManager type=\"IpPoolManager\">IpPoolManager</ipPoolManager><dvSwitchManager
type=\"DistributedVirtualSwitchManager\">DVSManager</dvSwitchManager><hostProfileManager
type=\"HostProfileManager\">HostProfileManager</hostProfileManager><clusterProfileManager
type=\"ClusterProfileManager\">ClusterProfileManager</clusterProfileManager><complianceManager
type=\"ProfileComplianceManager\">MoComplianceManager</complianceManager><localizationManager
type=\"LocalizationManager\">LocalizationManager</localizationManager><storageResourceManager
type=\"StorageResourceManager\">StorageResourceManager</storageResourceManager><guestOperationsManager
type=\"GuestOperationsManager\">guestOperationsManager</guestOperationsManager></returnval></RetrieveServiceContentResponse>\n</soapenv:Body>\n</soapenv:Envelope>"}
headers:
cache-control: [no-cache]
connection: [Keep-Alive]
content-length: ['3611']
content-type: [text/xml; charset=utf-8]
date: ['Wed, 23 Jul 2014 21:21:18 GMT']
set-cookie: [vmware_soap_session="52773cd3-35c6-b40a-17f1-fe664a9f08f3"; Path=/;
HttpOnly; Secure;]
status: {code: 200, message: OK}
- request:
body: '<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body><Login xmlns="urn:vim25"><_this type="SessionManager">SessionManager</_this><userName>my_user</userName><password>my_password</password></Login></soapenv:Body>
</soapenv:Envelope>'
headers:
Accept-Encoding: ['gzip, deflate']
Content-Type: [text/xml; charset=UTF-8]
Cookie: [vmware_soap_session="52773cd3-35c6-b40a-17f1-fe664a9f08f3"; Path=/;
HttpOnly; Secure;]
SOAPAction: ['"urn:vim25/5.5"']
method: POST
uri: https://vcsa:443/sdk
response:
body: {string: !!python/unicode "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<soapenv:Envelope
xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"\n xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"\n
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n<soapenv:Body>\n<LoginResponse
xmlns=\"urn:vim25\"><returnval><key>52773cd3-35c6-b40a-17f1-fe664a9f08f3</key><userName>root</userName><fullName>root
</fullName><loginTime>2014-07-23T21:21:18.297208Z</loginTime><lastActiveTime>2014-07-23T21:21:18.297208Z</lastActiveTime><locale>en</locale><messageLocale>en</messageLocale><extensionSession>false</extensionSession><ipAddress>172.16.16.1</ipAddress><userAgent></userAgent><callCount>0</callCount></returnval></LoginResponse>\n</soapenv:Body>\n</soapenv:Envelope>"}
headers:
cache-control: [no-cache]
connection: [Keep-Alive]
content-length: ['782']
content-type: [text/xml; charset=utf-8]
date: ['Wed, 23 Jul 2014 21:21:18 GMT']
status: {code: 200, message: OK}
- request:
body: '<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body><RetrieveServiceContent xmlns="urn:vim25"><_this type="ServiceInstance">ServiceInstance</_this></RetrieveServiceContent></soapenv:Body>
</soapenv:Envelope>'
headers:
Accept-Encoding: ['gzip, deflate']
Content-Type: [text/xml; charset=UTF-8]
Cookie: [vmware_soap_session="52773cd3-35c6-b40a-17f1-fe664a9f08f3"; Path=/;
HttpOnly; Secure;]
SOAPAction: ['"urn:vim25/5.5"']
method: POST
uri: https://vcsa:443/sdk
response:
body: {string: !!python/unicode "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<soapenv:Envelope
xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"\n xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"\n
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n<soapenv:Body>\n<RetrieveServiceContentResponse
xmlns=\"urn:vim25\"><returnval><rootFolder type=\"Folder\">group-d1</rootFolder><propertyCollector
type=\"PropertyCollector\">propertyCollector</propertyCollector><viewManager
type=\"ViewManager\">ViewManager</viewManager><about><name>VMware vCenter
Server</name><fullName>VMware vCenter Server 5.5.0 build-1750787 (Sim)</fullName><vendor>VMware,
Inc.</vendor><version>5.5.0</version><build>1750787 (Sim)</build><localeVersion>INTL</localeVersion><localeBuild>000</localeBuild><osType>linux-x64</osType><productLineId>vpx</productLineId><apiType>VirtualCenter</apiType><apiVersion>5.5</apiVersion><instanceUuid>EAB4D846-C243-426B-A021-0547644CE59D</instanceUuid><licenseProductName>VMware
VirtualCenter Server</licenseProductName><licenseProductVersion>5.0</licenseProductVersion></about><setting
type=\"OptionManager\">VpxSettings</setting><userDirectory type=\"UserDirectory\">UserDirectory</userDirectory><sessionManager
type=\"SessionManager\">SessionManager</sessionManager><authorizationManager
type=\"AuthorizationManager\">AuthorizationManager</authorizationManager><serviceManager
type=\"ServiceManager\">ServiceMgr</serviceManager><perfManager type=\"PerformanceManager\">PerfMgr</perfManager><scheduledTaskManager
type=\"ScheduledTaskManager\">ScheduledTaskManager</scheduledTaskManager><alarmManager
type=\"AlarmManager\">AlarmManager</alarmManager><eventManager type=\"EventManager\">EventManager</eventManager><taskManager
type=\"TaskManager\">TaskManager</taskManager><extensionManager type=\"ExtensionManager\">ExtensionManager</extensionManager><customizationSpecManager
type=\"CustomizationSpecManager\">CustomizationSpecManager</customizationSpecManager><customFieldsManager
type=\"CustomFieldsManager\">CustomFieldsManager</customFieldsManager><diagnosticManager
type=\"DiagnosticManager\">DiagMgr</diagnosticManager><licenseManager type=\"LicenseManager\">LicenseManager</licenseManager><searchIndex
type=\"SearchIndex\">SearchIndex</searchIndex><fileManager type=\"FileManager\">FileManager</fileManager><datastoreNamespaceManager
type=\"DatastoreNamespaceManager\">DatastoreNamespaceManager</datastoreNamespaceManager><virtualDiskManager
type=\"VirtualDiskManager\">virtualDiskManager</virtualDiskManager><snmpSystem
type=\"HostSnmpSystem\">SnmpSystem</snmpSystem><vmProvisioningChecker type=\"VirtualMachineProvisioningChecker\">ProvChecker</vmProvisioningChecker><vmCompatibilityChecker
type=\"VirtualMachineCompatibilityChecker\">CompatChecker</vmCompatibilityChecker><ovfManager
type=\"OvfManager\">OvfManager</ovfManager><ipPoolManager type=\"IpPoolManager\">IpPoolManager</ipPoolManager><dvSwitchManager
type=\"DistributedVirtualSwitchManager\">DVSManager</dvSwitchManager><hostProfileManager
type=\"HostProfileManager\">HostProfileManager</hostProfileManager><clusterProfileManager
type=\"ClusterProfileManager\">ClusterProfileManager</clusterProfileManager><complianceManager
type=\"ProfileComplianceManager\">MoComplianceManager</complianceManager><localizationManager
type=\"LocalizationManager\">LocalizationManager</localizationManager><storageResourceManager
type=\"StorageResourceManager\">StorageResourceManager</storageResourceManager><guestOperationsManager
type=\"GuestOperationsManager\">guestOperationsManager</guestOperationsManager></returnval></RetrieveServiceContentResponse>\n</soapenv:Body>\n</soapenv:Envelope>"}
headers:
cache-control: [no-cache]
connection: [Keep-Alive]
content-length: ['3611']
content-type: [text/xml; charset=utf-8]
date: ['Wed, 23 Jul 2014 21:21:18 GMT']
status: {code: 200, message: OK}
- request:
body: '<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body><RetrievePropertiesEx xmlns="urn:vim25"><_this type="PropertyCollector">propertyCollector</_this><specSet><propSet><type>ServiceInstance</type><all>false</all><pathSet>content</pathSet></propSet><objectSet><obj
type="ServiceInstance">ServiceInstance</obj><skip>false</skip></objectSet></specSet><options><maxObjects>1</maxObjects></options></RetrievePropertiesEx></soapenv:Body>
</soapenv:Envelope>'
headers:
Accept-Encoding: ['gzip, deflate']
Content-Type: [text/xml; charset=UTF-8]
Cookie: [vmware_soap_session="52773cd3-35c6-b40a-17f1-fe664a9f08f3"; Path=/;
HttpOnly; Secure;]
SOAPAction: ['"urn:vim25/5.5"']
method: POST
uri: https://vcsa:443/sdk
response:
body: {string: !!python/unicode "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<soapenv:Envelope
xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"\n xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"\n
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n<soapenv:Body>\n<RetrievePropertiesExResponse
xmlns=\"urn:vim25\"><returnval><objects><obj type=\"ServiceInstance\">ServiceInstance</obj><propSet><name>content</name><val
xsi:type=\"ServiceContent\"><rootFolder type=\"Folder\">group-d1</rootFolder><propertyCollector
type=\"PropertyCollector\">propertyCollector</propertyCollector><viewManager
type=\"ViewManager\">ViewManager</viewManager><about><name>VMware vCenter
Server</name><fullName>VMware vCenter Server 5.5.0 build-1750787 (Sim)</fullName><vendor>VMware,
Inc.</vendor><version>5.5.0</version><build>1750787 (Sim)</build><localeVersion>INTL</localeVersion><localeBuild>000</localeBuild><osType>linux-x64</osType><productLineId>vpx</productLineId><apiType>VirtualCenter</apiType><apiVersion>5.5</apiVersion><instanceUuid>EAB4D846-C243-426B-A021-0547644CE59D</instanceUuid><licenseProductName>VMware
VirtualCenter Server</licenseProductName><licenseProductVersion>5.0</licenseProductVersion></about><setting
type=\"OptionManager\">VpxSettings</setting><userDirectory type=\"UserDirectory\">UserDirectory</userDirectory><sessionManager
type=\"SessionManager\">SessionManager</sessionManager><authorizationManager
type=\"AuthorizationManager\">AuthorizationManager</authorizationManager><serviceManager
type=\"ServiceManager\">ServiceMgr</serviceManager><perfManager type=\"PerformanceManager\">PerfMgr</perfManager><scheduledTaskManager
type=\"ScheduledTaskManager\">ScheduledTaskManager</scheduledTaskManager><alarmManager
type=\"AlarmManager\">AlarmManager</alarmManager><eventManager type=\"EventManager\">EventManager</eventManager><taskManager
type=\"TaskManager\">TaskManager</taskManager><extensionManager type=\"ExtensionManager\">ExtensionManager</extensionManager><customizationSpecManager
type=\"CustomizationSpecManager\">CustomizationSpecManager</customizationSpecManager><customFieldsManager
type=\"CustomFieldsManager\">CustomFieldsManager</customFieldsManager><diagnosticManager
type=\"DiagnosticManager\">DiagMgr</diagnosticManager><licenseManager type=\"LicenseManager\">LicenseManager</licenseManager><searchIndex
type=\"SearchIndex\">SearchIndex</searchIndex><fileManager type=\"FileManager\">FileManager</fileManager><datastoreNamespaceManager
type=\"DatastoreNamespaceManager\">DatastoreNamespaceManager</datastoreNamespaceManager><virtualDiskManager
type=\"VirtualDiskManager\">virtualDiskManager</virtualDiskManager><snmpSystem
type=\"HostSnmpSystem\">SnmpSystem</snmpSystem><vmProvisioningChecker type=\"VirtualMachineProvisioningChecker\">ProvChecker</vmProvisioningChecker><vmCompatibilityChecker
type=\"VirtualMachineCompatibilityChecker\">CompatChecker</vmCompatibilityChecker><ovfManager
type=\"OvfManager\">OvfManager</ovfManager><ipPoolManager type=\"IpPoolManager\">IpPoolManager</ipPoolManager><dvSwitchManager
type=\"DistributedVirtualSwitchManager\">DVSManager</dvSwitchManager><hostProfileManager
type=\"HostProfileManager\">HostProfileManager</hostProfileManager><clusterProfileManager
type=\"ClusterProfileManager\">ClusterProfileManager</clusterProfileManager><complianceManager
type=\"ProfileComplianceManager\">MoComplianceManager</complianceManager><localizationManager
type=\"LocalizationManager\">LocalizationManager</localizationManager><storageResourceManager
type=\"StorageResourceManager\">StorageResourceManager</storageResourceManager><guestOperationsManager
type=\"GuestOperationsManager\">guestOperationsManager</guestOperationsManager></val></propSet></objects></returnval></RetrievePropertiesExResponse>\n</soapenv:Body>\n</soapenv:Envelope>"}
headers:
cache-control: [no-cache]
connection: [Keep-Alive]
content-length: ['3751']
content-type: [text/xml; charset=utf-8]
date: ['Wed, 23 Jul 2014 21:21:18 GMT']
status: {code: 200, message: OK}
- request:
body: '<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body><RetrievePropertiesEx xmlns="urn:vim25"><_this type="PropertyCollector">propertyCollector</_this><specSet><propSet><type>SessionManager</type><all>false</all><pathSet>currentSession</pathSet></propSet><objectSet><obj
type="SessionManager">SessionManager</obj><skip>false</skip></objectSet></specSet><options><maxObjects>1</maxObjects></options></RetrievePropertiesEx></soapenv:Body>
</soapenv:Envelope>'
headers:
Accept-Encoding: ['gzip, deflate']
Content-Type: [text/xml; charset=UTF-8]
Cookie: [vmware_soap_session="52773cd3-35c6-b40a-17f1-fe664a9f08f3"; Path=/;
HttpOnly; Secure;]
SOAPAction: ['"urn:vim25/5.5"']
method: POST
uri: https://vcsa:443/sdk
response:
body: {string: !!python/unicode "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<soapenv:Envelope
xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"\n xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"\n
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n<soapenv:Body>\n<RetrievePropertiesExResponse
xmlns=\"urn:vim25\"><returnval><objects><obj type=\"SessionManager\">SessionManager</obj><propSet><name>currentSession</name><val
xsi:type=\"UserSession\"><key>52773cd3-35c6-b40a-17f1-fe664a9f08f3</key><userName>my_user</userName><fullName>My User
</fullName><loginTime>2014-07-23T21:21:18.297208Z</loginTime><lastActiveTime>2014-07-23T21:21:18.297208Z</lastActiveTime><locale>en</locale><messageLocale>en</messageLocale><extensionSession>false</extensionSession><ipAddress>172.16.16.1</ipAddress><userAgent></userAgent><callCount>1</callCount></val></propSet></objects></returnval></RetrievePropertiesExResponse>\n</soapenv:Body>\n</soapenv:Envelope>"}
headers:
cache-control: [no-cache]
connection: [Keep-Alive]
content-length: ['958']
content-type: [text/xml; charset=utf-8]
date: ['Wed, 23 Jul 2014 21:21:18 GMT']
status: {code: 200, message: OK}
version: 1

View File

@@ -50,3 +50,18 @@ class ConnectionTests(unittest.TestCase):
pwd='bad_password') pwd='bad_password')
self.assertRaises(vim.fault.InvalidLogin, should_fail) self.assertRaises(vim.fault.InvalidLogin, should_fail)
@vcr.use_cassette('smart_connection.yaml',
cassette_library_dir=fixtures_path, record_mode='none')
def test_smart_connection(self):
# see: http://python3porting.com/noconv.html
si = connect.SmartConnect(host='vcsa',
user='my_user',
pwd='my_password')
session_id = si.content.sessionManager.currentSession.key
# NOTE (hartsock): assertIsNotNone does not work in Python 2.6
self.assertTrue(session_id is not None)
self.assertEqual('52773cd3-35c6-b40a-17f1-fe664a9f08f3', session_id)
if __name__ == '__main__':
unittest.main()