Python suds (SOAP Library) does not support SSLv3
The Oracle Virtual Machine (OVM) manager exposes a SOAP (wsdl) web-service. At the time of writing this can be found here: (for version 3.2.x)
https://<hostname>:7002/ovm/core/wsapi/soap?wsdl
You can access this url in your web browser and will be prompted to accept the self signed cert etc. (There is a way to add a real certificate but that's not what this article is about.)
In order to consume this webservice in python, I thought to try out the (now quite old) "suds" library. Opensuse still ship this library and you can install it with:
The problem I found was that when trying to connect to the service, I was receiving an exception error around SSL.
Here is how it looked...
The example code:
Rather than mess with the urllib2 library, I decided to download the source for the suds library, and fix the library.
Download suds from here:
The example code but this time you place your example code in the downloaded source tree so that python uses the local library. OR You can make the above modifications to your installed library which should be somewhere in /usr/lib/python-2.7/site-packages/suds.
Up to you.
Example Code:
https://<hostname>:7002/ovm/core/wsapi/soap?wsdl
You can access this url in your web browser and will be prompted to accept the self signed cert etc. (There is a way to add a real certificate but that's not what this article is about.)
In order to consume this webservice in python, I thought to try out the (now quite old) "suds" library. Opensuse still ship this library and you can install it with:
zypper in python-sudsEDIT: I have added the forked library to github here: https://github.com/linuxplayground/suds-sslv3-fork
The problem I found was that when trying to connect to the service, I was receiving an exception error around SSL.
Here is how it looked...
The example code:
#!/usr/bin/python from suds.client import Client client = Client(url='https://ovm:7002/ovm/core/wsapi/soap?wsdl') print clientOutput:
david.latham@davidpc:~/bin/ovm-webservices> python broken.py Traceback (most recent call last): File "broken.py", line 3, inThat last line, "SSL23_GET_SERVER_HELLO:unknown protocol" had me stuck for ages. Eventually I found a blog post that suggested this can be fixed by adding a new HTTPHandler to the URLLIB2 Opener.client = Client(url='https://ovm:7002/ovm/core/wsapi/soap?wsdl') File "/usr/lib/python2.7/site-packages/suds/client.py", line 112, in __init__ self.wsdl = reader.open(url) File "/usr/lib/python2.7/site-packages/suds/reader.py", line 152, in open d = self.fn(url, self.options) File "/usr/lib/python2.7/site-packages/suds/wsdl.py", line 136, in __init__ d = reader.open(url) File "/usr/lib/python2.7/site-packages/suds/reader.py", line 79, in open d = self.download(url) File "/usr/lib/python2.7/site-packages/suds/reader.py", line 95, in download fp = self.options.transport.open(Request(url)) File "/usr/lib/python2.7/site-packages/suds/transport/https.py", line 60, in open return HttpTransport.open(self, request) File "/usr/lib/python2.7/site-packages/suds/transport/http.py", line 62, in open return self.u2open(u2request) File "/usr/lib/python2.7/site-packages/suds/transport/http.py", line 118, in u2open return url.open(u2request, timeout=tm) File "/usr/lib64/python2.7/urllib2.py", line 404, in open response = self._open(req, data) File "/usr/lib64/python2.7/urllib2.py", line 422, in _open '_open', req) File "/usr/lib64/python2.7/urllib2.py", line 382, in _call_chain result = func(*args) File "/usr/lib64/python2.7/urllib2.py", line 1222, in https_open return self.do_open(httplib.HTTPSConnection, req) File "/usr/lib64/python2.7/urllib2.py", line 1184, in do_open raise URLError(err) urllib2.URLError:
Rather than mess with the urllib2 library, I decided to download the source for the suds library, and fix the library.
Download suds from here:
svn co http://svn.fedorahosted.org/svn/suds/trunkIn the source tree add the following httpsconnectionv3.py to /path/to/downloaded/source/suds/transport/httpsconnectionv3.py
#!/usr/bin/python import httplib, ssl, urllib2, socket class HTTPSConnectionV3(httplib.HTTPSConnection): def __init__(self, *args, **kwargs): httplib.HTTPSConnection.__init__(self, *args, **kwargs) def connect(self): sock = socket.create_connection((self.host, self.port), self.timeout) if self._tunnel_host: self.sock = sock self._tunnel() try: self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=ssl.PROTOCOL_SSLv3) except ssl.SSLError, e: print("Trying SSLv3.") self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=ssl.PROTOCOL_SSLv23) class HTTPSHandlerV3(urllib2.HTTPSHandler): def https_open(self, req): return self.do_open(HTTPSConnectionV3, req)Then update /path/to/downloaded/source/suds/transport/http.py with the following additions:
- include the new library in the imports
- from httpsconnectionv3 import *
- Add the following line to the function "u2handlers" after the line "handlers.append(u2.ProxyHandler(self.proxy))"
- handlers.append(HTTPSHandlerV3())
The example code but this time you place your example code in the downloaded source tree so that python uses the local library. OR You can make the above modifications to your installed library which should be somewhere in /usr/lib/python-2.7/site-packages/suds.
Up to you.
Example Code:
david.latham@davidpc:~/bin/ovm-webservices/ovm_wsapi> cat getVMList.py #!/usr/bin/python from suds.client import Client client = Client(url='https://ovm:7002/ovm/core/wsapi/soap?wsdl') username='admin' password='xxxxxxxx' loginResponse = client.service.login(username,password) print "Logging in .... <%s>" % loginResponse if loginResponse == True: vmlist = client.service.vmGetAll() for vm in vmlist: if vm.vmRunState == 'RUNNING' or vm.vmRunState == 'STOPPED': print "%s | %s" % (vm.name, vm.vmRunState) logoutResponse = client.service.logout() print "Logging out ... <%s>" % logoutResponse else: print "login failure"Output:
david.latham@davidpc:~/bin/ovm-webservices/ovm_wsapi> ./getVMList.py Logging in ....So that fixes suds for sslv3puppetmaster | RUNNING ksplice-test | RUNNING zimbra-test-el6 | STOPPED ksplice-client | RUNNING DB2_Server_RHEL58 | STOPPED ora133 | STOPPED secret_host_1 | STOPPED zimbra-test | RUNNING sqlsandpit | RUNNING secret_host_2 | STOPPED repo_server | RUNNING Logging out ...
Comments
The first symptom I had for this issue was:
urllib2.URLError:
Further diggin gusing a different URL revealed this:
urllib2.URLError:
and your post just saved my afternoon. Cheers!!
I have not actually implemented this in the proper OOP way. I think we should rather demonstrate how to create a class that inherits the original and overrides the appropriate functions.
Anyway - glad it helped someone.