The most interesting thing is probably the `groups' slot, which stores a
list of pairs (NAME, PATTERNS); the NAME is a string, and the PATTERNS a
- list of (TAG, PEER, NET) triples. The implication is that there should be
+ list of (TAG, PEER, NETS) triples. The implication is that there should be
precisely one peer from the set, and that it should be named TAG, where
- (TAG, PEER, NET) is the first triple such that the host's primary IP
+ (TAG, PEER, NETS) is the first triple such that the host's primary IP
address (if PEER is None -- or the IP address it would use for
- communicating with PEER) is within the NET.
+ communicating with PEER) is within one of the networks defined by NETS.
"""
def __init__(me, file):
(spec[i], e))
i += 1
- ## Parse the local network.
- if len(spec) != i + 1:
- raise ConfigError(me._file, lno, 'no network defined')
- try:
- net = parse_net(spec[i])
- except Exception, e:
- raise ConfigError(me._file, lno,
- "invalid IP network `%s': %s" %
- (spec[i], e))
+ ## Parse the list of local networks.
+ nets = []
+ while i < len(spec):
+ try:
+ net = parse_net(spec[i])
+ except Exception, e:
+ raise ConfigError(me._file, lno,
+ "invalid IP network `%s': %s" %
+ (spec[i], e))
+ else:
+ nets.append(net)
+ i += 1
+ if not nets:
+ raise ConfigError(me._file, lno, 'no networks defined')
## Add this entry to the list.
- grplist.append((name, peer, net))
+ grplist.append((name, peer, nets))
## Fill in the default test address if necessary.
if testaddr is None: testaddr = TESTADDR
def cmd_showgroup(g):
try: pats = CF.groups[g]
except KeyError: raise T.TripeJobError('unknown-group', g)
- for t, p, n in pats:
+ for t, p, nn in pats:
T.svcinfo('peer', t,
'target', p and str(p) or '(default)',
- 'net', str(n))
+ 'net', ' '.join(map(str, nn)))
###--------------------------------------------------------------------------
### Responding to a network up/down event.
if T._debug: print '# check group %s' % g
## Find out which peer in the group ought to be active.
- ip = None
statemap = {}
want = None
- for t, p, n in pp:
- if p is None or not upness:
- ipq = addr
- else:
- ipq = localaddr(p)
+ matchp = False
+ for t, p, nn in pp:
+ if p is None or not upness: ip = addr
+ else: ip = localaddr(p)
if T._debug:
- info = 'peer=%s; target=%s; net=%s; local=%s' % (
- t, p or '(default)', n, straddr(ipq))
- if upness and ip is None and \
- ipq is not None and ipq.withinp(n):
+ info = 'peer = %s; target = %s; nets = %s; local = %s' % (
+ t, p or '(default)', ', '.join(map(str, nn)), straddr(ip))
+ if upness and not matchp and \
+ ip is not None and any(ip.withinp(n) for n in nn):
if T._debug: print '# %s: SELECTED' % info
statemap[t] = 'up'
select.append('%s=%s' % (g, t))
- if t == 'down' or t.startswith('down/'):
- want = None
- else:
- want = t
- ip = ipq
+ if t == 'down' or t.startswith('down/'): want = None
+ else: want = t
+ matchp = True
else:
statemap[t] = 'down'
if T._debug: print '# %s: skipped' % info