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