in create_slice() and delete_slice() set the right gid_object_caller on the credentia...
[sfa.git] / sfa / managers / slice_manager_pl.py
1 ### $Id: slices.py 15842 2009-11-22 09:56:13Z anil $
2 ### $URL: https://svn.planet-lab.org/svn/sfa/trunk/sfa/plc/slices.py $
3
4 import datetime
5 import time
6 import traceback
7 import sys
8
9 from types import StringTypes
10 from sfa.util.misc import *
11 from sfa.util.rspec import *
12 from sfa.util.specdict import *
13 from sfa.util.faults import *
14 from sfa.util.record import GeniRecord
15 from sfa.util.policy import Policy
16 from sfa.util.prefixTree import prefixTree
17 from sfa.util.rspec import *
18 from sfa.util.sfaticket import *
19 from sfa.util.debug import log
20 from sfa.server.registry import Registries
21 from sfa.server.aggregate import Aggregates
22 import sfa.plc.peers as peers
23
24 def delete_slice(api, hrn, gid_origin_caller=None):
25     credential = api.getCredential()
26     credential.set_gid_origin_caller(gid_origin_caller)
27     aggregates = Aggregates(api)
28     for aggregate in aggregates:
29         success = False
30         # request hash is optional so lets try the call without it
31         try:
32             request_hash=None
33             aggregates[aggregate].delete_slice(credential, hrn, request_hash, origin_hrn)
34             success = True
35         except:
36             print >> log, "%s" % (traceback.format_exc())
37             print >> log, "Error calling delete slice at aggregate %s" % aggregate
38
39         # try sending the request hash if the previous call failed
40         if not success:
41             try:
42                 arg_list = [credential, hrn]
43                 request_hash = api.key.compute_hash(arg_list)
44                 aggregates[aggregate].delete_slice(credential, hrn, request_hash)
45                 success = True
46             except:
47                 print >> log, "%s" % (traceback.format_exc())
48                 print >> log, "Error calling list nodes at aggregate %s" % aggregate
49     return 1
50
51 def create_slice(api, hrn, rspec, gid_origin_caller=None):
52     spec = RSpec()
53     tempspec = RSpec()
54     spec.parseString(rspec)
55     slicename = hrn_to_pl_slicename(hrn)
56     specDict = spec.toDict()
57     if specDict.has_key('RSpec'): specDict = specDict['RSpec']
58     if specDict.has_key('start_time'): start_time = specDict['start_time']
59     else: start_time = 0
60     if specDict.has_key('end_time'): end_time = specDict['end_time']
61     else: end_time = 0
62
63     rspecs = {}
64     aggregates = Aggregates(api)
65     credential = api.getCredential()
66     credential.set_gid_origin_caller(gid_origin_caller)
67     # split the netspecs into individual rspecs
68     netspecs = spec.getDictsByTagName('NetSpec')
69     for netspec in netspecs:
70         net_hrn = netspec['name']
71         resources = {'start_time': start_time, 'end_time': end_time, 'networks': netspec}
72         resourceDict = {'RSpec': resources}
73         tempspec.parseDict(resourceDict)
74         rspecs[net_hrn] = tempspec.toxml()
75
76     #print "rspecs:", rspecs.keys()
77     #print "aggregates:", aggregates.keys() 
78     # send each rspec to the appropriate aggregate/sm
79     for net_hrn in rspecs:
80         try:
81             # if we are directly connected to the aggregate then we can just 
82             # send them the rspec. if not, then we may be connected to an sm 
83             # thats connected to the aggregate
84             if net_hrn in aggregates:
85                 # send the whloe rspec to the local aggregate
86                 if net_hrn in [api.hrn]:
87                     try:
88                         request_hash = None
89                         aggregates[net_hrn].create_slice(credential, hrn, \
90                                         rspec, request_hash)
91                     except:
92                         arg_list = [credential,hrn,rspec]
93                         request_hash = api.key.compute_hash(arg_list)
94                         aggregates[net_hrn].create_slice(credential, hrn, \
95                                         rspec, request_hash)
96                 else:
97                     try:
98                         request_hash = None
99                         aggregates[net_hrn].create_slice(credential, hrn, \
100                                 rspecs[net_hrn], request_hash)
101                     except:
102                         arg_list = [credential,hrn,rspecs[net_hrn]]
103                         request_hash = api.key.compute_hash(arg_list)
104                         aggregates[net_hrn].create_slice(credential, hrn, \
105                                 rspecs[net_hrn], request_hash)
106             else:
107                 # lets forward this rspec to a sm that knows about the network
108                 arg_list = [credential, net_hrn]
109                 request_hash = api.key.compute_hash(arg_list)
110                 for aggregate in aggregates:
111                     try:
112                         network_found = aggregates[aggregate].get_aggregates(credential, net_hrn)
113                     except:
114                         network_found = aggregates[aggregate].get_aggregates(credential, net_hrn, request_hash)
115                     if network_found:
116                         try:
117                             request_hash = None
118                             aggregates[aggregate].create_slice(credential, hrn, \
119                                     rspecs[net_hrn], request_hash, origin_hrn)
120                         except:
121                             arg_list = [credential, hrn, rspecs[net_hrn]]
122                             request_hash = api.key.compute_hash(arg_list)
123                             aggregates[aggregate].create_slice(credential, hrn, \
124                                     rspecs[net_hrn], request_hash, origin_hrn)
125
126         except:
127             print >> log, "Error creating slice %(hrn)s at aggregate %(net_hrn)s" % \
128                            locals()
129             traceback.print_exc()
130     return 1
131
132 def get_ticket(api, slice_hrn, rspec, origin_hrn=None):
133     
134     # get the netspecs contained within the clients rspec
135     client_rspec = RSpec(xml=rspec)
136     netspecs = client_rspec.getDictsByTagName('NetSpec')
137     
138     # create an rspec for each individual rspec 
139     rspecs = {}
140     temp_rspec = RSpec()
141     for netspec in netspecs:
142         net_hrn = netspec['name']
143         resources = {'start_time': 0, 'end_time': 0 , 
144                      'network': netspec}
145         resourceDict = {'RSpec': resources}
146         temp_rspec.parseDict(resourceDict)
147         rspecs[net_hrn] = temp_rspec.toxml() 
148     
149     # send the rspec to the appropiate aggregate/sm
150     aggregates = Aggregates(api)
151     credential = api.getCredential()
152     tickets = {}
153     for net_hrn in rspecs:    
154         try:
155             # if we are directly connected to the aggregate then we can just
156             # send them the request. if not, then we may be connected to an sm
157             # thats connected to the aggregate
158             if net_hrn in aggregates:
159                 try:
160                     ticket = aggregates[net_hrn].get_ticket(credential, slice_hrn, \
161                                 rspecs[net_hrn], None, origin_hrn)
162                     tickets[net_hrn] = ticket
163                 except:
164                     arg_list = [credential,hrn,rspecs[net_hrn]]
165                     request_hash = api.key.compute_hash(arg_list)
166                     ticket = aggregates[net_hrn].get_ticket(credential, slice_hrn, \
167                                 rspecs[net_hrn], request_hash, origin_hrn)
168                     tickets[net_hrn] = ticket 
169             else:
170                 # lets forward this rspec to a sm that knows about the network
171                 arg_list = [credential, net_hrn]
172                 request_hash = api.key.compute_hash(arg_list)
173                 for agg in aggregates:
174                     try:
175                         network_found = aggregates[agg].get_aggregates(credential, \
176                                                         net_hrn)
177                     except:
178                         network_found = aggregates[agg].get_aggregates(credential, \
179                                                         net_hrn, request_hash)
180                     if network_found:
181                         try:
182                             ticket = aggregates[aggregate].get_ticket(credential, \
183                                         slice_hrn, rspecs[net_hrn], None, origin_hrn)
184                             tickets[aggregate] = ticket
185                         except:
186                             arg_list = [credential, hrn, rspecs[net_hrn]]
187                             request_hash = api.key.compute_hash(arg_list)
188                             aggregates[aggregate].get_ticket(credential, slice_hrn, \
189                                     rspecs[net_hrn], request_hash, origin_hrn)
190                             tickets[aggregate] = ticket
191         except:
192             print >> log, "Error getting ticket for %(slice_hrn)s at aggregate %(net_hrn)s" % \
193                            locals()
194             
195     # create a new ticket
196     new_ticket = SfaTicket(subject = slice_hrn)
197     new_ticket.set_gid_caller(api.auth.client_gid)
198    
199     tmp_rspec = RSpec()
200     networks = []
201     valid_data = {} 
202     # merge data from aggregate ticket into new ticket 
203     for agg_ticket in tickets.values():
204         agg_ticket = SfaTicket(string=agg_ticket)
205         object_gid = agg_ticket.get_gid_object()
206         new_ticket.set_gid_object(object_gid)
207         new_ticket.set_issuer(key=api.key, subject=api.hrn)
208         new_ticket.set_pubkey(object_gid.get_pubkey())
209         
210         #new_ticket.set_attributes(data)
211         tmp_rspec.parseString(agg_ticket.get_rspec())
212         networks.extend([{'NetSpec': tmp_rspec.getDictsByTagName('NetSpec')}])
213     
214     #new_ticket.set_parent(api.auth.hierarchy.get_auth_ticket(auth_hrn))
215     resources = {'networks': networks, 'start_time': 0, 'duration': 0}
216     resourceDict = {'RSpec': resources}
217     tmp_rspec.parseDict(resourceDict)
218     new_ticket.set_rspec(tmp_rspec.toxml())
219         
220     new_ticket.encode()
221     new_ticket.sign()          
222     return new_ticket.save_to_string(save_parents=True)
223
224 def start_slice(api, hrn, origin_hrn=None):
225     slicename = hrn_to_pl_slicename(hrn)
226     slices = api.plshell.GetSlices(api.plauth, {'name': slicename}, ['slice_id'])
227     if not slices:
228         raise RecordNotFound(hrn)
229     slice_id = slices[0]
230     attributes = api.plshell.GetSliceTags(api.plauth, {'slice_id': slice_id, 'name': 'enabled'}, ['slice_attribute_id'])
231     attribute_id = attreibutes[0]['slice_attribute_id']
232     api.plshell.UpdateSliceTag(api.plauth, attribute_id, "1" )
233
234     return 1
235  
236 def stop_slice(api, hrn, origin_hrn):
237     slicename = hrn_to_pl_slicename(hrn)
238     slices = api.plshell.GetSlices(api.plauth, {'name': slicename}, ['slice_id'])
239     if not slices:
240         raise RecordNotFound(hrn)
241     slice_id = slices[0]['slice_id']
242     attributes = api.plshell.GetSliceTags(api.plauth, {'slice_id': slice_id, 'name': 'enabled'}, ['slice_attribute_id'])
243     attribute_id = attributes[0]['slice_attribute_id']
244     api.plshell.UpdateSliceTag(api.plauth, attribute_id, "0")
245     return 1
246
247 def reset_slice(api, hrn, origin_hrn):
248     # XX not implemented at this interface
249     return 1
250
251 def get_slices(api):
252     # XX just import the legacy module and excute that until
253     # we transition the code to this module
254     from sfa.plc.slices import Slices
255     slices = Slices(api)
256     slices.refresh()
257     return slices['hrn']
258      
259 def get_rspec(api, hrn=None, origin_gid_caller=None):
260     from sfa.plc.nodes import Nodes
261     nodes = Nodes(api, origin_gid_caller=origin_gid_caller)
262     if hrn:
263         rspec = nodes.get_rspec(hrn)
264     else:
265         nodes.refresh()
266         rspec = nodes['rspec']
267
268     return rspec
269
270 """
271 Returns the request context required by sfatables. At some point, this mechanism should be changed
272 to refer to "contexts", which is the information that sfatables is requesting. But for now, we just
273 return the basic information needed in a dict.
274 """
275 def fetch_context(slice_hrn, user_hrn, contexts):
276     base_context = {'sfa':{'user':{'hrn':user_hrn}}}
277     return base_context
278
279 def main():
280     r = RSpec()
281     r.parseFile(sys.argv[1])
282     rspec = r.toDict()
283     create_slice(None,'plc.princeton.tmacktestslice',rspec)
284
285 if __name__ == "__main__":
286     main()
287