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