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
120 record['node_id'] = None
121 tag = Slicetag(record)
122 slicetags[tag.id] = tag
123 self.slice_tag_ids.append(tag.id)
128 # Update a slice tag if it exists, else add it
129 def update_tag(self, tagname, value, slicetags, node = None):
130 tag = self.get_tag(tagname, slicetags, node)
131 if tag and tag.value == value:
137 tag = self.add_tag(tagname, value, slicetags, node)
140 def assign_egre_key(self, slicetags):
141 if not self.get_tag('egre_key', slicetags):
143 key = free_egre_key(slicetags)
144 self.update_tag('egre_key', key, slicetags)
146 # Should handle this case...
150 def turn_on_netns(self, slicetags):
151 tag = self.get_tag('netns', slicetags)
152 if (not tag) or (tag.value != '1'):
153 self.update_tag('netns', '1', slicetags)
156 def turn_off_netns(self, slicetags):
157 tag = self.get_tag('netns', slicetags)
158 if tag and (tag.value != '0'):
162 def add_cap_net_admin(self, slicetags):
163 tag = self.get_tag('capabilities', slicetags)
165 caps = tag.value.split(',')
167 if cap == "CAP_NET_ADMIN":
170 newcaps = "CAP_NET_ADMIN," + tag.value
171 self.update_tag('capabilities', newcaps, slicetags)
173 self.add_tag('capabilities', 'CAP_NET_ADMIN', slicetags)
176 def remove_cap_net_admin(self, slicetags):
177 tag = self.get_tag('capabilities', slicetags)
179 caps = tag.value.split(',')
182 if cap != "CAP_NET_ADMIN":
185 value = ','.join(newcaps)
186 self.update_tag('capabilities', value, slicetags)
191 # Update the vsys/setup-link and vsys/setup-nat slice tags.
192 def add_vsys_tags(self, slicetags):
194 for i in self.slice_tag_ids:
196 if tag.tagname == 'vsys':
197 if tag.value == 'setup-link':
199 elif tag.value == 'setup-nat':
202 self.add_tag('vsys', 'setup-link', slicetags)
204 self.add_tag('vsys', 'setup-nat', slicetags)
210 def __init__(self, tag):
211 self.id = tag['slice_tag_id']
213 # Make one up for the time being...
214 self.id = Slicetag.newid
216 self.slice_id = tag['slice_id']
217 self.tagname = tag['tagname']
218 self.value = tag['value']
219 self.node_id = tag['node_id']
224 # Mark a tag as deleted
229 def write(self, slices, nodes, dryrun):
233 UpdateSliceTag(self.id, self.value)
235 AddSliceTag(self.slice_id, self.tagname, self.value, self.node_id)
236 elif self.deleted and int(self.id) > 0:
237 DeleteSliceTag(self.id)
239 slice = slices[self.slice_id].name
241 node = nodes[tag.node_id].hostname
244 self.value = "deleted"
245 elif not self.changed:
246 self.value = "no change"
250 print "[%s] %s: %s (%s, %s)" % (self.id, self.tagname, self.value, slice, node)
252 print "[%s] %s: %s (%s)" % (self.id, self.tagname, self.value, slice)
256 Create a dictionary of site objects keyed by site ID
260 for site in GetSites():
261 t = site['site_id'], Site(site)
267 Create a dictionary of node objects keyed by node ID
271 for node in GetNodes():
272 t = node['node_id'], Node(node)
277 Create a dictionary of slice objects keyed by slice ID
281 for slice in GetSlices():
282 t = slice['slice_id'], Slice(slice)
287 Create a dictionary of slicetag objects keyed by slice tag ID
289 def get_slice_tags():
291 for tag in GetSliceTags():
292 t = tag['slice_tag_id'], Slicetag(tag)
299 def free_egre_key(slicetags):
303 if tag.tagname == 'egre_key':
304 used.add(int(tag.value))
306 for i in range(1, 256):
311 raise KeyError("No more EGRE keys available")
320 slices = get_slices()
321 slicetags = get_slice_tags()
325 sites[a].add_adjacency(sites[b])
326 sites[b].add_adjacency(sites[a])
330 tag = slice.get_tag('vini_topo', slicetags)
332 topo_type = tag.value
337 Valid values of topo_type:
338 'vsys': Use vsys topology scripts to set up virtual links
339 'iias': Automatically create a virtual topology mirroring the physical one
340 'manual': Don't modify the topo_rspec tags if present
341 None: No virtual topology
343 if topo_type in ['vsys', 'iias', 'manual']:
344 slice.assign_egre_key(slicetags)
345 slice.turn_on_netns(slicetags)
346 slice.add_cap_net_admin(slicetags)
348 # Let them keep EGRE key for now...
349 slice.turn_off_netns(slicetags)
350 slice.remove_cap_net_admin(slicetags)
352 # Add vsys/setup-link and vsys/setup-nat
353 if topo_type == 'vsys' and slice.get_tag('egre_key', slicetags):
354 slice.add_vsys_tags(slicetags)
356 if topo_type == 'iias' and slice.get_tag('egre_key', slicetags):
358 print "Building virtual topology for %s" % slice.name
360 hosts = "127.0.0.1\t\tlocalhost\n"
362 For each node in the slice, check whether the slice is running on any
363 adjacent nodes. For each pair of adjacent nodes, add to nodes' rspecs.
365 for node in slice.get_nodes(nodes):
367 adj_nodes = node.adjacent_nodes(sites, nodes, slice.node_ids)
368 for adj in adj_nodes:
370 hosts += "%s\t\t%s\n" % (node.get_virt_ip(adj), node.shortname)
372 topo_str = "%s" % node.rspecs
373 slice.update_tag('topo_rspec', topo_str, slicetags, node)
375 slice.update_tag('hosts', hosts, slicetags)
378 print "Slice %s not using IIAS" % slice.name
380 if topo_type == 'manual' and slice.get_tag('egre_key', slicetags):
381 for node in slice.get_nodes(nodes):
382 topo_tag = slice.get_tag('topo_rspec', slicetags, node)
384 topo_tag.updated = True
386 # Update the tag values in the database
389 if (tag.tagname == 'topo_rspec' or tag.tagname == 'hosts') and not tag.updated:
391 tag.write(slices, nodes, dryrun)