1 from sfa.util.faults import *
2 from sfa.util.misc import *
3 from sfa.util.rspec import Rspec
4 from sfa.server.registry import Registries
5 from sfa.plc.nodes import *
6 from sfa.rspecs.aggregates.vini_utils import *
9 SFA_VINI_DEFAULT_RSPEC = '/etc/sfa/vini.rspec'
10 SFA_VINI_WHITELIST = '/etc/sfa/vini.whitelist'
13 Copied from create_slice_aggregate() in sfa.plc.slices
15 def create_slice_vini_aggregate(api, hrn, nodes):
16 # Get the slice record from geni
18 registries = Registries(api)
19 registry = registries[api.hrn]
20 credential = api.getCredential()
21 records = registry.resolve(credential, hrn)
22 for record in records:
23 if record.get_type() in ['slice']:
24 slice = record.as_dict()
26 raise RecordNotFound(hrn)
28 # Make sure slice exists at plc, if it doesnt add it
29 slicename = hrn_to_pl_slicename(hrn)
30 slices = api.plshell.GetSlices(api.plauth, [slicename], ['node_ids'])
32 parts = slicename.split("_")
34 # if site doesnt exist add it
35 sites = api.plshell.GetSites(api.plauth, [login_base])
37 authority = get_authority(hrn)
38 site_records = registry.resolve(credential, authority)
41 raise RecordNotFound(authority)
42 site_record = site_records[0]
43 site = site_record.as_dict()
47 site_id = api.plshell.AddSite(api.plauth, site)
52 slice_keys = ['name', 'url', 'description']
53 for key in slice_keys:
54 if key in slice and slice[key]:
55 slice_fields[key] = slice[key]
56 api.plshell.AddSlice(api.plauth, slice_fields)
62 # get the list of valid slice users from the registry and make
63 # they are added to the slice
64 researchers = record.get('researcher', [])
65 for researcher in researchers:
67 person_records = registry.resolve(credential, researcher)
68 for record in person_records:
69 if record.get_type() in ['user']:
70 person_record = record
73 person_dict = person_record.as_dict()
74 persons = api.plshell.GetPersons(api.plauth, [person_dict['email']],
75 ['person_id', 'key_ids'])
77 # Create the person record
79 person_id=api.plshell.AddPerson(api.plauth, person_dict)
81 # The line below enables the user account on the remote aggregate
82 # soon after it is created.
83 # without this the user key is not transfered to the slice
84 # (as GetSlivers returns key of only enabled users),
85 # which prevents the user from login to the slice.
86 # We may do additional checks before enabling the user.
88 api.plshell.UpdatePerson(api.plauth, person_id, {'enabled' : True})
91 key_ids = persons[0]['key_ids']
93 api.plshell.AddPersonToSlice(api.plauth, person_dict['email'],
96 # Get this users local keys
97 keylist = api.plshell.GetKeys(api.plauth, key_ids, ['key'])
98 keys = [key['key'] for key in keylist]
100 # add keys that arent already there
101 for personkey in person_dict['keys']:
102 if personkey not in keys:
103 key = {'key_type': 'ssh', 'key': personkey}
104 api.plshell.AddPersonKey(api.plauth, person_dict['email'], key)
106 # find out where this slice is currently running
107 nodelist = api.plshell.GetNodes(api.plauth, slice['node_ids'],
109 hostnames = [node['hostname'] for node in nodelist]
111 # remove nodes not in rspec
112 deleted_nodes = list(set(hostnames).difference(nodes))
113 # add nodes from rspec
114 added_nodes = list(set(nodes).difference(hostnames))
117 print >> sys.stderr, "Slice on nodes:"
119 print >> sys.stderr, n
120 print >> sys.stderr, "Wants nodes:"
122 print >> sys.stderr, n
123 print >> sys.stderr, "Deleting nodes:"
124 for n in deleted_nodes:
125 print >> sys.stderr, n
126 print >> sys.stderr, "Adding nodes:"
127 for n in added_nodes:
128 print >> sys.stderr, n
131 api.plshell.AddSliceToNodes(api.plauth, slicename, added_nodes)
132 api.plshell.DeleteSliceFromNodes(api.plauth, slicename, deleted_nodes)
136 def get_rspec(api, hrn):
139 default.parseFile(SFA_VINI_DEFAULT_RSPEC)
142 slicename = hrn_to_pl_slicename(hrn)
143 defaultrspec = default.toDict()
144 nodedict = get_nodedict(defaultrspec)
146 # call the default sfa.plc.nodes.get_rspec() method
148 rspec = nodes.get_rspec(hrn)
150 # Grab all the PLC info we'll need at once
151 slice = get_slice(api, slicename)
153 nodes = get_nodes(api)
154 tags = get_slice_tags(api)
156 # Add the node tags from the Capacity statement to Node objects
157 for (k, v) in nodedict.iteritems():
159 if v == nodes[id].hostname:
163 for node in slice.get_nodes(nodes):
164 linktag = slice.get_tag('topo_rspec', tags, node)
166 l = eval(linktag.value)
167 for (id, realip, bw, lvip, rvip, vnet) in l:
168 endpoints.append((node.id, id, bw))
172 for (l, r, bw) in endpoints:
173 if (r, l, bw) in endpoints:
176 edict['endpoint'] = [nodes[l].tag, nodes[r].tag]
178 linkspecs.append(edict)
181 d['Rspec']['Request'][0]['NetSpec'][0]['LinkSpec'] = linkspecs
182 d['Rspec']['Request'][0]['NetSpec'][0]['name'] = hrn
187 # Return canned response for now...
188 rspec = default.toxml()
193 def create_slice(api, hrn, xml):
197 ### Check the whitelist
198 ### It consists of lines of the form: <slice hrn> <bw>
200 f = open(SFA_VINI_WHITELIST)
201 for line in f.readlines():
202 (slice, maxbw) = line.split()
203 whitelist[slice] = maxbw
206 maxbps = get_tc_rate(whitelist[hrn])
208 raise PermissionError("%s not in VINI whitelist" % hrn)
210 ### Check to make sure that the slice isn't requesting more
211 ### than its maximum bandwidth.
212 linkspecs = rspec['Rspec']['Request'][0]['NetSpec'][0]['LinkSpec']
216 bps = get_tc_rate(bw)
218 raise GeniInvalidArgument(bw, "BW")
220 raise PermissionError(" %s requested %s but max BW is %s" % (hrn, bw, whitelist[hrn]))
222 # Check request against current allocations
225 nodes = rspec_to_nodeset(rspec)
226 create_slice_vini_aggregate(api, hrn, nodes)
228 # Add VINI-specific topology attributes to slice here
230 linkspecs = rspec['Rspec']['Request'][0]['NetSpec'][0]['LinkSpec']
232 slicename = hrn_to_pl_slicename(hrn)
234 # Grab all the PLC info we'll need at once
235 slice = get_slice(api, slicename)
237 nodes = get_nodes(api)
238 tags = get_slice_tags(api)
240 slice.update_tag('vini_topo', 'manual', tags)
241 slice.assign_egre_key(tags)
242 slice.turn_on_netns(tags)
243 slice.add_cap_net_admin(tags)
246 for (k, v) in get_nodedict(rspec).iteritems():
248 if v == nodes[id].hostname:
249 nodedict[k] = nodes[id]
252 n1 = nodedict[l['endpoint'][0]]
253 n2 = nodedict[l['endpoint'][1]]
258 for node in slice.get_nodes(nodes):
260 topo_str = "%s" % node.links
261 slice.update_tag('topo_rspec', topo_str, tags, node)
263 # Update slice tags in database
266 if tag.slice_id == slice.id:
267 if tag.tagname == 'topo_rspec' and not tag.updated:
277 def get_nodedict(rspec):
280 sitespecs = rspec['Rspec']['Capacity'][0]['NetSpec'][0]['SiteSpec']
282 for node in s['NodeSpec']:
283 nodedict[node['name']] = node['hostname'][0]
290 def rspec_to_nodeset(rspec):
293 nodedict = get_nodedict(rspec)
294 linkspecs = rspec['Rspec']['Request'][0]['NetSpec'][0]['LinkSpec']
296 for e in l['endpoint']:
297 nodes.add(nodedict[e])
306 r.parseFile(sys.argv[1])
308 create_slice(None,'plc',rspec)
310 if __name__ == "__main__":