removed another bunch of references to geni
[sfa.git] / sfa / rspecs / aggregates / rspec_manager_vini.py
1 from sfa.util.faults import *
2 from sfa.util.namespace 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 *
8 import sys
9
10 SFA_VINI_WHITELIST = '/etc/sfa/vini.whitelist'
11
12 """
13 Copied from create_slice_aggregate() in sfa.plc.slices
14 """
15 def create_slice_vini_aggregate(api, hrn, nodes):
16     # Get the slice record from SFA
17     slice = {}
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['type'] in ['slice']:
24             slice = record
25     if not slice:
26         raise RecordNotFound(hrn)   
27
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'])
31     if not slices:
32         parts = slicename.split("_")
33         login_base = parts[0]
34         # if site doesnt exist add it
35         sites = api.plshell.GetSites(api.plauth, [login_base])
36         if not sites:
37             authority = get_authority(hrn)
38             site_records = registry.resolve(credential, authority)
39             site_record = {}
40             if not site_records:
41                 raise RecordNotFound(authority)
42             site = site_records[0]
43                 
44             # add the site
45             site.pop('site_id')
46             site_id = api.plshell.AddSite(api.plauth, site)
47         else:
48             site = sites[0]
49             
50         slice_fields = {}
51         slice_keys = ['name', 'url', 'description']
52         for key in slice_keys:
53             if key in slice and slice[key]:
54                 slice_fields[key] = slice[key]  
55         api.plshell.AddSlice(api.plauth, slice_fields)
56         slice = slice_fields
57         slice['node_ids'] = 0
58     else:
59         slice = slices[0]    
60
61     # get the list of valid slice users from the registry and make 
62     # they are added to the slice 
63     researchers = record.get('researcher', [])
64     for researcher in researchers:
65         person_record = {}
66         person_records = registry.resolve(credential, researcher)
67         for record in person_records:
68             if record['type'] in ['user']:
69                 person_record = record
70         if not person_record:
71             pass
72         person_dict = person_record
73         persons = api.plshell.GetPersons(api.plauth, [person_dict['email']],
74                                          ['person_id', 'key_ids'])
75
76         # Create the person record 
77         if not persons:
78             person_id=api.plshell.AddPerson(api.plauth, person_dict)
79
80             # The line below enables the user account on the remote aggregate
81             # soon after it is created.
82             # without this the user key is not transfered to the slice
83             # (as GetSlivers returns key of only enabled users),
84             # which prevents the user from login to the slice.
85             # We may do additional checks before enabling the user.
86
87             api.plshell.UpdatePerson(api.plauth, person_id, {'enabled' : True})
88             key_ids = []
89         else:
90             key_ids = persons[0]['key_ids']
91
92         api.plshell.AddPersonToSlice(api.plauth, person_dict['email'],
93                                      slicename)        
94
95         # Get this users local keys
96         keylist = api.plshell.GetKeys(api.plauth, key_ids, ['key'])
97         keys = [key['key'] for key in keylist]
98
99         # add keys that arent already there 
100         for personkey in person_dict['keys']:
101             if personkey not in keys:
102                 key = {'key_type': 'ssh', 'key': personkey}
103                 api.plshell.AddPersonKey(api.plauth, person_dict['email'], key)
104
105     # find out where this slice is currently running
106     nodelist = api.plshell.GetNodes(api.plauth, slice['node_ids'],
107                                     ['hostname'])
108     hostnames = [node['hostname'] for node in nodelist]
109
110     # remove nodes not in rspec
111     deleted_nodes = list(set(hostnames).difference(nodes))
112     # add nodes from rspec
113     added_nodes = list(set(nodes).difference(hostnames))
114
115     """
116     print >> sys.stderr, "Slice on nodes:"
117     for n in hostnames:
118         print >> sys.stderr, n
119     print >> sys.stderr, "Wants nodes:"
120     for n in nodes:
121         print >> sys.stderr, n
122     print >> sys.stderr, "Deleting nodes:"
123     for n in deleted_nodes:
124         print >> sys.stderr, n
125     print >> sys.stderr, "Adding nodes:"
126     for n in added_nodes:
127         print >> sys.stderr, n
128     """
129
130     api.plshell.AddSliceToNodes(api.plauth, slicename, added_nodes) 
131     api.plshell.DeleteSliceFromNodes(api.plauth, slicename, deleted_nodes)
132
133     return 1
134
135 def get_rspec(api, hrn):
136     topo = Topology(api)      
137     if (hrn):
138         slicename = hrn_to_pl_slicename(hrn)
139         slice = get_slice(api, slicename)
140         if slice:
141             slice.hrn = hrn
142             topo.nodeTopoFromSliceTags(slice)
143         else:
144             # call the default sfa.plc.nodes.get_rspec() method
145             return Nodes(api).get_rspec(hrn)     
146
147     return topo.toxml(hrn)
148
149
150
151 """
152 Hook called via 'sfi.py create'
153 """
154 def create_slice(api, hrn, xml):
155     ### Check the whitelist
156     ### It consists of lines of the form: <slice hrn> <bw>
157     whitelist = {}
158     f = open(SFA_VINI_WHITELIST)
159     for line in f.readlines():
160         (slice, maxbw) = line.split()
161         whitelist[slice] = maxbw
162         
163     if hrn in whitelist:
164         maxbw = whitelist[hrn]
165     else:
166         raise PermissionError("%s not in VINI whitelist" % hrn)
167         
168     rspec = RSpec(xml)
169     topo = Topology(api)
170     
171     topo.nodeTopoFromRSpec(rspec)
172
173     # Check request against current allocations
174     topo.verifyNodeTopo(hrn, topo, maxbw)
175     
176     nodes = topo.nodesInTopo()
177     hostnames = []
178     for node in nodes:
179         hostnames.append(node.hostname)
180     create_slice_vini_aggregate(api, hrn, hostnames)
181
182     slicename = hrn_to_pl_slicename(hrn)
183     slice = get_slice(api, slicename)
184     if slice:
185         topo.updateSliceTags(slice)    
186
187     return True
188
189 """
190 Returns the request context required by sfatables. At some point, this mechanism should be changed
191 to refer to "contexts", which is the information that sfatables is requesting. But for now, we just
192 return the basic information needed in a dict.
193 """
194 def fetch_context(slice_hrn, user_hrn, contexts):
195     base_context = {'sfa':{'user':{'hrn':user_hrn},
196                            'slice':{'hrn':slice_hrn}}}
197     return base_context
198
199 def main():
200     r = RSpec()
201     r.parseFile(sys.argv[1])
202     rspec = r.toDict()
203     create_slice(None,'plc',rspec)
204
205 if __name__ == "__main__":
206     main()