: ${tripectl=$bindir/tripectl}
export TRIPEDIR TRIPESOCK
-case "$#,$1,$2" in
-
- 2,-c,*:*)
- ## Proxy through to another server.
- server=${2%:*} user=${2##*:}
- exec ssh "$server" "$user"
+## Make sure we're being called properly, and figure out the peer identity.
+case "$#,$1" in
+ 2,-c) ;;
+ *)
+ echo >&2 "usage: $0 -c '[SERVER:]PEER [hello|goodbye]'"
+ exit 1
;;
+esac
- 2,-c,*)
- ## Connect to the local tripe server.
- exec $tripectl SVCSUBMIT connect passive "$2"
- ;;
+## SSH has smushed all of our arguments together, so let's split them apart
+## again.
+set -- $2
+
+## Examine the peer identifier and work out how to proceed.
+case "$#,$1" in
+ 0,*) echo >&2 "$0: missing peer identifier"; exit 1 ;;
+ *:*) mode=proxy server=${1%:*} user=${1##*:} ;;
+ *) mode=local user=$1 ;;
+esac
+shift
+## If there's no action then check to see whether SSH has hidden one
+## somewhere. Make sure the command looks sensible.
+case "$#" in 0) set -- $SSH_ORIGINAL_COMMAND ;; esac
+case "$#,$1" in
+ 0, | 1,hello) act=hello ;;
+ 1,goodbye) act=goodbye ;;
+ *) echo >&2 "$0: unknown action spec \`$*'"; exit 1 ;;
+esac
+
+## Now actually do something.
+case "$mode,$act" in
+ proxy,*)
+ exec ssh "$server" "$user" "$act"
+ ;;
+ local,hello)
+ exec $tripectl SVCSUBMIT connect passive "$user"
+ ;;
+ local,goodbye)
+ peer=$($tripectl SVCSUBMIT connect userpeer "$user")
+ exec $tripectl KILL "$peer"
+ ;;
*)
- ## Anything else is an error.
- echo >&2 "usage: $0 -c [SERVER:]PEER"
+ echo >&2 "$0: unknown mode/action $mode/$act"
exit 1
;;
-
esac
+tripe (1.0.0pre12) experimental; urgency=low
+
+ * tripe-peer-services: Add machinery for notifying a peer that we no
+ longer require its services.
+
+ -- Mark Wooding <mdw@distorted.org.uk> Sat, 05 Jan 2013 07:50:33 +0000
+
tripe (1.0.0pre11.1) experimental; urgency=low
* tripe: Fix segfault from PEERINFO command.
;; connect: shell command to use to wake up the remote peer and establish the
;; connection.
-connect = ssh -q $(ssh-user)@$[$(host)]
+connect = ssh -q $(ssh-user)@$[$(host)] hello
+
+;; disconnect: shell command to use to shut the remote peer down.
+disconnect = ssh -q $(ssh-user)@$[$(host)] goodbye
;; keepalive: how often to send NOP packets to keep the connection alive, at
;; least in the minds of intermediate stateful firewalls and NAT routers.
Don't initiate immediate key exchange. Used by
.BR connect (8).
.TP
+.B disconnect
+Shell command for closing down connection to this peer. Used by
+.BR watch (8).
+.TP
.B every
Interval for checking that the peer is still alive and well. Used by
.BR watch (8).
seconds are assumed.
.\"-opts
.RE
+.SP
+.BI "userpeer " user
+Output a single
+.B INFO
+line identifying the peer corresponding to the
+.I user
+name.
.
.\"--------------------------------------------------------------------------
.SH "ERROR MESSAGES"
.SP
.BI "unknown-user " user
(For
-.BR passive .)
+.B passive
+and
+.BR userinfo .)
There is no record of
.I user
in the database.
for i in items:
T.svcinfo('%s=%s' % (i, peer.get(i)))
+def cmd_userpeer(user):
+ """
+ userpeer USER: Report the peer name for the named user.
+ """
+ try:
+ peer = CDB.init(opts.cdb)['U' + user]
+ except KeyError:
+ raise T.TripeJobError('unknown-user', user)
+ T.svcinfo(peer)
+
## Dictionary mapping challenges to waiting passive-connection coroutines.
chalmap = {}
'passive': (1, None, '[OPTIONS] USER', cmd_passive),
'active': (1, 1, 'PEER', cmd_active),
'info': (1, 1, 'PEER', cmd_info),
- 'list': (0, 0, '', cmd_list)
+ 'list': (0, 0, '', cmd_list),
+ 'userpeer': (1, 1, 'USER', cmd_userpeer)
})]
if __name__ == '__main__':
where
.I our-name
is the remote peer's name for this host.
+.PP
+Similarly, if the database record has a
+.B disconnect
+entry, then
+.B watch
+will use this to give the peer explicit notification that its services
+are no longer needed. The value f the
+.B disconnect
+key is invoked as a Bourne shell command. This ought to result in a
+.B KILL
+command being issued to the peer's server.
.SS "Operation"
On startup,
.B watch
A child spawned in order to establish a dynamic connection with
.IR peer .
.SP
+.BI "disconnect " peer
+A child spawned in order to shut down a dynamic connection with
+.IR peer .
+.SP
.BI "ifdown " peer
A child spawned to deconfigure the network interface for
.IR peer .
q.get()
potwatch('connect', peer, q)
+def disconnect(peer, disconn = None):
+ """
+ Start the job of disconnecting from a passive PEER.
+
+ The DISCONN string is a shell command which will disconnect from the peer.
+ """
+ if disconn is None:
+ try:
+ conn = peerinfo(peer)['disconnect']
+ except KeyError:
+ return
+ q = T.Queue()
+ cmd = Command(['disconnect', peer], q, 'disconnect',
+ ['/bin/sh', '-c', disconn], None)
+ potwatch('disconnect', peer, q)
+
_pingseq = 0
class PingPeer (object):
"""
pinger.kill(peer)
except KeyError:
pass
+ if 'disconnect' in info:
+ T.Coroutine(disconnect, name = 'disconnect %s' % peer) \
+ .switch(peer, info['disconnect'])
if 'ifdown' in info:
T.Coroutine(ifupdown, name = 'ifdown %s' % peer) \
.switch('ifdown', peer, info)