Re-indent
[sfa.git] / sfa / rspecs / aggregates / rspec_manager_vini.py
1 from sfa.util.faults import *
2 from sfa.util.rspec import Rspec
3 from sfa.server.registry import Registries
4 import sys
5 import pdb
6
7 SFA_VINI_DEFAULT_RSPEC = '/etc/sfa/vini.rspec'
8
9 """
10 Copied from create_slice_aggregate() in sfa.plc.slices
11 """
12 def create_slice_vini_aggregate(api, hrn, nodes):
13     # Get the slice record from geni
14     slice = {}
15     registries = Registries(api)
16     registry = registries[api.hrn]
17     credential = api.getCredential()
18     records = registry.resolve(credential, hrn)
19     for record in records:
20         if record.get_type() in ['slice']:
21             slice = record.as_dict()
22     if not slice:
23         raise RecordNotFound(hrn)   
24
25     # Make sure slice exists at plc, if it doesnt add it
26     slicename = hrn_to_pl_slicename(hrn)
27     slices = api.plshell.GetSlices(api.plauth, [slicename], ['node_ids'])
28     if not slices:
29         parts = slicename.split("_")
30         login_base = parts[0]
31         # if site doesnt exist add it
32         sites = api.plshell.GetSites(api.plauth, [login_base])
33         if not sites:
34             authority = get_authority(hrn)
35             site_records = registry.resolve(credential, authority)
36             site_record = {}
37             if not site_records:
38                 raise RecordNotFound(authority)
39             site_record = site_records[0]
40             site = site_record.as_dict()
41                 
42             # add the site
43             site.pop('site_id')
44             site_id = api.plshell.AddSite(api.plauth, site)
45         else:
46             site = sites[0]
47             
48         slice_fields = {}
49         slice_keys = ['name', 'url', 'description']
50         for key in slice_keys:
51             if key in slice and slice[key]:
52                 slice_fields[key] = slice[key]  
53         api.plshell.AddSlice(api.plauth, slice_fields)
54         slice = slice_fields
55         slice['node_ids'] = 0
56     else:
57         slice = slices[0]    
58
59     # get the list of valid slice users from the registry and make 
60     # they are added to the slice 
61     researchers = record.get('researcher', [])
62     for researcher in researchers:
63         person_record = {}
64         person_records = registry.resolve(credential, researcher)
65         for record in person_records:
66             if record.get_type() in ['user']:
67                 person_record = record
68         if not person_record:
69             pass
70         person_dict = person_record.as_dict()
71         persons = api.plshell.GetPersons(api.plauth, [person_dict['email']],
72                                          ['person_id', 'key_ids'])
73
74         # Create the person record 
75         if not persons:
76             person_id=api.plshell.AddPerson(api.plauth, person_dict)
77
78             # The line below enables the user account on the remote aggregate
79             # soon after it is created.
80             # without this the user key is not transfered to the slice
81             # (as GetSlivers returns key of only enabled users),
82             # which prevents the user from login to the slice.
83             # We may do additional checks before enabling the user.
84
85             api.plshell.UpdatePerson(api.plauth, person_id, {'enabled' : True})
86             key_ids = []
87         else:
88             key_ids = persons[0]['key_ids']
89
90         api.plshell.AddPersonToSlice(api.plauth, person_dict['email'],
91                                      slicename)        
92
93         # Get this users local keys
94         keylist = api.plshell.GetKeys(api.plauth, key_ids, ['key'])
95         keys = [key['key'] for key in keylist]
96
97         # add keys that arent already there 
98         for personkey in person_dict['keys']:
99             if personkey not in keys:
100                 key = {'key_type': 'ssh', 'key': personkey}
101                 api.plshell.AddPersonKey(api.plauth, person_dict['email'], key)
102
103     # find out where this slice is currently running
104     nodelist = api.plshell.GetNodes(api.plauth, slice['node_ids'],
105                                     ['hostname'])
106     hostnames = [node['hostname'] for node in nodelist]
107
108     # remove nodes not in rspec
109     deleted_nodes = list(set(hostnames).difference(nodes))
110     # add nodes from rspec
111     added_nodes = list(set(nodes).difference(hostnames))
112
113     api.plshell.AddSliceToNodes(api.plauth, slicename, added_nodes) 
114     api.plshell.DeleteSliceFromNodes(api.plauth, slicename, deleted_nodes)
115
116     return 1
117
118 def get_rspec(api, hrn):
119     rspec = None
120     
121     if (hrn):
122         # Convert HRN to slice name
123         # Get SliceTags for the slice
124
125         # Construct LinkSpecs from the topo_rspec SliceTags
126         # The first field is the NodeId of the remote node.
127         # So the endpoints are the SliceTag node and the remote node.
128
129         # How to:
130         # - avoid duplicates?
131         # - verify both ends of the link?
132         pass
133     else:
134         # Return canned response for now...
135         r = Rspec()
136         r.parseFile(SFA_VINI_DEFAULT_RSPEC)
137         rspec = r.toxml()
138
139     return rspec
140
141
142 def create_slice(api, hrn, xml):
143     r = Rspec()
144     r.parseString(xml)
145     rspec = r.toGenDict()
146
147     # Check request against current allocations
148     # Request OK
149
150     nodes = rspec_to_nodeset(rspec)
151     create_slice_vini_aggregate(api, hrn, nodes)
152
153     # Add VINI-specific topology attributes to slice here
154
155     return True
156
157 def rspec_to_nodeset(rspec):
158     nodedict = {}
159     nodes = set()
160     try:
161         sitespecs = rspec['Rspec'][0]['Capacity'][0]['NetSpec'][0]['SiteSpec']
162         for s in sitespecs:
163             for node in s['NodeSpec']:
164                 nodedict[node['name'][0]] = node['hostname'][0]
165
166         linkspecs = rspec['Rspec'][0]['Request'][0]['NetSpec'][0]['LinkSpec']
167         for l in linkspecs:
168             for e in l['endpoint']:
169                 nodes.add(nodedict[e])
170         
171     except KeyError:
172         # Bad Rspec
173         pass
174     
175     return nodes
176
177 def main():
178     r = Rspec()
179     r.parseFile(sys.argv[1])
180     rspec = r.toGenDict()
181     create_slice(None,'plc',rspec)
182     
183 if __name__ == "__main__":
184     main()