324d09fa0ff5bda7c187ec04163ff4548a59a852
[nodemanager-topo.git] / create-topo-attributes.py
1 # $Id$
2 # $URL$
3
4 """
5 Scan the VINI Central database and create topology "rspec" attributes for
6 slices that have an EGRE key.  This script to be run from a cron job.
7 """
8
9 import string
10 import socket
11
12 """
13 Links in the physical topology, gleaned from looking at the Internet2
14 and NLR topology maps.  Link (a, b) connects sites with IDs a and b.
15 """
16 links = [(2, 12),  # I2 Princeton - New York 
17          (4, 5),   # NLR Chicago - Houston
18          (4, 6),   # NLR Chicago - Atlanta
19          (4, 7),   # NLR Chicago - Seattle
20          (4, 9),   # NLR Chicago - New York
21          (4, 10),  # NLR Chicago - Wash DC
22          (5, 6),   # NLR Houston - Atlanta
23          (5, 8),   # NLR Houston - Los Angeles
24          (6, 10),  # NLR Atlanta - Wash DC
25          (7, 8),   # NLR Seattle - Los Angeles
26          (9, 10),  # NLR New York - Wash DC
27          (11, 13), # I2 Chicago - Wash DC
28          (11, 15), # I2 Chicago - Atlanta
29          (11, 16), # I2 Chicago - CESNET
30          (11, 17), # I2 Chicago - Kansas City
31          (12, 13), # I2 New York - Wash DC
32          (13, 15), # I2 Wash DC - Atlanta
33          (15, 19), # I2 Atlanta - Houston
34          (17, 19), # I2 Kansas City - Houston
35          (17, 22), # I2 Kansas City - Salt Lake City
36          (19, 20), # I2 Houston - Los Angeles
37          (20, 21), # I2 Los Angeles - Seattle
38          (20, 22), # I2 Los Angeles - Salt Lake City
39          (21, 22)] # I2 Seattle - Salt Lake City
40
41
42 """
43 Generate site adjacency map from list of links
44 """
45 def gen_adjacencies(links):
46     adj = {}
47     for (a, b) in links:
48         if a in adj:
49             adj[a].append(b)
50         else:
51             adj[a] = [a, b]
52         if b in adj:
53             adj[b].append(a)
54         else:
55             adj[b] = [b, a]
56     return adj
57
58
59 """
60 Test whether two sites are adjacent to each other in the adjacency graph.
61 """
62 def is_adjacent(adjacencies, s1, s2):
63     set1 = set(adjacencies[s1])
64     set2 = set(adjacencies[s2])
65
66     if s1 in set2 and s2 in set1:
67         return True
68     elif not s1 in set2 and not s2 in set1:
69         return False
70     else:
71         raise Exception("Adjacency mismatch, sites %d and %d." % (s1, s2))
72
73
74 """
75 Check the adjacency graph for discrepancies.
76 """
77 def check_adjacencies(adjacencies):
78     for site in adjacencies:
79         for adj in adjacencies[site]:
80             try:
81                 test = is_adjacent(adjacencies, site, adj)
82             except Exception, e:
83                 print "Error: ", e, " Fix adjacencies!"
84     return
85
86
87 def get_site(nodeid):
88     if nodes[nodeid]:
89         return nodes[nodeid]['site_id']
90     raise Exception("Nodeid %s not found." % nodeid)
91
92
93 def get_ipaddr(nodeid):
94     if nodes[nodeid]:
95         return socket.gethostbyname(nodes[nodeid]['hostname'])
96     raise Exception("Nodeid %s not found." % nodeid)
97
98
99 def get_sitenodes(siteid):
100     if sites[siteid]:
101         return sites[siteid]['node_ids']
102     raise Exception("Siteid %s not found." % siteid)
103
104
105 """
106 Find the IP address assigned to a virtual interface in the topology
107 (for creating /etc/hosts)
108 """
109 def get_virt_ip(myid, nodeid):
110     if myid < nodeid:
111         virtip = "10.%d.%d.2" % (myid, nodeid)
112     else:
113         virtip = "10.%d.%d.3" % (nodeid, myid)
114     return virtip
115
116
117 """
118 Create a dictionary of site records keyed by site ID
119 """
120 def get_sites():
121     tmp = []
122     for site in GetSites():
123         t = site['site_id'], site
124         tmp.append(t)
125     return dict(tmp)
126
127
128 """
129 Create a dictionary of node records keyed by node ID
130 """
131 def get_nodes():
132     tmp = []
133     for node in GetNodes():
134         t = node['node_id'], node
135         tmp.append(t)
136     return dict(tmp)
137
138 adjacencies = gen_adjacencies(links)    
139 check_adjacencies(adjacencies)
140
141 """ Need global topology information """
142 sites = get_sites()
143 nodes = get_nodes()
144
145 for slice in GetSlices():
146     """ Create dictionary of the slice's attributes """
147     attrs ={}
148     topo_attr = {}
149     for attribute in GetSliceAttributes(slice['slice_attribute_ids']):
150         attrs[attribute['name']] = attribute['slice_attribute_id']
151         if attribute['name'] == 'topo_rspec' and attribute['node_id']:
152             topo_attr[attribute['node_id']] = attribute['slice_attribute_id']
153             
154     if 'egre_key' in attrs:
155         #print "Virtual topology for %s:" % slice['name']
156         slicenodes = set(slice['node_ids'])
157         hosts = "127.0.0.1\t\tlocalhost\n"
158         """
159         For each node in the slice, check whether nodes at adjacent sites
160         are also in the slice's node set.  If so, add a virtual link to 
161         the rspec.  
162         """
163         for node in slicenodes:
164             topo = []
165             for adj in adjacencies[get_site(node)]:
166                 for adj_node in get_sitenodes(adj):
167                     if node != adj_node and adj_node in slicenodes:
168                         link = adj_node, get_ipaddr(adj_node), "1Mbit"
169                         topo.append(link)
170                         shortname = nodes[node]['hostname'].replace('.vini-veritas.net', '')
171                         hosts += "%s\t\t%s\n" % (get_virt_ip(node, adj_node),
172                                                   shortname)
173             topo_str = "%s" % topo
174             #print node, topo_str
175             if node in topo_attr:
176                 UpdateSliceAttribute(topo_attr[node], topo_str)
177                 del topo_attr[node]
178             else:
179                 id = slice['slice_id']
180                 AddSliceAttribute(id, 'topo_rspec', topo_str, node)
181
182         #print hosts
183         if 'hosts' in attrs:
184             UpdateSliceAttribute(attrs['hosts'], hosts)
185         else:
186             id = slice['slice_id']
187             AddSliceAttribute(id, 'hosts', hosts)
188     #else:
189         #print "No EGRE key for %s" % slice['name']
190
191     """ Remove old topo_rspec entries """
192     for node in topo_attr:
193         DeleteSliceAttribute(topo_attr[node])
194
195