remove origin_hrn
[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, gid_origin_caller=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     credential.set_gid_origin_caller(gid_origin_caller)
153     tickets = {}
154     for net_hrn in rspecs:    
155         try:
156             # if we are directly connected to the aggregate then we can just
157             # send them the request. if not, then we may be connected to an sm
158             # thats connected to the aggregate
159             if net_hrn in aggregates:
160                 try:
161                     ticket = aggregates[net_hrn].get_ticket(credential, slice_hrn, \
162                                 rspecs[net_hrn], None)
163                     tickets[net_hrn] = ticket
164                 except:
165                     arg_list = [credential,hrn,rspecs[net_hrn]]
166                     request_hash = api.key.compute_hash(arg_list)
167                     ticket = aggregates[net_hrn].get_ticket(credential, slice_hrn, \
168                                 rspecs[net_hrn], request_hash)
169                     tickets[net_hrn] = ticket 
170             else:
171                 # lets forward this rspec to a sm that knows about the network
172                 arg_list = [credential, net_hrn]
173                 request_hash = api.key.compute_hash(arg_list)
174                 for agg in aggregates:
175                     try:
176                         network_found = aggregates[agg].get_aggregates(credential, \
177                                                         net_hrn)
178                     except:
179                         network_found = aggregates[agg].get_aggregates(credential, \
180                                                         net_hrn, request_hash)
181                     if network_found:
182                         try:
183                             ticket = aggregates[aggregate].get_ticket(credential, \
184                                         slice_hrn, rspecs[net_hrn], None)
185                             tickets[aggregate] = ticket
186                         except:
187                             arg_list = [credential, hrn, rspecs[net_hrn]]
188                             request_hash = api.key.compute_hash(arg_list)
189                             aggregates[aggregate].get_ticket(credential, slice_hrn, \
190                                     rspecs[net_hrn], request_hash)
191                             tickets[aggregate] = ticket
192         except:
193             print >> log, "Error getting ticket for %(slice_hrn)s at aggregate %(net_hrn)s" % \
194                            locals()
195             
196     # create a new ticket
197     new_ticket = SfaTicket(subject = slice_hrn)
198     new_ticket.set_gid_caller(api.auth.client_gid)
199    
200     tmp_rspec = RSpec()
201     networks = []
202     valid_data = {} 
203     # merge data from aggregate ticket into new ticket 
204     for agg_ticket in tickets.values():
205         agg_ticket = SfaTicket(string=agg_ticket)
206         object_gid = agg_ticket.get_gid_object()
207         new_ticket.set_gid_object(object_gid)
208         new_ticket.set_issuer(key=api.key, subject=api.hrn)
209         new_ticket.set_pubkey(object_gid.get_pubkey())
210         
211         #new_ticket.set_attributes(data)
212         tmp_rspec.parseString(agg_ticket.get_rspec())
213         networks.extend([{'NetSpec': tmp_rspec.getDictsByTagName('NetSpec')}])
214     
215     #new_ticket.set_parent(api.auth.hierarchy.get_auth_ticket(auth_hrn))
216     resources = {'networks': networks, 'start_time': 0, 'duration': 0}
217     resourceDict = {'RSpec': resources}
218     tmp_rspec.parseDict(resourceDict)
219     new_ticket.set_rspec(tmp_rspec.toxml())
220         
221     new_ticket.encode()
222     new_ticket.sign()          
223     return new_ticket.save_to_string(save_parents=True)
224
225 def start_slice(api, hrn):
226     slicename = hrn_to_pl_slicename(hrn)
227     slices = api.plshell.GetSlices(api.plauth, {'name': slicename}, ['slice_id'])
228     if not slices:
229         raise RecordNotFound(hrn)
230     slice_id = slices[0]
231     attributes = api.plshell.GetSliceTags(api.plauth, {'slice_id': slice_id, 'name': 'enabled'}, ['slice_attribute_id'])
232     attribute_id = attreibutes[0]['slice_attribute_id']
233     api.plshell.UpdateSliceTag(api.plauth, attribute_id, "1" )
234
235     return 1
236  
237 def stop_slice(api, hrn):
238     slicename = hrn_to_pl_slicename(hrn)
239     slices = api.plshell.GetSlices(api.plauth, {'name': slicename}, ['slice_id'])
240     if not slices:
241         raise RecordNotFound(hrn)
242     slice_id = slices[0]['slice_id']
243     attributes = api.plshell.GetSliceTags(api.plauth, {'slice_id': slice_id, 'name': 'enabled'}, ['slice_attribute_id'])
244     attribute_id = attributes[0]['slice_attribute_id']
245     api.plshell.UpdateSliceTag(api.plauth, attribute_id, "0")
246     return 1
247
248 def reset_slice(api, hrn):
249     # XX not implemented at this interface
250     return 1
251
252 def get_slices(api):
253     # XX just import the legacy module and excute that until
254     # we transition the code to this module
255     from sfa.plc.slices import Slices
256     slices = Slices(api)
257     slices.refresh()
258     return slices['hrn']
259      
260 def get_rspec(api, hrn=None, origin_gid_caller=None):
261     from sfa.plc.nodes import Nodes
262     nodes = Nodes(api, origin_gid_caller=origin_gid_caller)
263     if hrn:
264         rspec = nodes.get_rspec(hrn)
265     else:
266         nodes.refresh()
267         rspec = nodes['rspec']
268
269     return rspec
270
271 """
272 Returns the request context required by sfatables. At some point, this mechanism should be changed
273 to refer to "contexts", which is the information that sfatables is requesting. But for now, we just
274 return the basic information needed in a dict.
275 """
276 def fetch_context(slice_hrn, user_hrn, contexts):
277     base_context = {'sfa':{'user':{'hrn':user_hrn}}}
278     return base_context
279
280 def main():
281     r = RSpec()
282     r.parseFile(sys.argv[1])
283     rspec = r.toDict()
284     create_slice(None,'plc.princeton.tmacktestslice',rspec)
285
286 if __name__ == "__main__":
287     main()
288