initial fixture based testing setup

* new dependencies files
* makes testing possible
* defines fixture storage paths
* creates initial fixture for testing
* defines test requirements
* fixes connection fault so that it raises a traceback for diagnostics

partial https://github.com/vmware/pyvmomi/issues/42
blocks https://github.com/vmware/pyvmomi/issues/55
This commit is contained in:
Shawn Hartsock 2014-07-21 18:58:16 -04:00
parent 66871e5f19
commit cd533499cb
10 changed files with 471 additions and 40 deletions

View File

@ -6,10 +6,10 @@ python:
before_install:
- if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install unittest2; fi
- pip install -r requirements.txt
- pip install -r test-requirements.txt
install:
- python setup.py bdist_egg
- pip install -e file://$TRAVIS_BUILD_DIR
- python setup.py -q install
script:
nosetests
script: python setup.py test

View File

@ -23,7 +23,7 @@ Connect to a VMOMI ServiceInstance.
Detailed description (for [e]pydoc goes here).
"""
from six import reraise
import sys
import threading
import thread
@ -313,7 +313,13 @@ def __Login(host, port, user, pwd, service, adapter, version, path,
except vmodl.MethodFault:
raise
except Exception, e:
raise vim.fault.HostConnectFault(msg=str(e))
# NOTE (hartsock): preserve the traceback for diagnostics
# pulling and preserving the traceback makes diagnosing connection
# failures easier since the fault will also include where inside the
# library the fault occurred. Without the traceback we have no idea
# why the connection failed beyond the message string.
(type, value, traceback) = sys.exc_info()
reraise(vim.fault.HostConnectFault(msg=str(e)), None, traceback)
# Get a ticket if we're connecting to localhost and password is not specified
if host == 'localhost' and not pwd:

View File

@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import httplib
from six.moves import http_client
import sys
import os
import time
@ -854,7 +854,9 @@ class SoapStubAdapterBase(StubAdapterBase):
## Subclass of HTTPConnection that connects over a Unix domain socket
## instead of a TCP port. The path of the socket is passed in place of
## the hostname. Fairly gross but does the job.
class UnixSocketConnection(httplib.HTTPConnection):
# NOTE (hartsock): rewrite this class as a wrapper, see HTTPSConnectionWrapper
# below for a guide.
class UnixSocketConnection(http_client.HTTPConnection):
# The HTTPConnection ctor expects a single argument, which it interprets
# as the host to connect to; for UnixSocketConnection, we instead interpret
# the parameter as the filesystem path of the Unix domain socket.
@ -862,7 +864,7 @@ class UnixSocketConnection(httplib.HTTPConnection):
# Pass '' as the host to HTTPConnection; it doesn't really matter
# what we pass (since we've overridden the connect method) as long
# as it's a valid string.
httplib.HTTPConnection.__init__(self, '')
http_client.HTTPConnection.__init__(self, '')
self.path = path
def connect(self):
@ -884,7 +886,7 @@ try:
'''If there is a thumbprint, connect to the server and verify that the
SSL certificate matches the given thumbprint. An exception is thrown
if there is a mismatch.'''
if thumbprint and isinstance(connection, httplib.HTTPSConnection):
if thumbprint and isinstance(connection, http_client.HTTPSConnection):
if not connection.sock:
connection.connect()
derCert = connection.sock.getpeercert(True)
@ -903,21 +905,28 @@ except ImportError:
SSL_THUMBPRINTS_SUPPORTED = False
def _VerifyThumbprint(thumbprint, connection):
if thumbprint and isinstance(connection, httplib.HTTPSConnection):
if thumbprint and isinstance(connection, http_client.HTTPSConnection):
raise Exception(
"Thumbprint verification not supported on python < 2.6")
def _SocketWrapper(rawSocket, keyfile, certfile, *args, **kwargs):
wrappedSocket = socket.ssl(rawSocket, keyfile, certfile)
return httplib.FakeSocket(rawSocket, wrappedSocket)
return http_client.FakeSocket(rawSocket, wrappedSocket)
## Internal version of https connection
## https connection wrapper
#
# NOTE (hartsock): do not override core library types or implementations
# directly because this makes brittle code that is too easy to break and
# closely tied to implementation details we do not control. Instead, wrap
# the core object to introduce additional behaviors.
#
# Purpose:
# Support ssl.wrap_socket params which are missing from httplib
# HTTPSConnection (e.g. ca_certs)
# Note: Only works iff the ssl params are passing in as kwargs
class _HTTPSConnection(httplib.HTTPSConnection):
class HTTPSConnectionWrapper(object):
def __init__(self, *args, **kwargs):
wrapped = http_client.HTTPSConnection(*args, **kwargs)
# Extract ssl.wrap_socket param unknown to httplib.HTTPConnection,
# and push back the params in connect()
self._sslArgs = {}
@ -927,15 +936,14 @@ class _HTTPSConnection(httplib.HTTPSConnection):
"ciphers"]:
if key in tmpKwargs:
self._sslArgs[key] = tmpKwargs.pop(key)
httplib.HTTPSConnection.__init__(self, *args, **tmpKwargs)
self._wrapped = wrapped
## Override connect to allow us to pass in additional ssl paramters to
# ssl.wrap_socket (e.g. cert_reqs, ca_certs for ca cert verification)
def connect(self):
if len(self._sslArgs) == 0:
def connect(self, wrapped):
if len(self._sslArgs) == 0 or hasattr(self, '_baseclass'):
# No override
httplib.HTTPSConnection.connect(self)
return
return wrapped.connect
# Big hack. We have to copy and paste the httplib connect fn for
# each python version in order to handle extra ssl paramters. Yuk!
@ -943,18 +951,16 @@ class _HTTPSConnection(httplib.HTTPSConnection):
# Python 2.7
sock = socket.create_connection((self.host, self.port),
self.timeout, self.source_address)
if self._tunnel_host:
self.sock = sock
self._tunnel()
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, **self._sslArgs)
if wrapped._tunnel_host:
wrapped.sock = sock
wrapped._tunnel()
wrapped.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, **self._sslArgs)
elif hasattr(self, "timeout"):
# Python 2.6
sock = socket.create_connection((self.host, self.port), self.timeout)
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, **self._sslArgs)
else:
# Unknown python version. Do nothing
httplib.HTTPSConnection.connect(self)
return
wrapped.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, **self._sslArgs)
return wrapped.connect
# TODO: Additional verification of peer cert if needed
#cert_reqs = self._sslArgs.get("cert_reqs", ssl.CERT_NONE)
@ -965,6 +971,11 @@ class _HTTPSConnection(httplib.HTTPSConnection):
# dercert = self.sock.getpeercert(False)
# # pemcert = ssl.DER_cert_to_PEM_cert(dercert)
def __getattr__(self, item):
if item == 'connect':
return self.connect(self._wrapped)
return getattr(self._wrapped, item)
## Stand-in for the HTTPSConnection class that will connect to a proxy and
## issue a CONNECT command to start an SSL tunnel.
class SSLTunnelConnection(object):
@ -985,13 +996,13 @@ class SSLTunnelConnection(object):
for arg in kwargs.keys():
if arg not in ("port", "strict", "timeout", "source_address"):
del kwargs[arg]
tunnel = httplib.HTTPConnection(path, **kwargs)
tunnel = http_client.HTTPConnection(path, **kwargs)
tunnel.request('CONNECT', self.proxyPath)
resp = tunnel.getresponse()
tunnelSocket = resp.fp
if resp.status != 200:
raise httplib.HTTPException("%d %s" % (resp.status, resp.reason))
retval = httplib.HTTPSConnection(path)
raise http_client.HTTPException("%d %s" % (resp.status, resp.reason))
retval = http_client.HTTPSConnection(path)
retval.sock = _SocketWrapper(tunnelSocket,
keyfile=key_file, certfile=cert_file)
return retval
@ -1121,11 +1132,11 @@ class SoapStubAdapter(SoapStubAdapterBase):
# keyword argument as passed in.
if urlpath not in ('', '/'):
path = urlpath
self.scheme = scheme == "http" and httplib.HTTPConnection \
or scheme == "https" and _HTTPSConnection
self.scheme = scheme == "http" and http_client.HTTPConnection \
or scheme == "https" and HTTPSConnectionWrapper
else:
port, self.scheme = port < 0 and (-port, httplib.HTTPConnection) \
or (port, _HTTPSConnection)
port, self.scheme = port < 0 and (-port, http_client.HTTPConnection) \
or (port, HTTPSConnectionWrapper)
if host.find(':') != -1: # is IPv6?
host = '[' + host + ']'
self.host = '%s:%d' % (host, port)
@ -1141,7 +1152,7 @@ class SoapStubAdapter(SoapStubAdapterBase):
if sslProxyPath:
self.scheme = SSLTunnelConnection(sslProxyPath)
elif httpProxyHost:
if self.scheme == _HTTPSConnection:
if self.scheme == HTTPSConnectionWrapper:
self.scheme = SSLTunnelConnection(self.host)
else:
if url:
@ -1206,7 +1217,7 @@ class SoapStubAdapter(SoapStubAdapterBase):
try:
conn.request('POST', self.path, req, headers)
resp = conn.getresponse()
except (socket.error, httplib.HTTPException):
except (socket.error, http_client.HTTPException):
# The server is probably sick, drop all of the cached connections.
self.DropConnections()
raise
@ -1240,7 +1251,7 @@ class SoapStubAdapter(SoapStubAdapterBase):
raise obj # pylint: disable-msg=E0702
else:
conn.close()
raise httplib.HTTPException("%d %s" % (resp.status, resp.reason))
raise http_client.HTTPException("%d %s" % (resp.status, resp.reason))
## Clean up connection pool to throw away idle timed-out connections
# SoapStubAdapter lock must be acquired before this method is called.
@ -1461,7 +1472,7 @@ class SessionOrientedStub(StubAdapterBase):
self._CallLoginMethod()
# Invoke the method
status, obj = self.soapStub.InvokeMethod(mo, info, args, self)
except (socket.error, httplib.HTTPException, ExpatError):
except (socket.error, http_client.HTTPException, ExpatError):
if self.retryDelay and retriesLeft:
time.sleep(self.retryDelay)
retriesLeft -= 1
@ -1497,7 +1508,7 @@ class SessionOrientedStub(StubAdapterBase):
self._CallLoginMethod()
# Invoke the method
obj = StubAdapterBase.InvokeAccessor(self, mo, info)
except (socket.error, httplib.HTTPException, ExpatError):
except (socket.error, http_client.HTTPException, ExpatError):
if self.retryDelay and retriesLeft:
time.sleep(self.retryDelay)
retriesLeft -= 1

2
requirements.txt Normal file
View File

@ -0,0 +1,2 @@
requests>=2.3.0
six>=1.7.3

View File

@ -16,9 +16,16 @@
from setuptools import setup
import os
def read(fname):
return open(os.path.join(os.path.dirname(__file__), fname)).read()
with open('requirements.txt') as f:
required = f.read().splitlines()
with open('test-requirements.txt') as f:
required_for_tests = f.read().splitlines()
setup(
name='pyvmomi',
version='5.5.0_2014.dev',
@ -27,6 +34,7 @@ setup(
author_email='jhu@vmware.com',
url='https://github.com/vmware/pyvmomi',
packages=['pyVmomi', 'pyVim'],
install_requires=required,
license='Apache',
long_description=read('README.md'),
classifiers=[
@ -38,5 +46,7 @@ setup(
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: System :: Distributed Computing"
],
test_suite='tests',
tests_require= required_for_tests,
zip_safe=True
)

4
test-requirements.txt Normal file
View File

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

23
tests/__init__.py Normal file
View File

@ -0,0 +1,23 @@
# VMware vSphere Python SDK
# Copyright (c) 2008-2014 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.
import os
def tests_resource_path(local_path=''):
this_file = os.path.dirname(os.path.abspath(__file__))
return os.path.join(this_file, local_path)
# Fully qualified path to the fixtures directory underneath this module
fixtures_path = tests_resource_path('fixtures')

234
tests/fixtures/basic_connection.yaml vendored Normal file
View File

@ -0,0 +1,234 @@
interactions:
- 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/4.1"']
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-1623101 (Sim)</fullName><vendor>VMware,
Inc.</vendor><version>5.5.0</version><build>1623101 (Sim)</build><localeVersion>INTL</localeVersion><localeBuild>000</localeBuild><osType>linux-x64</osType><productLineId>vpx</productLineId><apiType>VirtualCenter</apiType><apiVersion>5.5</apiVersion><instanceUuid>E8636946-5510-44E7-B288-20DA0AD9DA38</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><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><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></returnval></RetrieveServiceContentResponse>\n</soapenv:Body>\n</soapenv:Envelope>"}
headers:
cache-control: [no-cache]
connection: [Keep-Alive]
content-length: ['3332']
content-type: [text/xml; charset=utf-8]
date: ['Mon, 21 Jul 2014 22:31:05 GMT']
set-cookie: [vmware_soap_session="52970dd3-2b0f-647b-22b3-44bda6d49983"; 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="52970dd3-2b0f-647b-22b3-44bda6d49983"; Path=/;
HttpOnly; Secure;]
SOAPAction: ['"urn:vim25/4.1"']
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>my_user</userName><fullName>My User
</fullName><loginTime>2014-07-21T22:31:05.480973Z</loginTime><lastActiveTime>2014-07-21T22:31:05.480973Z</lastActiveTime><locale>en</locale><messageLocale>en</messageLocale></returnval></LoginResponse>\n</soapenv:Body>\n</soapenv:Envelope>"}
headers:
cache-control: [no-cache]
connection: [Keep-Alive]
content-length: ['659']
content-type: [text/xml; charset=utf-8]
date: ['Mon, 21 Jul 2014 22:31:05 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="52970dd3-2b0f-647b-22b3-44bda6d49983"; Path=/;
HttpOnly; Secure;]
SOAPAction: ['"urn:vim25/4.1"']
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-1623101 (Sim)</fullName><vendor>VMware,
Inc.</vendor><version>5.5.0</version><build>1623101 (Sim)</build><localeVersion>INTL</localeVersion><localeBuild>000</localeBuild><osType>linux-x64</osType><productLineId>vpx</productLineId><apiType>VirtualCenter</apiType><apiVersion>5.5</apiVersion><instanceUuid>E8636946-5510-44E7-B288-20DA0AD9DA38</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><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><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></returnval></RetrieveServiceContentResponse>\n</soapenv:Body>\n</soapenv:Envelope>"}
headers:
cache-control: [no-cache]
connection: [Keep-Alive]
content-length: ['3332']
content-type: [text/xml; charset=utf-8]
date: ['Mon, 21 Jul 2014 22:31:05 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="52970dd3-2b0f-647b-22b3-44bda6d49983"; Path=/;
HttpOnly; Secure;]
SOAPAction: ['"urn:vim25/4.1"']
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-1623101 (Sim)</fullName><vendor>VMware,
Inc.</vendor><version>5.5.0</version><build>1623101 (Sim)</build><localeVersion>INTL</localeVersion><localeBuild>000</localeBuild><osType>linux-x64</osType><productLineId>vpx</productLineId><apiType>VirtualCenter</apiType><apiVersion>5.5</apiVersion><instanceUuid>E8636946-5510-44E7-B288-20DA0AD9DA38</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><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><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></val></propSet></objects></returnval></RetrievePropertiesExResponse>\n</soapenv:Body>\n</soapenv:Envelope>"}
headers:
cache-control: [no-cache]
connection: [Keep-Alive]
content-length: ['3472']
content-type: [text/xml; charset=utf-8]
date: ['Mon, 21 Jul 2014 22:31:05 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="52970dd3-2b0f-647b-22b3-44bda6d49983"; Path=/;
HttpOnly; Secure;]
SOAPAction: ['"urn:vim25/4.1"']
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-21T22:31:05.480973Z</loginTime><lastActiveTime>2014-07-21T22:31:05.480973Z</lastActiveTime><locale>en</locale><messageLocale>en</messageLocale></val></propSet></objects></returnval></RetrievePropertiesExResponse>\n</soapenv:Body>\n</soapenv:Envelope>"}
headers:
cache-control: [no-cache]
connection: [Keep-Alive]
content-length: ['835']
content-type: [text/xml; charset=utf-8]
date: ['Mon, 21 Jul 2014 22:31:05 GMT']
status: {code: 200, message: OK}
version: 1

View File

@ -0,0 +1,89 @@
interactions:
- 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/4.1"']
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><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><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></returnval></RetrieveServiceContentResponse>\n</soapenv:Body>\n</soapenv:Envelope>"}
headers:
cache-control: [no-cache]
connection: [Keep-Alive]
content-length: ['3332']
content-type: [text/xml; charset=utf-8]
date: ['Tue, 22 Jul 2014 17:36:32 GMT']
set-cookie: [vmware_soap_session="528b8755-46b5-df6a-47fd-89e57d4807c5"; 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>bad_password</password></Login></soapenv:Body>
</soapenv:Envelope>'
headers:
Accept-Encoding: ['gzip, deflate']
Content-Type: [text/xml; charset=UTF-8]
Cookie: [vmware_soap_session="528b8755-46b5-df6a-47fd-89e57d4807c5"; Path=/;
HttpOnly; Secure;]
SOAPAction: ['"urn:vim25/4.1"']
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<soapenv:Fault><faultcode>ServerFaultCode</faultcode><faultstring>Cannot
complete login due to an incorrect user name or password.</faultstring><detail><InvalidLoginFault
xmlns=\"urn:vim25\" xsi:type=\"InvalidLogin\"></InvalidLoginFault></detail></soapenv:Fault>\n</soapenv:Body>\n</soapenv:Envelope>"}
headers:
cache-control: [no-cache]
connection: [Keep-Alive]
content-length: ['585']
content-type: [text/xml; charset=utf-8]
date: ['Tue, 22 Jul 2014 17:36:37 GMT']
status: {code: 500, message: Internal Server Error}
version: 1

52
tests/test_connect.py Normal file
View File

@ -0,0 +1,52 @@
# VMware vSphere Python SDK
# Copyright (c) 2008-2014 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 tests import fixtures_path
import logging
import unittest
import vcr
from pyVim import connect
from pyVmomi import vim
class ConnectionTests(unittest.TestCase):
def setUp(self):
logging.basicConfig()
vcr_log = logging.getLogger('vcr')
vcr_log.setLevel(logging.DEBUG)
@vcr.use_cassette('basic_connection.yaml',
cassette_library_dir=fixtures_path, record_mode='none')
def test_basic_connection(self):
# see: http://python3porting.com/noconv.html
si = connect.Connect(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)
@vcr.use_cassette('basic_connection_bad_password.yaml',
cassette_library_dir=fixtures_path, record_mode='none')
def test_basic_connection_bad_password(self):
def should_fail():
connect.Connect(host='vcsa',
user='my_user',
pwd='bad_password')
self.assertRaises(vim.fault.InvalidLogin, should_fail)