<div>Hello-</div><div><br></div><div>I have a project that is based on Twisted used to</div><div>communicate with network devices and I am adding support for a new</div><div>vendor (Citrix NetScaler) whose API is SOAP. Unfortunately the</div>
<div>support for SOAP in Twisted still relies on SOAPpy, which is badly out</div><div>of date. In fact as of this email (I just checked), twisted.web.soap</div><div>itself hasn't even been updated in 21 months!</div><div>
<br></div><div>I would like to ask if anyone has any experience they would be willing</div><div>to share with utilizing Twisted's superb asynchronous transport</div><div>functionality with SUDS. It seems like plugging in a custom Twisted</div>
<div>transport would be a natural fit in SUDS' Client.options.transport, I'm just having</div><div>a hard time wrapping my head around it.</div><div><br></div><div>I did come up with a way to call the SOAP method with SUDS</div>
<div>asynchronously by utilizing twisted.internet.threads.deferToThread(),</div><div>but this feels like a hack to me.</div><div><br></div><div>Here is an example of what I've done, just to give you an idea:</div><div>
<br></div><div> # netscaler is a module I wrote using suds to interface with NetScaler SOAP</div><div> # Source: <a href="http://bitbucket.org/jathanism/netscaler-api/src">http://bitbucket.org/jathanism/netscaler-api/src</a></div>
<div> import netscaler</div><div> import os, sys</div><div> from twisted.internet import reactor, defer, threads</div><div><br></div><div> # netscaler.API is the class that sets up the suds.client.Client object</div>
<div> host = 'netscaler.local'</div><div> username = password = 'nsroot'</div><div> wsdl_url = 'file://' + os.path.join(os.getcwd(), 'NSUserAdmin.wsdl')</div><div> api = netscaler.API(host, username=username, password=password,</div>
<div>wsdl_url=wsdl_url)</div><div><br></div><div> results = []</div><div> errors = []</div><div><br></div><div> def handleResult(result):</div><div> print '\tgot result: %s' % (result,)</div><div> results.append(result)</div>
<div><br></div><div> def handleError(err):</div><div> sys.stderr.write('\tgot failure: %s' % (err,))</div><div> errors.append(err)</div><div><br></div><div> # this converts the api.login() call to a Twisted thread. </div>
<div> # api.login() is equivalent to:</div><div> # api.service.login(username=self.username, password=self.password)</div><div> deferred = threads.deferToThread(api.login)</div><div> deferred.addCallbacks(handleResult, handleError)</div>
<div><br></div><div> reactor.run()</div><div><br></div><div>This works as expected and defers return of the api.login() call until</div><div>it is complete, instead of blocking. But as I said, it doesn't feel</div>
<div>right. </div><div><br></div><div>Thanks in advance for any help, guidance, feedback, criticism,</div><div>insults, or total solutions.</div><div><br></div><div>jathan.</div>