Modify module paths
[sfa.git] / sfa / managers / aggregate_manager_vini.py
1 from sfa.util.faults import *
2 from sfa.util.namespace import *
3 from sfa.server.registry import Registries
4 from sfa.plc.nodes import *
5 from sfa.plc.api import *
6 from sfa.managers.vini.utils import *
7 import sys
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
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['type'] in ['slice']:
21             slice = record
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 = site_records[0]
40                 
41             # add the site
42             site.pop('site_id')
43             site_id = api.plshell.AddSite(api.plauth, site)
44         else:
45             site = sites[0]
46             
47         slice_fields = {}
48         slice_keys = ['name', 'url', 'description']
49         for key in slice_keys:
50             if key in slice and slice[key]:
51                 slice_fields[key] = slice[key]  
52         api.plshell.AddSlice(api.plauth, slice_fields)
53         slice = slice_fields
54         slice['node_ids'] = 0
55     else:
56         slice = slices[0]    
57
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['type'] in ['user']:
66                 person_record = record
67         if not person_record:
68             pass
69         person_dict = person_record
70         persons = api.plshell.GetPersons(api.plauth, [person_dict['email']],
71                                          ['person_id', 'key_ids'])
72
73         # Create the person record 
74         if not persons:
75             person_id=api.plshell.AddPerson(api.plauth, person_dict)
76
77             # The line below enables the user account on the remote aggregate
78             # soon after it is created.
79             # without this the user key is not transfered to the slice
80             # (as GetSlivers returns key of only enabled users),
81             # which prevents the user from login to the slice.
82             # We may do additional checks before enabling the user.
83
84             api.plshell.UpdatePerson(api.plauth, person_id, {'enabled' : True})
85             key_ids = []
86         else:
87             key_ids = persons[0]['key_ids']
88
89         api.plshell.AddPersonToSlice(api.plauth, person_dict['email'],
90                                      slicename)        
91
92         # Get this users local keys
93         keylist = api.plshell.GetKeys(api.plauth, key_ids, ['key'])
94         keys = [key['key'] for key in keylist]
95
96         # add keys that arent already there 
97         for personkey in person_dict['keys']:
98             if personkey not in keys:
99                 key = {'key_type': 'ssh', 'key': personkey}
100                 api.plshell.AddPersonKey(api.plauth, person_dict['email'], key)
101
102     # find out where this slice is currently running
103     nodelist = api.plshell.GetNodes(api.plauth, slice['node_ids'],
104                                     ['hostname'])
105     hostnames = [node['hostname'] for node in nodelist]
106
107     # remove nodes not in rspec
108     deleted_nodes = list(set(hostnames).difference(nodes))
109     # add nodes from rspec
110     added_nodes = list(set(nodes).difference(hostnames))
111
112     """
113     print >> sys.stderr, "Slice on nodes:"
114     for n in hostnames:
115         print >> sys.stderr, n
116     print >> sys.stderr, "Wants nodes:"
117     for n in nodes:
118         print >> sys.stderr, n
119     print >> sys.stderr, "Deleting nodes:"
120     for n in deleted_nodes:
121         print >> sys.stderr, n
122     print >> sys.stderr, "Adding nodes:"
123     for n in added_nodes:
124         print >> sys.stderr, n
125     """
126
127     api.plshell.AddSliceToNodes(api.plauth, slicename, added_nodes) 
128     api.plshell.DeleteSliceFromNodes(api.plauth, slicename, deleted_nodes)
129
130     return 1
131
132 def get_rspec(api, xrn, origin_hrn):
133     hrn = urn_to_hrn(xrn)[0]
134     topo = Topology(api)      
135     if (hrn):
136         slicename = hrn_to_pl_slicename(hrn)
137         slice = get_slice(api, slicename)
138         if slice:
139             slice.hrn = hrn
140             topo.nodeTopoFromSliceTags(slice)
141         else:
142             # call the default sfa.plc.nodes.get_rspec() method
143             return Nodes(api).get_rspec(hrn)     
144
145     return topo.toxml(hrn)
146
147
148
149 """
150 Hook called via 'sfi.py create'
151 """
152 def create_slice(api, xrn, xml):
153     hrn = urn_to_hrn(xrn)[0]
154     topo = Topology(api)
155     topo.nodeTopoFromRSpec(xml)
156
157     # Check request against current allocations
158     topo.verifyNodeTopo(hrn, topo)
159     
160     nodes = topo.nodesInTopo()
161     hostnames = []
162     for node in nodes:
163         hostnames.append(node.hostname)
164     create_slice_vini_aggregate(api, hrn, hostnames)
165
166     slicename = hrn_to_pl_slicename(hrn)
167     slice = get_slice(api, slicename)
168     if slice:
169         topo.updateSliceTags(slice)    
170
171     # print topo.toxml(hrn)
172
173     return True
174
175 """
176 Returns the request context required by sfatables. At some point, this mechanism should be changed
177 to refer to "contexts", which is the information that sfatables is requesting. But for now, we just
178 return the basic information needed in a dict.
179 """
180 def fetch_context(slice_hrn, user_hrn, contexts):
181     base_context = {'sfa':{'user':{'hrn':user_hrn},
182                            'slice':{'hrn':slice_hrn}}}
183     return base_context
184
185 def main():
186     api = SfaAPI()
187     #rspec = get_rspec(api, "plc.princeton.iias", None)
188     #print rspec
189     f = open(sys.argv[1])
190     xml = f.read()
191     f.close()
192     create_slice(api, "plc.princeton.iias", xml)
193
194 if __name__ == "__main__":
195     main()