Add some debugging output, and improve the notifications. I recently
had a problem which I thought might have been conntrack misbehaving, but
I couldn't tell. It turns out that conntrack was innocent, but this
will help in future cases.
The service's internal state machine is confused.
.RE
.SP
The service's internal state machine is confused.
.RE
.SP
-.BI "USER conntrack " up \fR| down " " reason\fR...
+.BI "USER conntrack " up \fR| down " " group = peer\fR... " " reason\fR...
The network connection has apparently gone up or down, and
.B conntrack
The network connection has apparently gone up or down, and
.B conntrack
-is about to kill and/or connect peers accordingly. The
+is about to kill and/or connect peers accordingly: for each group, the
+selected peer is listed; if a group is not listed, then either the group
+is to be brought down, or no matching peer was found. The
.I reason
is one of the following.
.RS
.I reason
is one of the following.
.RS
## so turn them all off.
cp = RawConfigParser()
cp.read(me._file)
## so turn them all off.
cp = RawConfigParser()
cp.read(me._file)
+ if T._debug: print '# reread config'
## Save the test address. Make sure it's vaguely sensible. The default
## is probably good for most cases, in fact, since that address isn't
## Save the test address. Make sure it's vaguely sensible. The default
## is probably good for most cases, in fact, since that address isn't
### This will be a configuration file.
CF = None
### This will be a configuration file.
CF = None
+def straddr(a): return S.inet_ntoa(pack('>L', a))
+def strmask(m):
+ for i in xrange(33):
+ if m == 0xffffffff ^ ((1 << (32 - i)) - 1): return i
+ return straddr(m)
+
+def cmd_showconfig():
+ T.svcinfo('test-addr=%s' % CF.testaddr)
+def cmd_showgroups():
+ for sec, pats in CF.groups:
+ T.svcinfo(sec)
+def cmd_showgroup(g):
+ for s, p in CF.groups:
+ if s == g:
+ pats = p
+ break
+ else:
+ raise T.TripeJobError, 'unknown-group', g
+ for t, p, a, m in pats:
+ T.svcinfo('peer', t,
+ 'target', p or '(default)',
+ 'net', '%s/%s' % (straddr(a), strmask(m)))
+
###--------------------------------------------------------------------------
### Responding to a network up/down event.
###--------------------------------------------------------------------------
### Responding to a network up/down event.
def kickpeers():
while True:
upness, reason = _kick.get()
def kickpeers():
while True:
upness, reason = _kick.get()
+ if T._debug: print '# kickpeers %s: %s' % (upness, reason)
+ select = []
## Make sure the configuration file is up-to-date. Don't worry if we
## can't do anything useful.
## Make sure the configuration file is up-to-date. Don't worry if we
## can't do anything useful.
upness = False
else:
addr = None
upness = False
else:
addr = None
+ if not T._debug: pass
+ elif addr: print '# local address = %s' % straddr(addr)
+ else: print '# offline'
## Now decide what to do.
changes = []
for g, pp in CF.groups:
## Now decide what to do.
changes = []
for g, pp in CF.groups:
+ if T._debug: print '# check group %s' % g
## Find out which peer in the group ought to be active.
ip = None
## Find out which peer in the group ought to be active.
ip = None
ipq = addr
else:
ipq = localaddr(p)
ipq = addr
else:
ipq = localaddr(p)
+ if T._debug:
+ info = 'peer=%s; target=%s; net=%s/%s; local=%s' % (
+ t, p or '(default)', straddr(a), strmask(m), straddr(ipq))
if upness and ip is None and \
ipq is not None and (ipq & m) == a:
if upness and ip is None and \
ipq is not None and (ipq & m) == a:
+ if T._debug: print '# %s: SELECTED' % info
+ select.append('%s=%s' % (g, t))
if t == 'down' or t.startswith('down/'):
want = None
else:
if t == 'down' or t.startswith('down/'):
want = None
else:
ip = ipq
else:
map[t] = 'down'
ip = ipq
else:
map[t] = 'down'
+ if T._debug: print '# %s: skipped' % info
## Shut down the wrong ones.
found = False
## Shut down the wrong ones.
found = False
+ if T._debug: print '# peer-map = %r' % map
for p in peers:
what = map.get(p, 'leave')
if what == 'up':
found = True
for p in peers:
what = map.get(p, 'leave')
if what == 'up':
found = True
+ if T._debug: print '# peer %s: already up' % p
elif what == 'down':
def _(p = p):
try:
elif what == 'down':
def _(p = p):
try:
+ if T._debug: print '# peer %s: bring down' % p
changes.append(_)
## Start the right one if necessary.
changes.append(_)
## Start the right one if necessary.
SM.svcsubmit('connect', 'active', want)
except T.TripeError, exc:
SM.warn('conntrack', 'connect-failed', want, *exc.args)
SM.svcsubmit('connect', 'active', want)
except T.TripeError, exc:
SM.warn('conntrack', 'connect-failed', want, *exc.args)
+ if T._debug: print '# peer %s: bring up' % want
changes.append(_)
## Commit the changes.
if changes:
changes.append(_)
## Commit the changes.
if changes:
- SM.notify('conntrack', upness and 'up' or 'down', *reason)
+ SM.notify('conntrack', upness and 'up' or 'down', *select + reason)
for c in changes: c()
def netupdown(upness, reason):
for c in changes: c()
def netupdown(upness, reason):
return lambda *args: T.defer(netupdown, upness, ['manual'] + list(args))
service_info = [('conntrack', VERSION, {
'up': (0, None, '', cmd_updown(True)),
return lambda *args: T.defer(netupdown, upness, ['manual'] + list(args))
service_info = [('conntrack', VERSION, {
'up': (0, None, '', cmd_updown(True)),
- 'down': (0, None, '', cmd_updown(False))
+ 'down': (0, None, '', cmd_updown(False)),
+ 'show-config': (0, 0, '', cmd_showconfig),
+ 'show-groups': (0, 0, '', cmd_showgroups),
+ 'show-group': (1, 1, 'GROUP', cmd_showgroup)
})]
if __name__ == '__main__':
})]
if __name__ == '__main__':