def __read_private_ips(self, filename): router_private_address = defaultdict(dict) ip_to_bd = defaultdict(list) try: with open(filename, 'r') as f: private_address_binding = json.load(f) for subnets in private_address_binding.itervalues(): # Log router id in broadcast domain sub = subnets.keys() for rid, ip in subnets.iteritems(): # Enable single private address as string if not is_container(ip): ip = [ip] # Log private addresses adjacencies other = sub[:] other.remove(rid) for s in other: router_private_address[rid][s] = ip for i in ip: # Register the broadcast domain for each ip ip_to_bd[i] = other except ValueError as e: log.error('Incorrect private IP addresses binding file') log.error(str(e)) ip_to_bd.clear() router_private_address.clear() except IOError as e: log.warning('Cannot read private address file') ip_to_bd.clear() router_private_address.clear() return router_private_address, ip_to_bd
def DFS(generator, consumer, generate_from=None, *elems): """Perform a Depth First Search (DFS). :param generator: The function that will generate the next set of element to examinate from the current one :param consumer: The function that will consume one element. If it returns a single iterable, feed them to the generator If it returns a 2-tuple (x, y), feed x to the generator and yield y :param generate_from: A starting element to feed to the generator :param elems: Elements to add in the original set to visit""" visited = set() to_visit = set(elems) if generate_from: to_visit |= set(generator(generate_from)) while to_visit: n = to_visit.pop() if n in visited: continue visited.add(n) ret = consumer(n) try: remains, to_yield = ret if to_yield: yield to_yield except TypeError: remains = ret if remains: if not is_container(remains): remains = (remains,) to_visit |= set(*map(generator, remains))
def add_local_route(self, router, prefix, targets, **kw): """Add a fake local route available for specified targets""" if not is_container(targets): targets = [targets] self.add_fake_route(router, prefix, target=targets, **kw)
def network_for_domains(net, domains, scale_factor=1, max_prefixlen=sys.maxint): """"Return [ ( subnet, [ intf* ] )* ] Assign a network prefix to every broadcast domain :param net: the original network to split, if this is a list, modifies it to contain the list of prefixes still free :param domains: the list of broadcast domains :param scale_factor: the number of ip to assign per interface :param max_prefixlen: The maximal length of the prefix allocated for each broadcast domain""" domains.sort(key=len, reverse=True) # We want to support allocation across multiple network prefixes # ip_network(ip_network(x)) is safe -- tests/test_pyaddress.py if not is_container(net): net = [ip_network(net)] else: for i, n in enumerate(net): net[i] = ip_network(n) networks = net # Hopefully we only allocate across prefixes in the same IP version... net_space = networks[0].max_prefixlen """We keep the networks sorted as x < y so that the bigger domains take the smallest network before subdividing The assumption is that if the domains range from the biggest to the smallest, and if the networks are sorted from the smallest to the biggest, the biggest domains will take the first network that is able to contain it, and split it in several subnets until it is restricted to its prefix. The next domain then is necessarily of the same size (reuses on of the split networks) or smaller: use and earlier network or split a bigger one. """ # Need to setup invariant networks.sort(cmp=cmp_prefixlen) for d in domains: if not networks: log.error("No subnet left in the prefix space for all" "broadcast domains") sys.exit(1) intf_count = len(d) * scale_factor plen = min(max_prefixlen, net_space - math.ceil(math.log(2 + intf_count, 2))) if plen < networks[-1].prefixlen: raise ValueError('Could not find a subnet big enough for a ' 'broadcast domain, aborting!') log.debug('Allocating prefix %s in network %s for interfaces %s', plen, net, d) # Try to find a suitable subnet in the list for i, net in enumerate(networks): nets = [] # if the subnet is too big for the prefix, expand it while plen > net.prefixlen: # Get list of subnets and append to list of previous # subnets as it is bigger wrt. prefixlen nets.extend(net.subnets(prefixlen_diff=1)) net = nets.pop(-1) # Check if we have an appropriately-sized subnet if plen == net.prefixlen: # Remove and return the expanded/used network yield (net, d) del networks[i] # Insert the creadted subnets if any networks.extend(nets) # Sort the array again networks.sort(cmp=cmp_prefixlen) break