4 # Taken from bwlimit.py
6 # See tc_util.c and http://physics.nist.gov/cuu/Units/binary.html. Be
7 # warned that older versions of tc interpret "kbps", "mbps", "mbit",
8 # and "kbit" to mean (in this system) "kibps", "mibps", "mibit", and
9 # "kibit" and that if an older version is installed, all rates will
10 # be off by a small fraction.
18 "gibit": 1024*1024*1024,
20 "tibit": 1024*1024*1024*1024,
21 "tbit": 1000000000000,
27 "gibps": 8*1024*1024*1024,
29 "tibps": 8*1024*1024*1024*1024,
36 Parses an integer or a tc rate string (e.g., 1.5mbit) into bits/second
41 m = re.match(r"([0-9.]+)(\D*)", s)
44 suffix = m.group(2).lower()
45 if suffixes.has_key(suffix):
46 return int(float(m.group(1)) * suffixes[suffix])
52 def __init__(self, node):
53 self.id = node['node_id']
54 self.hostname = node['hostname']
55 self.shortname = self.hostname.replace('.vini-veritas.net', '')
56 self.site_id = node['site_id']
57 self.ipaddr = socket.gethostbyname(self.hostname)
60 def get_link_id(self, remote):
61 if self.id < remote.id:
62 link = (self.id<<7) + remote.id
64 link = (remote.id<<7) + self.id
67 def get_iface_id(self, remote):
68 if self.id < remote.id:
74 def get_virt_ip(self, remote):
75 link = self.get_link_id(remote)
76 iface = self.get_iface_id(remote)
78 second = ((link & 0x3f)<<2) + iface
79 return "192.168.%d.%d" % (first, second)
81 def get_virt_net(self, remote):
82 link = self.get_link_id(remote)
84 second = (link & 0x3f)<<2
85 return "192.168.%d.%d/30" % (first, second)
87 def get_site(self, sites):
88 return sites[self.site_id]
90 def adjacent_nodes(self, sites, nodes, node_ids):
91 mysite = self.get_site(sites)
92 adj_ids = mysite.adj_node_ids.intersection(node_ids)
95 adj_nodes.append(nodes[id])
101 def add_link(self, remote, bw):
102 my_ip = self.get_virt_ip(remote)
103 remote_ip = remote.get_virt_ip(self)
104 net = self.get_virt_net(remote)
105 link = remote.id, remote.ipaddr, bw, my_ip, remote_ip, net
106 self.links.append(link)
110 def __init__(self, site):
111 self.id = site['site_id']
112 self.node_ids = site['node_ids']
113 self.adj_site_ids = set()
114 self.adj_node_ids = set()
116 def get_sitenodes(self, nodes):
118 for i in self.node_ids:
122 def add_adjacency(self, site):
123 self.adj_site_ids.add(site.id)
124 for n in site.node_ids:
125 self.adj_node_ids.add(n)
129 def __init__(self, slice):
130 self.id = slice['slice_id']
131 self.name = slice['name']
132 self.node_ids = set(slice['node_ids'])
133 self.slice_tag_ids = slice['slice_tag_ids']
135 def get_tag(self, tagname, slicetags, node = None):
136 for i in self.slice_tag_ids:
138 if tag.tagname == tagname:
139 if (not node) or (node.id == tag.node_id):
144 def get_nodes(self, nodes):
146 for id in self.node_ids:
151 # Add a new slice tag
152 def add_tag(self, tagname, value, slicetags, node = None):
153 record = {'slice_tag_id':None, 'slice_id':self.id, 'tagname':tagname, 'value':value}
155 record['node_id'] = node.id
157 record['node_id'] = None
158 tag = Slicetag(record)
159 slicetags[tag.id] = tag
160 self.slice_tag_ids.append(tag.id)
165 # Update a slice tag if it exists, else add it
166 def update_tag(self, tagname, value, slicetags, node = None):
167 tag = self.get_tag(tagname, slicetags, node)
168 if tag and tag.value == value:
174 tag = self.add_tag(tagname, value, slicetags, node)
177 def assign_egre_key(self, slicetags):
178 if not self.get_tag('egre_key', slicetags):
180 key = free_egre_key(slicetags)
181 self.update_tag('egre_key', key, slicetags)
183 # Should handle this case...
187 def turn_on_netns(self, slicetags):
188 tag = self.get_tag('netns', slicetags)
189 if (not tag) or (tag.value != '1'):
190 self.update_tag('netns', '1', slicetags)
193 def turn_off_netns(self, slicetags):
194 tag = self.get_tag('netns', slicetags)
195 if tag and (tag.value != '0'):
199 def add_cap_net_admin(self, slicetags):
200 tag = self.get_tag('capabilities', slicetags)
202 caps = tag.value.split(',')
204 if cap == "CAP_NET_ADMIN":
207 newcaps = "CAP_NET_ADMIN," + tag.value
208 self.update_tag('capabilities', newcaps, slicetags)
210 self.add_tag('capabilities', 'CAP_NET_ADMIN', slicetags)
213 def remove_cap_net_admin(self, slicetags):
214 tag = self.get_tag('capabilities', slicetags)
216 caps = tag.value.split(',')
219 if cap != "CAP_NET_ADMIN":
222 value = ','.join(newcaps)
223 self.update_tag('capabilities', value, slicetags)
228 # Update the vsys/setup-link and vsys/setup-nat slice tags.
229 def add_vsys_tags(self, slicetags):
231 for i in self.slice_tag_ids:
233 if tag.tagname == 'vsys':
234 if tag.value == 'setup-link':
236 elif tag.value == 'setup-nat':
239 self.add_tag('vsys', 'setup-link', slicetags)
241 self.add_tag('vsys', 'setup-nat', slicetags)
247 def __init__(self, tag):
248 self.id = tag['slice_tag_id']
250 # Make one up for the time being...
251 self.id = Slicetag.newid
253 self.slice_id = tag['slice_id']
254 self.tagname = tag['tagname']
255 self.value = tag['value']
256 self.node_id = tag['node_id']
261 # Mark a tag as deleted
266 def write(self, api):
269 api.plshell.UpdateSliceTag(api.plauth, self.id, self.value)
271 api.plshell.AddSliceTag(api.plauth, self.slice_id,
272 self.tagname, self.value, self.node_id)
273 elif self.deleted and int(self.id) > 0:
274 api.plshell.DeleteSliceTag(api.plauth, self.id)
278 Create a dictionary of site objects keyed by site ID
282 for site in GetSites():
283 t = site['site_id'], Site(site)
289 Create a dictionary of node objects keyed by node ID
293 for node in api.plshell.GetNodes(api.plauth):
294 t = node['node_id'], Node(node)
299 Create a dictionary of slice objects keyed by slice ID
301 def get_slice(api, slicename):
302 slice = api.plshell.GetSlices(api.plauth, [slicename])
304 return Slice(slice[0])
309 Create a dictionary of slicetag objects keyed by slice tag ID
311 def get_slice_tags(api):
313 for tag in api.plshell.GetSliceTags(api.plauth):
314 t = tag['slice_tag_id'], Slicetag(tag)
321 def free_egre_key(slicetags):
325 if tag.tagname == 'egre_key':
326 used.add(int(tag.value))
328 for i in range(1, 256):
333 raise KeyError("No more EGRE keys available")