cli: Add support for Unix domain sockets
This commit is contained in:
@@ -1475,6 +1475,8 @@ def get_parser():
|
||||
# daemon
|
||||
parser_daemon = subparsers.add_parser('daemon', help="Run Daemon")
|
||||
parser_daemon.add_argument("-d", "--detached", action="store_true", dest="detach", default=False, help="run daemon in detached mode")
|
||||
parser_daemon.add_argument("--rpcsock", dest="rpcsock", default=None, help="what socket type to which to bind RPC daemon", choices=['unix', 'tcp', 'auto'])
|
||||
parser_daemon.add_argument("--rpcsockpath", dest="rpcsockpath", help="where to place RPC file socket")
|
||||
add_network_options(parser_daemon)
|
||||
add_global_options(parser_daemon)
|
||||
# commands
|
||||
|
||||
@@ -61,10 +61,15 @@ _logger = get_logger(__name__)
|
||||
class DaemonNotRunning(Exception):
|
||||
pass
|
||||
|
||||
def get_rpcsock_defaultpath(config: SimpleConfig):
|
||||
return os.path.join(config.path, 'daemon_rpc_socket')
|
||||
|
||||
def get_rpcsock_default_type(osname):
|
||||
return 'tcp'
|
||||
|
||||
def get_lockfile(config: SimpleConfig):
|
||||
return os.path.join(config.path, 'daemon')
|
||||
|
||||
|
||||
def remove_lockfile(lockfile):
|
||||
os.unlink(lockfile)
|
||||
|
||||
@@ -96,7 +101,15 @@ def request(config: SimpleConfig, endpoint, args=(), timeout=60):
|
||||
create_time = None
|
||||
try:
|
||||
with open(lockfile) as f:
|
||||
(host, port), create_time = ast.literal_eval(f.read())
|
||||
socktype, address, create_time = ast.literal_eval(f.read())
|
||||
if socktype == 'unix':
|
||||
path = address
|
||||
(host, port) = "127.0.0.1", 0
|
||||
# We still need a host and port for e.g. HTTP Host header
|
||||
elif socktype == 'tcp':
|
||||
(host, port) = address
|
||||
else:
|
||||
raise Exception(f"corrupt lockfile; socktype={socktype!r}")
|
||||
except Exception:
|
||||
raise DaemonNotRunning()
|
||||
rpc_user, rpc_password = get_rpc_credentials(config)
|
||||
@@ -104,7 +117,13 @@ def request(config: SimpleConfig, endpoint, args=(), timeout=60):
|
||||
auth = aiohttp.BasicAuth(login=rpc_user, password=rpc_password)
|
||||
loop = asyncio.get_event_loop()
|
||||
async def request_coroutine():
|
||||
async with aiohttp.ClientSession(auth=auth) as session:
|
||||
if socktype == 'unix':
|
||||
connector = aiohttp.UnixConnector(path=path)
|
||||
elif socktype == 'tcp':
|
||||
connector = None # This will transform into TCP.
|
||||
else:
|
||||
raise Exception(f"impossible socktype ({socktype!r})")
|
||||
async with aiohttp.ClientSession(auth=auth, connector=connector) as session:
|
||||
c = util.JsonRPCClient(session, server_url)
|
||||
return await c.request(endpoint, *args)
|
||||
try:
|
||||
@@ -225,6 +244,9 @@ class CommandsServer(AuthenticatedServer):
|
||||
self.daemon = daemon
|
||||
self.fd = fd
|
||||
self.config = daemon.config
|
||||
sockettype = self.config.get('rpcsock', 'auto')
|
||||
self.socktype = sockettype if sockettype != 'auto' else get_rpcsock_default_type(os.name)
|
||||
self.sockpath = self.config.get('rpcsockpath', get_rpcsock_defaultpath(self.config))
|
||||
self.host = self.config.get('rpchost', '127.0.0.1')
|
||||
self.port = self.config.get('rpcport', 0)
|
||||
self.app = web.Application()
|
||||
@@ -239,10 +261,21 @@ class CommandsServer(AuthenticatedServer):
|
||||
async def run(self):
|
||||
self.runner = web.AppRunner(self.app)
|
||||
await self.runner.setup()
|
||||
site = web.TCPSite(self.runner, self.host, self.port)
|
||||
if self.socktype == 'unix':
|
||||
site = web.UnixSite(self.runner, self.sockpath)
|
||||
elif self.socktype == 'tcp':
|
||||
site = web.TCPSite(self.runner, self.host, self.port)
|
||||
else:
|
||||
raise Exception(f"unknown socktype '{self.socktype!r}'")
|
||||
await site.start()
|
||||
socket = site._server.sockets[0]
|
||||
os.write(self.fd, bytes(repr((socket.getsockname(), time.time())), 'utf8'))
|
||||
if self.socktype == 'unix':
|
||||
addr = self.sockpath
|
||||
elif self.socktype == 'tcp':
|
||||
addr = socket.getsockname()
|
||||
else:
|
||||
raise Exception(f"impossible socktype ({self.socktype!r})")
|
||||
os.write(self.fd, bytes(repr((self.socktype, addr, time.time())), 'utf8'))
|
||||
os.close(self.fd)
|
||||
|
||||
async def ping(self):
|
||||
|
||||
Reference in New Issue
Block a user