Changeset 8212638


Ignore:
Timestamp:
Sep 19, 2012 4:03:06 PM (12 years ago)
Author:
Ted Faber <faber@…>
Branches:
master
Children:
319fb0a
Parents:
b9ec635
Message:

Recognize and respect user allocated IP addresses

File:
1 edited

Legend:

Unmodified
Added
Removed
  • fedd/federation/experiment_control.py

    rb9ec635 r8212638  
    13141314    def allocate_ips_to_topo(self, top):
    13151315        """
    1316         Add an ip4_address attribute to all the hosts in the topology, based on
    1317         the shared substrates on which they sit.  An /etc/hosts file is also
    1318         created and returned as a list of hostfiles entries.  We also return
    1319         the allocator, because we may need to allocate IPs to portals
     1316        Add an ip4_address attribute to all the hosts in the topology that have
     1317        not already been assigned one by the user, based on the shared
     1318        substrates on which they sit.  An /etc/hosts file is also created and
     1319        returned as a list of hostfiles entries.  We also return the allocator,
     1320        because we may need to allocate IPs to portals
    13201321        (specifically DRAGON portals).
    13211322        """
     
    13271328        hosts = [ ]
    13281329
     1330        assigned = { }
     1331        assigned_subs = set()
     1332        # Look for IP networks that were already assigned to the experiment by
     1333        # the user.  We assume that users are smart in making that assignment,
     1334        # but we check them later.
     1335        for e in top.elements:
     1336            if not isinstance(e, topdl.Computer): continue
     1337            for inf in e.interface:
     1338                a = inf.get_attribute('ip4_address')
     1339                if not a: continue
     1340                for s in inf.substrate:
     1341                    assigned_subs.add(s)
     1342                a = ip_addr(a)
     1343                n = ip_addr(inf.get_attribute('ip4_netmask'))
     1344
     1345                sz = 0x100000000 - long(n)
     1346                net = (long(a) & long(n)) & 0xffffffff
     1347                if net in assigned:
     1348                    if sz > assigned[net]: assigned[net] = sz
     1349                assigned[net] = sz
     1350
     1351        # Walk all substrates, smallest to largest, assigning IP addresses to
     1352        # the unassigned and checking the assigned.  Build an /etc/hosts file
     1353        # as well.
    13291354        for idx, s in enumerate(subs):
    1330             net_size = len(s.interfaces)+2
    1331 
    1332             a = ips.allocate(net_size)
    1333             if a :
    1334                 base, num = a
    1335                 if num < net_size:
    1336                     raise service_error(service_error.internal,
    1337                             "Allocator returned wrong number of IPs??")
     1355            if s.name not in assigned_subs:
     1356                net_size = len(s.interfaces)+2
     1357
     1358                # Get an ip allocation for this substrate.  Make sure the
     1359                # allocation does not collide with any user allocations.
     1360                ok = False
     1361                while not ok:
     1362                    a = ips.allocate(net_size)
     1363                    if not a:
     1364                        raise service_error(service_error.req,
     1365                                "Cannot allocate IP addresses")
     1366                    base, num = a
     1367                    if num < net_size:
     1368                        raise service_error(service_error.internal,
     1369                                "Allocator returned wrong number of IPs??")
     1370                    # Check for overlap.  An assigned network could contain an
     1371                    # endpoint of the new allocation or the new allocation
     1372                    # could contain an endpoint of an assigned network.
     1373                    # NB the else is attached to the for - if the loop is not
     1374                    # exited by a break, ok = True.
     1375                    for n, sz in assigned.items():
     1376                        if base >= n and base < n + sz:
     1377                            ok = False
     1378                            break
     1379                        if base + num > n and base + num  < n + sz:
     1380                            ok = False
     1381                            break
     1382                        if n >= base and n < base + num:
     1383                            ok = False
     1384                            break
     1385                        if n+sz > base and n+sz < base + num:
     1386                            ok = False
     1387                            break
     1388                    else:
     1389                        ok = True
     1390                           
     1391                mask = ips.min_alloc
     1392                while mask < net_size:
     1393                    mask *= 2
     1394
     1395                netmask = ((2**32-1) ^ (mask-1))
    13381396            else:
    1339                 raise service_error(service_error.req,
    1340                         "Cannot allocate IP addresses")
    1341             mask = ips.min_alloc
    1342             while mask < net_size:
    1343                 mask *= 2
    1344 
    1345             netmask = ((2**32-1) ^ (mask-1))
    1346 
     1397                base = 0
     1398
     1399            # Add the attributes and build hosts
    13471400            base += 1
    13481401            for i in s.interfaces:
    1349                 i.attribute.append(
    1350                         topdl.Attribute('ip4_address',
    1351                             "%s" % ip_addr(base)))
    1352                 i.attribute.append(
    1353                         topdl.Attribute('ip4_netmask',
    1354                             "%s" % ip_addr(int(netmask))))
    1355 
     1402                # Add address and masks to interfaces on unassigned substrates
     1403                if s.name not in assigned_subs:
     1404                    i.attribute.append(
     1405                            topdl.Attribute('ip4_address',
     1406                                "%s" % ip_addr(base)))
     1407                    i.attribute.append(
     1408                            topdl.Attribute('ip4_netmask',
     1409                                "%s" % ip_addr(int(netmask))))
     1410
     1411                # Make /etc/hosts entries
     1412                addr = i.get_attribute('ip4_address')
     1413                if addr is None:
     1414                    raise service_error(service_error.req,
     1415                            "Partially assigned substrate %s" %s.name)
    13561416                hname = i.element.name
    1357                 if ifs.has_key(hname):
     1417                if hname in ifs:
    13581418                    hosts.append("%s\t%s-%s %s-%d" % \
    1359                             (ip_addr(base), hname, s.name, hname,
    1360                                 ifs[hname]))
     1419                            (addr, hname, s.name, hname, ifs[hname]))
    13611420                else:
     1421                    # First IP allocated it the default ip according to hosts,
     1422                    # so the extra alias is here.
    13621423                    ifs[hname] = 0
    13631424                    hosts.append("%s\t%s-%s %s-%d %s" % \
    1364                             (ip_addr(base), hname, s.name, hname,
    1365                                 ifs[hname], hname))
     1425                            (addr, hname, s.name, hname, ifs[hname], hname))
    13661426
    13671427                ifs[hname] += 1
Note: See TracChangeset for help on using the changeset viewer.