chiark / gitweb /
svc/conntrack{,.8}.in: Better diagnostics.
authorMark Wooding <mdw@distorted.org.uk>
Sat, 15 Dec 2012 19:16:22 +0000 (19:16 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Sat, 15 Dec 2012 19:16:22 +0000 (19:16 +0000)
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.

svc/conntrack.8.in
svc/conntrack.in

index e74713d1e0cdfbfc3af5964f7db31e7935e68341..5dc6bff866652a44294542128372235dfd6fb4aa 100644 (file)
@@ -208,10 +208,12 @@ A connection has been lost.
 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
-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
index 78141e6fe79bd2dd20b5426b0f44cf82c7a380fc..c86a7d8211e1b442cefec0f70ad945aa2b3258a6 100644 (file)
@@ -140,6 +140,7 @@ class Config (object):
     ## 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
@@ -193,6 +194,29 @@ class Config (object):
 ### 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.
 
@@ -216,6 +240,8 @@ _kick = T.Queue()
 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.
@@ -235,10 +261,14 @@ def kickpeers():
         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:
+      if T._debug: print '#   check group %s' % g
 
       ## Find out which peer in the group ought to be active.
       ip = None
@@ -249,9 +279,14 @@ def kickpeers():
           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 T._debug: print '#     %s: SELECTED' % info
           map[t] = 'up'
+          select.append('%s=%s' % (g, t))
           if t == 'down' or t.startswith('down/'):
             want = None
           else:
@@ -259,13 +294,16 @@ def kickpeers():
           ip = ipq
         else:
           map[t] = 'down'
+          if T._debug: print '#     %s: skipped' % info
 
       ## 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
+          if T._debug: print '#   peer %s: already up' % p
         elif what == 'down':
           def _(p = p):
             try:
@@ -276,6 +314,7 @@ def kickpeers():
                 pass
               else:
                 raise
+          if T._debug: print '#   peer %s: bring down' % p
           changes.append(_)
 
       ## Start the right one if necessary.
@@ -285,11 +324,12 @@ def kickpeers():
             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:
-      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):
@@ -546,7 +586,10 @@ def cmd_updown(upness):
   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__':