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)
153 Hook called via 'sfi.py create'
155 def create_slice(api, hrn, xml):
156 ### Check the whitelist
157 ### It consists of lines of the form: <slice hrn> <bw>
159 f = open(SFA_VINI_WHITELIST)
160 for line in f.readlines():
161 (slice, maxbw) = line.split()
162 whitelist[slice] = maxbw
165 maxbw = whitelist[hrn]
167 raise PermissionError("%s not in VINI whitelist" % hrn)
172 topo.nodeTopoFromRSpec(rspec)
174 # Check request against current allocations
175 topo.verifyNodeTopo(hrn, topo, maxbw)
177 nodes = topo.nodesInTopo()
180 hostnames.append(node.hostname)
181 create_slice_vini_aggregate(api, hrn, hostnames)
183 slicename = hrn_to_pl_slicename(hrn)
184 slice = get_slice(api, slicename)
186 topo.updateSliceTags(slice)
191 Returns the request context required by sfatables. At some point, this mechanism should be changed
192 to refer to "contexts", which is the information that sfatables is requesting. But for now, we just
193 return the basic information needed in a dict.
195 def fetch_context(slice_hrn, user_hrn, contexts):
196 base_context = {'sfa':{'user':{'hrn':user_hrn}}}
201 r.parseFile(sys.argv[1])
203 create_slice(None,'plc',rspec)
205 if __name__ == "__main__":