2012-07-30 10 views
10

Ich versuche mit supervisord zu interagieren, und ich möchte mit ihm über einen Unix-Socket sprechen (es ist eine Shared-Hosting-Umgebung).Verwenden Sie Python xmlrpclib mit Unix-Domain-Sockets?

Was ich bisher versucht ist:

import xmlrpclib 
server = xmlrpclib.ServerProxy('unix:///path/to/supervisor.sock/RPC2') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/local/lib/python2.7/xmlrpclib.py", line 1549, in __init__ 
    raise IOError, "unsupported XML-RPC protocol" 
IOError: unsupported XML-RPC protocol 

/path/to/supervisor.sock besteht auf jeden Fall. URIs in der Form 'unix: ///path/to/supervisor.sock/RPC2' werden von supervisord verwendet, wo ich die Idee hatte. Die Dokumente behandeln keine Unix-Sockets: http://docs.python.org/library/xmlrpclib.html.

Ist das möglich? Soll ich eine andere Bibliothek benutzen?

Antwort

13

xmlrpclib erfordert, dass die URL mit http oder https übergeben wird. Um dies zu definieren, müssen Sie einen benutzerdefinierten Transport definieren, der diese URL ignoriert. Hier ist ein Code, den Transport von Vorgesetzten mit:

import supervisor.xmlrpc 
import xmlrpclib 

proxy = xmlrpclib.ServerProxy('http://127.0.0.1', 
           transport=supervisor.xmlrpc.SupervisorTransport(
            None, None, serverurl='unix://'+socketpath)) 

proxy.supervisor.getState() 

Falls das nicht nützlich ist, ist hier eine aktualisierte Version des Codes here gefunden:

class UnixStreamHTTPConnection(httplib.HTTPConnection, object): 
    def __init__(self, *args, **kwargs): 
     self.socketpath = kwargs.pop('socketpath') 
     super(UnixStreamHTTPConnection, self).__init__(*args, **kwargs) 

    def connect(self): 
     self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) 
     self.sock.connect_ex(self.socketpath) 

class UnixStreamTransport(xmlrpclib.Transport, object): 
    def __init__(self, *args, **kwargs): 
     self.socketpath = kwargs.pop('socketpath') 
     super(UnixStreamTransport, self).__init__(*args, **kwargs) 
6

Hier ist ein aktualisierter Beispiel für die Verwendung von xmlrpclib zu Vorgesetzten sprechen :

import httplib 
import socket 
import xmlrpclib 

class UnixStreamHTTPConnection(httplib.HTTPConnection): 
    def connect(self): 
     self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) 
     self.sock.connect(self.host) 

class UnixStreamTransport(xmlrpclib.Transport, object): 
    def __init__(self, socket_path): 
     self.socket_path = socket_path 
     super(UnixStreamTransport, self).__init__() 

    def make_connection(self, host): 
     return UnixStreamHTTPConnection(self.socket_path) 


server = xmlrpclib.Server('http://arg_unused', transport=UnixStreamTransport("/var/run/supervisor.sock")) 
print(server.supervisor.getState()) 

Wie bereits erwähnt, müssen wir eine Dummy-uRL mit http: // angeben oder https: // und dann einen benutzerdefinierten Transport zu handhaben die angeben Domain-Socket

2

die Antworten mischen oben, hier ist was für mich ...

import httplib 
import socket 
import xmlrpclib 

class UnixStreamHTTPConnection(httplib.HTTPConnection, object): 
    def __init__(self, *args, **kwargs): 
     self.socketpath = kwargs.pop('socketpath') 
     super(UnixStreamHTTPConnection, self).__init__(*args, **kwargs) 

    def connect(self): 
     self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) 
     self.sock.connect(self.socketpath) 

class UnixStreamTransport(xmlrpclib.Transport, object): 
    def __init__(self, *args, **kwargs): 
     self.socketpath = kwargs.pop('socketpath') 
     super(UnixStreamTransport, self).__init__(*args, **kwargs) 

    def make_connection(self, host): 
     return UnixStreamHTTPConnection(host, socketpath=self.socketpath) 

server = xmlrpclib.ServerProxy('http://arg_unused', transport=UnixStreamTransport(socketpath="path/to/supervisor.sock")) 
print server.supervisor.getState()