chiark / gitweb /
Use the new `mLib' annotations on varargs functions.
[tripe] / svc / conntrack.in
index b80f92edc0a4e88cc2ca8c99fad12bac14f6614d..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.
 
@@ -214,9 +238,10 @@ def localaddr(peer):
 
 _kick = T.Queue()
 def kickpeers():
-  lastip = {}
   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.
@@ -236,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
@@ -250,32 +279,57 @@ 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'
-          want = t
+          select.append('%s=%s' % (g, t))
+          if t == 'down' or t.startswith('down/'):
+            want = None
+          else:
+            want = t
           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':
-          changes.append(lambda p=p: SM.kill(p))
+          def _(p = p):
+            try:
+              SM.kill(p)
+            except T.TripeError, exc:
+              if exc.args[0] == 'unknown-peer':
+                ## Inherently racy; don't worry about this.
+                pass
+              else:
+                raise
+          if T._debug: print '#   peer %s: bring down' % p
+          changes.append(_)
 
       ## Start the right one if necessary.
-      if want is not None and (not found or ip != lastip.get(g, None)):
-        changes.append(lambda: T._simple(SM.svcsubmit('connect', 'active',
-                                                      want)))
-      lastip[g] = ip
+      if want is not None and not found:
+        def _(want = want):
+          try:
+            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):
@@ -532,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__':