Newer
Older
ctun.close()
stun.close()
return rcode
#
# Port forwarding:
#
@listed
def forward(self, label, login, port, destination='127.0.0.1'):
""" Forward a TCP port to the client.
:param label: label of the tunnel created by the client (cli side)
:param login: login of the remote client on which establish the tunnel
:param port: port on which establish the tunnel on destination
:param destination: tunnel destination (from the remote client side)
self.client.check('forward', query='id=%s' % login)
# Create the tunnel to the node:
try:
host_client = self.server.get_client(login)
except KeyError:
raise KeyError('Specified client is not connected')
s2n_tun = host_client.forward(port, destination)
# Create tunnel to the CLI
self.client.register_tunnel('forward', host_client, s2n_tun)
#
# Debug:
#
@listed
def dbstats(self):
""" Get statistics about tql database.
"""
return self.server.db.stats()
def forward_call(self, login, func, *args, **kwargs):
""" Forward a call to a connected client and return result.
:param login: login of the connected client
:param func: function to execute on the client
:param \*args, \*\*kwargs: arguments of the call
"""
self.client.check('forward_call')
client = self.server.get_client(login)
return client.conn.call(func, *args, **kwargs)
class CliClient(Client):
""" A cli client connected to the cc-server.
"""
ROLE = 'cli'
RPC_HANDLER = CliHandler
KILL_ALREADY_CONNECTED = True
def __init__(self, *args, **kwargs):
super(CliClient, self).__init__(*args, **kwargs)
self._tunnels = {} # Running tunnels for this client (as client)
def spawn_job(self, job_class, **kwargs):
self._server.jobs.spawn(job_class, self.login, **kwargs)
def register_tunnel(self, ttype, client, tun, label=None):
""" Create and register a tunnel for this client.
:param ttype: type of tunnel
:param client: client where the tunnel go
:param tun: the tunnel of this client
:param label: label of the tunnel to create
"""
def cb_on_close(tun):
# Call the default callback:
tun.cb_default_on_close(tun)
# Delete the tunnel from the current running tunnels:
self.unregister_tunnel(tun.label)
ctun = self.conn.create_tunnel(label=label, endpoint=tun.socket,
on_close=cb_on_close)
self._tunnels[ctun.label] = (ttype, client, ctun, tun)
return ctun
def get_tunnel(self, label):
""" Get the tunnel binded to the provided label.
:return: a tuple (type, remote_client, tunnel, remote_client_tunnel)
where: **type** is a string provided on tunnel creation,
**remote_client** the client object of the remote client on which
the tunnel is established, **tunnel** the cli-to-server tunnel
object from the sjRpc, **remote_client_tunnel** the
server-to-remote-client tunnel object from the sjRpc.
"""
return self._tunnels[label]
def unregister_tunnel(self, label):
try:
del self._tunnels[label]
except KeyError:
pass
Client.register_client_class(CliClient)