5 Scan the VINI Central database and create topology "rspec" tags for
6 slices that have an EGRE key. This script to be run from a cron job.
11 from topology import links
14 def __init__(self, node):
15 self.id = node['node_id']
16 self.hostname = node['hostname']
17 self.shortname = self.hostname.replace('.vini-veritas.net', '')
18 self.site_id = node['site_id']
19 self.ipaddr = socket.gethostbyname(self.hostname)
21 def get_link_id(self, remote):
22 if self.id < remote.id:
23 link = (self.id<<7) + remote.id
25 link = (remote.id<<7) + self.id
28 def get_iface_id(self, remote):
29 if self.id < remote.id:
35 def get_virt_ip(self, remote):
36 link = self.get_link_id(remote)
37 iface = self.get_iface_id(remote)
39 second = ((link & 0x3f)<<2) + iface
40 return "192.168.%d.%d" % (first, second)
42 def get_virt_net(self, remote):
43 link = self.get_link_id(remote)
45 second = (link & 0x3f)<<2
46 return "192.168.%d.%d/30" % (first, second)
48 def get_site(self, sites):
49 return sites[self.site_id]
52 # What nodes in the set of node_ids are adjacent to this one?
53 def adjacent_nodes(self, sites, nodes, node_ids):
54 mysite = self.get_site(sites)
55 adj_ids = mysite.adj_node_ids.intersection(node_ids)
58 adj_nodes.append(nodes[id])
61 def init_rspecs(self):
64 def add_rspec(self, remote):
65 my_ip = self.get_virt_ip(remote)
66 remote_ip = remote.get_virt_ip(self)
67 net = self.get_virt_net(remote)
68 rspec = remote.id, remote.ipaddr, "1Mbit", my_ip, remote_ip, net
69 self.rspecs.append(rspec)
73 def __init__(self, site):
74 self.id = site['site_id']
75 self.node_ids = site['node_ids']
76 self.adj_site_ids = set()
77 self.adj_node_ids = set()
79 def get_sitenodes(self, nodes):
81 for i in self.node_ids:
85 def add_adjacency(self, site):
86 self.adj_site_ids.add(site.id)
87 for n in site.node_ids:
88 self.adj_node_ids.add(n)
92 def __init__(self, slice):
93 self.id = slice['slice_id']
94 self.name = slice['name']
95 self.node_ids = set(slice['node_ids'])
96 self.slice_tag_ids = slice['slice_tag_ids']
98 def get_tag(self, tagname, slicetags, node = None):
99 for i in self.slice_tag_ids:
101 if tag.tagname == tagname:
102 if (not node) or (node.id == tag.node_id):
107 def get_nodes(self, nodes):
109 for id in self.node_ids:
114 # Add a new slice tag
115 def add_tag(self, tagname, value, slicetags, node = None):
116 record = {'slice_tag_id':None, 'slice_id':self.id, 'tagname':tagname, 'value':value}
118 record['node_id'] = node.id
119 tag = Slicetag(record)
121 self.slice_tag_ids.append(id)
126 # Update a slice tag if it exists, else add it
127 def update_tag(self, tagname, value, slicetags, node = None):
128 tag = self.get_tag(tagname, slicetags, node)
129 if tag and tag.value == value:
135 tag = self.add_tag(tagname, value, slicetags, node)
138 def assign_egre_key(self, slicetags):
139 if not self.get_tag('egre_key', slicetags):
141 key = free_egre_key(slicetags)
142 self.update_tag('egre_key', key, slicetags)
144 # Should handle this case...
148 def turn_on_netns(self, slicetags):
149 tag = self.get_tag('netns', slicetags)
150 if (not tag) or (tag.value != '1'):
151 self.update_tag('netns', '1', slicetags)
154 def turn_off_netns(self, slicetags):
155 tag = self.get_tag('netns', slicetags)
156 if tag and (tag.value != '0'):
160 def add_cap_net_admin(self, slicetags):
161 tag = self.get_tag('capabilities', slicetags)
163 caps = tag.value.split(',')
165 if cap == "CAP_NET_ADMIN":
168 newcaps = "CAP_NET_ADMIN," + caps
169 self.update_tag('capabilities', newcaps, slicetags)
171 self.add_tag('capabilities', 'CAP_NET_ADMIN', slicetags)
174 def remove_cap_net_admin(self, slicetags):
175 tag = self.get_tag('capabilities', slicetags)
177 caps = tag.value.split(',')
180 if cap != "CAP_NET_ADMIN":
183 value = ','.join(newcaps)
184 self.update_tag('capabilities', value, slicetags)
189 # Update the vsys/setup-link and vsys/setup-nat slice tags.
190 def add_vsys_tags(self, slicetags):
192 for i in self.slice_tag_ids:
194 if tag.tagname == 'vsys':
195 if tag.value == 'setup-link':
197 elif tag.value == 'setup-nat':
200 self.add_tag('vsys', 'setup-link', slicetags)
202 self.add_tag('vsys', 'setup-nat', slicetags)
208 def __init__(self, tag):
209 self.id = tag['slice_tag_id']
211 # Make one up for the time being...
212 self.id = Slicetag.newid
214 self.slice_id = tag['slice_id']
215 self.tagname = tag['tagname']
216 self.value = tag['value']
217 self.node_id = tag['node_id']
222 # Mark a tag as deleted
227 def write(self, slices, nodes, dryrun):
231 UpdateSliceTag(self.id, self.value)
233 AddSliceTag(self.slice_id, self.tagname, self.value, self.node_id)
234 elif self.deleted and int(self.id) > 0:
235 DeleteSliceTag(self.id)
237 slice = slices[self.slice_id].name
239 node = nodes[tag.node_id].hostname
242 self.value = "deleted"
243 elif not self.changed:
244 self.value = "no change"
248 print "[%s] %s: %s (%s, %s)" % (self.id, self.tagname, self.value, slice, node)
250 print "[%s] %s: %s (%s)" % (self.id, self.tagname, self.value, slice)
254 Create a dictionary of site objects keyed by site ID
258 for site in GetSites():
259 t = site['site_id'], Site(site)
265 Create a dictionary of node objects keyed by node ID
269 for node in GetNodes():
270 t = node['node_id'], Node(node)
275 Create a dictionary of slice objects keyed by slice ID
279 for slice in GetSlices():
280 t = slice['slice_id'], Slice(slice)
285 Create a dictionary of slicetag objects keyed by slice tag ID
287 def get_slice_tags():
289 for tag in GetSliceTags():
290 t = tag['slice_tag_id'], Slicetag(tag)
297 def free_egre_key(slicetags):
301 if tag.tagname == 'egre_key':
302 used.add(int(tag.value))
304 for i in range(1, 256):
309 raise KeyError("No more EGRE keys available")
318 slices = get_slices()
319 slicetags = get_slice_tags()
323 sites[a].add_adjacency(sites[b])
324 sites[b].add_adjacency(sites[a])
328 tag = slice.get_tag('vini_topo', slicetags)
330 topo_type = tag.value
334 if topo_type == 'vsys' or topo_type == 'iias':
335 slice.assign_egre_key(slicetags)
336 slice.turn_on_netns(slicetags)
337 slice.add_cap_net_admin(slicetags)
339 # Let them keep EGRE key for now...
340 slice.turn_off_netns(slicetags)
341 slice.remove_cap_net_admin(slicetags)
343 # Add vsys/setup-link and vsys/setup-nat
344 if topo_type == 'vsys' and slice.get_tag('egre_key', slicetags):
345 slice.add_vsys_tags(slicetags)
347 if topo_type == 'iias' and slice.get_tag('egre_key', slicetags):
349 print "Building virtual topology for %s" % slice.name
351 hosts = "127.0.0.1\t\tlocalhost\n"
353 For each node in the slice, check whether the slice is running on any
354 adjacent nodes. For each pair of adjacent nodes, add to nodes' rspecs.
356 for node in slice.get_nodes(nodes):
358 adj_nodes = node.adjacent_nodes(sites, nodes, slice.node_ids)
359 for adj in adj_nodes:
361 hosts += "%s\t\t%s\n" % (node.get_virt_ip(adj), node.shortname)
363 topo_str = "%s" % node.rspecs
364 slice.update_tag('topo_rspec', topo_str, slicetags, node)
366 slice.update_tag('hosts', hosts, slicetags)
369 print "Slice %s not using IIAS" % slice.name
371 # Update the tag values in the database
374 if (tag.tagname == 'topo_rspec' or tag.tagname == 'hosts') and not tag.updated:
376 tag.write(slices, nodes, dryrun)