Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use Python xmlrpclib with unix domain sockets?

I'm trying to interact with supervisord, and I'd like to talk with it over a unix socket (it's a shared hosting environment).

What I've tried so far is:

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 definitely exists. URIs of the form 'unix:///path/to/supervisor.sock/RPC2' are used by supervisord, which is where I got the idea. The docs don't discuss unix sockets: http://docs.python.org/library/xmlrpclib.html.

Is this possible? Should I use a different library?

like image 228
Marcin Avatar asked Jul 30 '12 20:07

Marcin


People also ask

Does Windows support UNIX domain sockets?

Support for the unix socket has existed both in BSD and Linux for the longest time, but, not on Windows.

How do I use a domain socket in UNIX?

To create a UNIX domain socket, use the socket function and specify AF_UNIX as the domain for the socket. The z/TPF system supports a maximum number of 16,383 active UNIX domain sockets at any time. After a UNIX domain socket is created, you must bind the socket to a unique file path by using the bind function.

Are UNIX domain sockets reliable?

SOCK_DGRAM (compare to UDP) – for a datagram-oriented socket that preserves message boundaries (as on most UNIX implementations, UNIX domain datagram sockets are always reliable and don't reorder datagrams)

Are UNIX domain sockets faster?

Unix domain sockets are often twice as fast as a TCP socket when both peers are on the same host. The Unix domain protocols are not an actual protocol suite, but a way of performing client/server communication on a single host using the same API that is used for clients and servers on different hosts.


2 Answers

My version for python3, prepared from versions above.

from http.client import HTTPConnection
import socket
from xmlrpc import client

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

class UnixStreamTransport(client.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)

proxy = client.ServerProxy('http://localhost', transport=UnixStreamTransport("/var/run/supervisor.sock"))

print(proxy.supervisor.getState())
like image 86
Pavel Cisar Avatar answered Sep 24 '22 18:09

Pavel Cisar


xmlrpclib requires that the url passed start with http or https. The way around this is to define a custom transport which ignores that url. Here's some code using the transport from supervisor:

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()

In case that's not useful, here's an updated version of the code found here:

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)
like image 40
Marcin Avatar answered Sep 25 '22 18:09

Marcin