'sfi resources' appears to work
[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         # get the list of valid slice users from the registry and make 
59         # they are added to the slice 
60         researchers = record.get('researcher', [])
61         for researcher in researchers:
62             person_record = {}
63             person_records = registry.resolve(credential, researcher)
64             for record in person_records:
65                 if record.get_type() in ['user']:
66                     person_record = record
67             if not person_record:
68                 pass
69             person_dict = person_record.as_dict()
70             persons = api.plshell.GetPersons(api.plauth, [person_dict['email']], ['person_id', 'key_ids'])
71
72             # Create the person record 
73             if not persons:
74                 person_id=api.plshell.AddPerson(api.plauth, person_dict)
75
76                 # The line below enables the user account on the remote aggregate soon after it is created.
77                 # without this the user key is not transfered to the slice (as GetSlivers returns key of only enabled users),
78                 # which prevents the user from login to the slice. We may do additional checks before enabling the user.
79
80                 api.plshell.UpdatePerson(api.plauth, person_id, {'enabled' : True})
81                 key_ids = []
82             else:
83                 key_ids = persons[0]['key_ids']
84
85             api.plshell.AddPersonToSlice(api.plauth, person_dict['email'], slicename)        
86
87             # Get this users local keys
88             keylist = api.plshell.GetKeys(api.plauth, key_ids, ['key'])
89             keys = [key['key'] for key in keylist]
90
91             # add keys that arent already there 
92             for personkey in person_dict['keys']:
93                 if personkey not in keys:
94                     key = {'key_type': 'ssh', 'key': personkey}
95                     api.plshell.AddPersonKey(api.plauth, person_dict['email'], key)
96
97         # find out where this slice is currently running
98         nodelist = api.plshell.GetNodes(api.plauth, slice['node_ids'], ['hostname'])
99         hostnames = [node['hostname'] for node in nodelist]
100
101         # remove nodes not in rspec
102         deleted_nodes = list(set(hostnames).difference(nodes))
103         # add nodes from rspec
104         added_nodes = list(set(nodes).difference(hostnames))
105
106         api.plshell.AddSliceToNodes(api.plauth, slicename, added_nodes) 
107         api.plshell.DeleteSliceFromNodes(api.plauth, slicename, deleted_nodes)
108
109         return 1
110
111
112 def get_rspec(api, hrn):
113     rspec = None
114     
115     if (hrn):
116         # Convert HRN to slice name
117         # Get SliceTags for the slice
118
119         # Construct LinkSpecs from the topo_rspec SliceTags
120         # The first field is the NodeId of the remote node.
121         # So the endpoints are the SliceTag node and the remote node.
122
123         # How to:
124         # - avoid duplicates?
125         # - verify both ends of the link?
126         pass
127     else:
128         # Return canned response for now...
129         r = Rspec()
130         r.parseFile(SFA_VINI_DEFAULT_RSPEC)
131         rspec = r.toxml()
132
133     return rspec
134
135
136 def create_slice(api, hrn, xml):
137     r = Rspec()
138     r.parseString(xml)
139     rspec = r.toGenDict()
140
141     # Check request against current allocations
142     # Request OK
143
144     nodes = rspec_to_nodeset(rspec)
145     create_slice_vini_aggregate(api, hrn, nodes)
146
147     # Add VINI-specific topology attributes to slice here
148
149     return True
150
151 def rspec_to_nodeset(rspec):
152     nodedict = {}
153     nodes = set()
154     try:
155         sitespecs = rspec['Rspec'][0]['Capacity'][0]['NetSpec'][0]['SiteSpec']
156         for s in sitespecs:
157             for node in s['NodeSpec']:
158                 nodedict[node['name'][0]] = node['hostname'][0]
159
160         linkspecs = rspec['Rspec'][0]['Request'][0]['NetSpec'][0]['LinkSpec']
161         for l in linkspecs:
162             for e in l['endpoint']:
163                 nodes.add(nodedict[e])
164         
165     except KeyError:
166         # Bad Rspec
167         pass
168
169     return nodes
170
171 def main():
172     r = Rspec()
173     r.parseFile(sys.argv[1])
174     rspec = r.toGenDict()
175     create_slice(None,'plc',rspec)
176     
177 if __name__ == "__main__":
178     main()