| 1 | # Copyright (C) 2007 SPARTA, Inc. |
|---|
| 2 | # This software is licensed under the GPLv3 license, included in |
|---|
| 3 | # ./GPLv3-LICENSE.txt in the source distribution |
|---|
| 4 | |
|---|
| 5 | from seer import CIDR |
|---|
| 6 | from seerplatform import execAndRead, pipeIn |
|---|
| 7 | import re |
|---|
| 8 | import sys |
|---|
| 9 | import socket |
|---|
| 10 | import logging |
|---|
| 11 | |
|---|
| 12 | class MyState(object): |
|---|
| 13 | |
|---|
| 14 | def __init__(self): |
|---|
| 15 | self.LoadEID() |
|---|
| 16 | self.LoadControlInfo() |
|---|
| 17 | self.LoadIfConfig() |
|---|
| 18 | self.LoadTopoFile() |
|---|
| 19 | |
|---|
| 20 | |
|---|
| 21 | def LoadEID(self): |
|---|
| 22 | """ Load the nickname file to get the node, experiment and project names """ |
|---|
| 23 | try: |
|---|
| 24 | file = open('/var/emulab/boot/swapper', 'r') |
|---|
| 25 | self.swapper = file.readline().strip() |
|---|
| 26 | file.close() |
|---|
| 27 | |
|---|
| 28 | file = open('/var/emulab/boot/nickname', 'r') |
|---|
| 29 | line = file.readline() |
|---|
| 30 | file.close() |
|---|
| 31 | |
|---|
| 32 | (self.node, self.exp, self.proj) = line.strip().split('.') |
|---|
| 33 | self.eid = self.proj+"/"+self.exp |
|---|
| 34 | self.controlip = socket.gethostbyname(line.strip()) |
|---|
| 35 | except IOError, e: |
|---|
| 36 | logging.error("Can't load node info from /var/emulab/boot/nickname: %s" % (e)) |
|---|
| 37 | |
|---|
| 38 | |
|---|
| 39 | def LoadControlInfo(self): |
|---|
| 40 | """ Load the control IP address and IF name files """ |
|---|
| 41 | myif = open('/var/emulab/boot/controlif', 'r') |
|---|
| 42 | self.controlif = myif.readline().strip() |
|---|
| 43 | myif.close() |
|---|
| 44 | |
|---|
| 45 | |
|---|
| 46 | def LoadIfConfig(self): |
|---|
| 47 | """ Load all of the interface info from emulab/boot/tmcc/ifconfig """ |
|---|
| 48 | self.iplist = {} |
|---|
| 49 | self.iflist = {} |
|---|
| 50 | name = inet = mask = mac = '' |
|---|
| 51 | |
|---|
| 52 | iffile = pipeIn('/usr/local/etc/emulab/tmcc ifconfig') |
|---|
| 53 | |
|---|
| 54 | # Split into lines |
|---|
| 55 | for line in iffile.readlines(): |
|---|
| 56 | # Split into tokens |
|---|
| 57 | for piece in line.split(): |
|---|
| 58 | # It is now key=val |
|---|
| 59 | keyval = piece.split('=') |
|---|
| 60 | if keyval[0] == 'INET': |
|---|
| 61 | inet = keyval[1] |
|---|
| 62 | elif keyval[0] == 'MASK': |
|---|
| 63 | mask = keyval[1] |
|---|
| 64 | elif keyval[0] == 'MAC': |
|---|
| 65 | mac = keyval[1] |
|---|
| 66 | |
|---|
| 67 | if (sys.platform == 'cygwin'): |
|---|
| 68 | name = execAndRead("/usr/seer/bin/ip2pcapif %s" % (inet)).strip() |
|---|
| 69 | else: |
|---|
| 70 | name = execAndRead("/usr/local/etc/emulab/findif %s" % (mac)).strip() |
|---|
| 71 | |
|---|
| 72 | self.iplist[inet] = (name, mac, mask) |
|---|
| 73 | self.iflist[name] = (inet, mac, mask) |
|---|
| 74 | |
|---|
| 75 | iffile.close() |
|---|
| 76 | |
|---|
| 77 | def GetIPList(self): |
|---|
| 78 | """ Return the list of experimental IP addresses for this node """ |
|---|
| 79 | return self.iplist.keys() |
|---|
| 80 | |
|---|
| 81 | def GetIFList(self): |
|---|
| 82 | """ Return the list of experimental interfaces for this node """ |
|---|
| 83 | return self.iflist.keys() |
|---|
| 84 | |
|---|
| 85 | def GetIfInfo(self, ip): |
|---|
| 86 | """ Return the interface info for a given IP address """ |
|---|
| 87 | return self.iplist.get(ip) |
|---|
| 88 | |
|---|
| 89 | |
|---|
| 90 | def LoadTopoFile(self): |
|---|
| 91 | """ |
|---|
| 92 | # nodes: vname,links |
|---|
| 93 | control,link5:10.1.1.3 |
|---|
| 94 | node1,link5:10.1.1.2 |
|---|
| 95 | # lans: vname,mask,cost |
|---|
| 96 | link5,255.255.255.0,1 |
|---|
| 97 | """ |
|---|
| 98 | readtype = 0 |
|---|
| 99 | ips = {} |
|---|
| 100 | nodes = {} |
|---|
| 101 | interfaces = {} |
|---|
| 102 | lanbases = {} |
|---|
| 103 | lans = {} |
|---|
| 104 | |
|---|
| 105 | topomap = open('/var/emulab/boot/topomap', 'r'); |
|---|
| 106 | for line in topomap.readlines(): |
|---|
| 107 | if line.startswith('# nodes'): |
|---|
| 108 | readtype = 1 |
|---|
| 109 | continue |
|---|
| 110 | if line.startswith('# lans'): |
|---|
| 111 | readtype = 2 |
|---|
| 112 | continue |
|---|
| 113 | |
|---|
| 114 | if (readtype == 1): |
|---|
| 115 | details = re.split('[, \n]+', line.strip()) |
|---|
| 116 | node = details.pop(0) |
|---|
| 117 | nodes[node] = {} |
|---|
| 118 | for link in details: |
|---|
| 119 | if ':' not in link: continue |
|---|
| 120 | (linkname, linkip) = link.split(':') |
|---|
| 121 | nodes[node][linkname] = linkip |
|---|
| 122 | ips[linkip] = node |
|---|
| 123 | if linkname not in interfaces: # Is there a nicer way to do this, like automagically |
|---|
| 124 | interfaces[linkname] = {} |
|---|
| 125 | interfaces[linkname][node] = linkip |
|---|
| 126 | lanbases[linkname] = linkip # overwrites |
|---|
| 127 | |
|---|
| 128 | elif (readtype == 2): |
|---|
| 129 | (linkname, netmask, cost) = line.split(',') |
|---|
| 130 | lans[linkname] = CIDR(basestr=lanbases[linkname], maskstr=netmask) |
|---|
| 131 | |
|---|
| 132 | topomap.close() |
|---|
| 133 | |
|---|
| 134 | ## Sanity check the assigned IP addresses and their subnetmasks |
|---|
| 135 | for l in interfaces: |
|---|
| 136 | for node in interfaces[l]: |
|---|
| 137 | # Check to see if all the IPs in this subnet fit given the subnetmask |
|---|
| 138 | c = CIDR(basestr=interfaces[l][node], maskstr=lans[l].maskstr) |
|---|
| 139 | if (c.basestr != lans[l].basestr): |
|---|
| 140 | logging.error("Some of the defined subnets are not valid (%s)." % (l)) |
|---|
| 141 | logging.error("\t%s\n\t%s\n" % (interfaces[l], lans[l])) |
|---|
| 142 | |
|---|
| 143 | self.topoips = ips # ips[ip] = node |
|---|
| 144 | self.nodes = nodes # nodes[node][linklan] = IP |
|---|
| 145 | self.interfaces = interfaces # interfaces[linklan][node] = IP |
|---|
| 146 | self.lans = lans # lans[linklan] = CIDR for subnet |
|---|
| 147 | |
|---|
| 148 | |
|---|
| 149 | def GetNodeForIP(self, ip): |
|---|
| 150 | """ Lookup the node that is linked to this IP address """ |
|---|
| 151 | return self.topoips.get(ip) |
|---|
| 152 | |
|---|
| 153 | def GetControlNameForIP(self, ip): |
|---|
| 154 | """ Return control plane hostname """ |
|---|
| 155 | return ".".join([self.topoips.get(ip), self.exp, self.proj]) |
|---|
| 156 | |
|---|
| 157 | def GetIPForNode(self, node): |
|---|
| 158 | """ To make sure everyone gets the same IP, we revert to DNS lookups """ |
|---|
| 159 | try: |
|---|
| 160 | return socket.gethostbyname(node) |
|---|
| 161 | except Exception, e: |
|---|
| 162 | return None |
|---|
| 163 | |
|---|
| 164 | |
|---|
| 165 | # Small test if running this file directly |
|---|
| 166 | if __name__ == "__main__": |
|---|
| 167 | x = MyState() |
|---|
| 168 | print x.__dict__ |
|---|