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 *
7 from sfa.rspecs.aggregates.vini.rspec import *
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 slicename = hrn_to_pl_slicename(hrn)
140 slice = get_slice(api, slicename)
143 topo.nodeTopoFromSliceTags(slice)
145 # call the default sfa.plc.nodes.get_rspec() method
146 return Nodes(api).get_rspec(hrn)
148 return topo.toxml(hrn)
152 Check the requested topology against the available topology and capacity
154 def check_request(hrn, rspec, nodes, sites, sitelinks, maxbw):
155 linkspecs = rspec['Rspec']['Request'][0]['NetSpec'][0]['LinkSpec']
158 n1 = Node.lookup(l['endpoint'][0])
159 n2 = Node.lookup(l['endpoint'][1])
161 reqbps = get_tc_rate(bw)
162 maxbps = get_tc_rate(maxbw)
165 raise GeniInvalidArgument(bw, "BW")
167 raise PermissionError(" %s requested %s but max BW is %s" %
170 if adjacent_nodes(n1, n2, sites, sitelinks):
171 availbps = get_avail_bps(n1, n2, sites, sitelinks)
172 if availbps < reqbps:
173 raise PermissionError("%s: capacity exceeded" % hrn)
175 raise PermissionError("%s: nodes %s and %s not adjacent"
176 % (hrn, n1.tag, n2.tag))
179 Hook called via 'sfi.py create'
181 def create_slice(api, hrn, xml):
182 ### Check the whitelist
183 ### It consists of lines of the form: <slice hrn> <bw>
185 f = open(SFA_VINI_WHITELIST)
186 for line in f.readlines():
187 (slice, maxbw) = line.split()
188 whitelist[slice] = maxbw
191 maxbw = whitelist[hrn]
193 raise PermissionError("%s not in VINI whitelist" % hrn)
198 topo.nodeTopoFromRspec(rspec)
200 # Check request against current allocations
201 #check_request(hrn, rspec, nodes, sites, sitelinks, maxbw)
203 nodes = topo.nodesInTopo()
206 hostnames.append(node.hostname)
207 create_slice_vini_aggregate(api, hrn, hostnames)
209 slicename = hrn_to_pl_slicename(hrn)
210 slice = get_slice(api, slicename)
212 topo.updateSliceTags(slice)
219 r.parseFile(sys.argv[1])
221 create_slice(None,'plc',rspec)
223 if __name__ == "__main__":