to avoid NoneType object is not iterable error
[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.namespace 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 SfaRecord
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, xrn, 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             aggregates[aggregate].delete_slice(credential, xrn, origin_hrn)
32             success = True
33         except:
34             print >> log, "%s" % (traceback.format_exc())
35             print >> log, "Error calling delete slice at aggregate %s" % aggregate
36     return 1
37
38 def create_slice(api, xrn, rspec, origin_hrn=None):
39     hrn, type = urn_to_hrn(xrn)
40     spec = RSpec()
41     tempspec = RSpec()
42     spec.parseString(rspec)
43     slicename = hrn_to_pl_slicename(hrn)
44     specDict = spec.toDict()
45     if specDict.has_key('RSpec'): specDict = specDict['RSpec']
46     if specDict.has_key('start_time'): start_time = specDict['start_time']
47     else: start_time = 0
48     if specDict.has_key('end_time'): end_time = specDict['end_time']
49     else: end_time = 0
50
51     rspecs = {}
52     aggregates = Aggregates(api)
53     credential = api.getCredential()
54     # split the netspecs into individual rspecs
55     netspecs = spec.getDictsByTagName('NetSpec')
56     for netspec in netspecs:
57         net_hrn = netspec['name']
58         resources = {'start_time': start_time, 'end_time': end_time, 'networks': {'NetSpec' : netspec}}
59         resourceDict = {'RSpec': resources}
60         tempspec.parseDict(resourceDict)
61         rspecs[net_hrn] = tempspec.toxml()
62     
63     #print "rspecs:", rspecs.keys()
64     #print "aggregates:", aggregates.keys() 
65     # send each rspec to the appropriate aggregate/sm
66     for net_hrn in rspecs:
67         net_urn = hrn_to_urn(net_hrn, 'authority')
68         try:
69             # if we are directly connected to the aggregate then we can just 
70             # send them the rspec. if not, then we may be connected to an sm 
71             # thats connected to the aggregate
72             if net_hrn in aggregates:
73                 # send the whloe rspec to the local aggregate
74                 if net_hrn in [api.hrn]:
75                     aggregates[net_hrn].create_slice(credential, xrn, rspec, \
76                                 origin_hrn)
77                 else:
78                     aggregates[net_hrn].create_slice(credential, xrn, \
79                                 rspecs[net_hrn], origin_hrn)
80             else:
81                 # lets forward this rspec to a sm that knows about the network
82                 for aggregate in aggregates:
83                     network_found = aggregates[aggregate].get_aggregates(credential, net_hrn)
84                     if network_found:
85                         aggregates[aggregate].create_slice(credential, xrn, \
86                                     rspecs[net_hrn], origin_hrn)
87
88         except:
89             print >> log, "Error creating slice %(hrn)s at aggregate %(net_hrn)s" % \
90                            locals()
91             traceback.print_exc()
92     return 1
93
94 def get_ticket(api, xrn, rspec, origin_hrn=None):
95     slice_hrn, type = urn_to_hrn(xrn)
96     # get the netspecs contained within the clients rspec
97     client_rspec = RSpec(xml=rspec)
98     netspecs = client_rspec.getDictsByTagName('NetSpec')
99     
100     # create an rspec for each individual rspec 
101     rspecs = {}
102     temp_rspec = RSpec()
103     for netspec in netspecs:
104         net_hrn = netspec['name']
105         resources = {'start_time': 0, 'end_time': 0 , 
106                      'network': {'NetSpec' : netspec}}
107         resourceDict = {'RSpec': resources}
108         temp_rspec.parseDict(resourceDict)
109         rspecs[net_hrn] = temp_rspec.toxml() 
110     
111     # send the rspec to the appropiate aggregate/sm
112     aggregates = Aggregates(api)
113     credential = api.getCredential()
114     tickets = {}
115     for net_hrn in rspecs:
116         net_urn = urn_to_hrn(net_hrn)     
117         try:
118             # if we are directly connected to the aggregate then we can just
119             # send them the request. if not, then we may be connected to an sm
120             # thats connected to the aggregate
121             if net_hrn in aggregates:
122                 ticket = aggregates[net_hrn].get_ticket(credential, xrn, \
123                             rspecs[net_hrn], origin_hrn)
124                 tickets[net_hrn] = ticket
125             else:
126                 # lets forward this rspec to a sm that knows about the network
127                 for agg in aggregates:
128                     network_found = aggregates[agg].get_aggregates(credential, net_urn)
129                     if network_found:
130                         ticket = aggregates[aggregate].get_ticket(credential, \
131                                         slice_hrn, rspecs[net_hrn], origin_hrn)
132                         tickets[aggregate] = ticket
133         except:
134             print >> log, "Error getting ticket for %(slice_hrn)s at aggregate %(net_hrn)s" % \
135                            locals()
136             
137     # create a new ticket
138     new_ticket = SfaTicket(subject = slice_hrn)
139     new_ticket.set_gid_caller(api.auth.client_gid)
140     new_ticket.set_issuer(key=api.key, subject=api.hrn)
141    
142     tmp_rspec = RSpec()
143     networks = []
144     valid_data = {
145         'timestamp': int(time.time()),
146         'initscripts': [],
147         'slivers': [] 
148     } 
149     # merge data from aggregate ticket into new ticket 
150     for agg_ticket in tickets.values():
151         # get data from this ticket
152         agg_ticket = SfaTicket(string=agg_ticket)
153         attributes = agg_ticket.get_attributes()
154         if attributes.get('initscripts', []) != None:
155             valid_data['initscripts'].extend(attributes.get('initscripts', []))
156         if attributes.get('slivers', []) != None:
157             valid_data['slivers'].extend(attributes.get('slivers', []))
158  
159         # set the object gid
160         object_gid = agg_ticket.get_gid_object()
161         new_ticket.set_gid_object(object_gid)
162         new_ticket.set_pubkey(object_gid.get_pubkey())
163
164         # build the rspec
165         tmp_rspec.parseString(agg_ticket.get_rspec())
166         networks.extend([{'NetSpec': tmp_rspec.getDictsByTagName('NetSpec')}])
167     
168     #new_ticket.set_parent(api.auth.hierarchy.get_auth_ticket(auth_hrn))
169     new_ticket.set_attributes(valid_data)
170     resources = {'networks': networks, 'start_time': 0, 'duration': 0}
171     resourceDict = {'RSpec': resources}
172     tmp_rspec.parseDict(resourceDict)
173     new_ticket.set_rspec(tmp_rspec.toxml())
174     new_ticket.encode()
175     new_ticket.sign()          
176     return new_ticket.save_to_string(save_parents=True)
177
178 def start_slice(api, xrn):
179     hrn, type = urn_to_hrn(xrn)
180     slicename = hrn_to_pl_slicename(hrn)
181     slices = api.plshell.GetSlices(api.plauth, {'name': slicename}, ['slice_id'])
182     if not slices:
183         raise RecordNotFound(hrn)
184     slice_id = slices[0]
185     attributes = api.plshell.GetSliceTags(api.plauth, {'slice_id': slice_id, 'name': 'enabled'}, ['slice_attribute_id'])
186     attribute_id = attreibutes[0]['slice_attribute_id']
187     api.plshell.UpdateSliceTag(api.plauth, attribute_id, "1" )
188
189     return 1
190  
191 def stop_slice(api, xrn):
192     hrn, type = urn_to_hrn(xrn)
193     slicename = hrn_to_pl_slicename(hrn)
194     slices = api.plshell.GetSlices(api.plauth, {'name': slicename}, ['slice_id'])
195     if not slices:
196         raise RecordNotFound(hrn)
197     slice_id = slices[0]['slice_id']
198     attributes = api.plshell.GetSliceTags(api.plauth, {'slice_id': slice_id, 'name': 'enabled'}, ['slice_attribute_id'])
199     attribute_id = attributes[0]['slice_attribute_id']
200     api.plshell.UpdateSliceTag(api.plauth, attribute_id, "0")
201     return 1
202
203 def reset_slice(api, xrn):
204     # XX not implemented at this interface
205     return 1
206
207 def get_slices(api):
208     # XX just import the legacy module and excute that until
209     # we transition the code to this module
210     from sfa.plc.slices import Slices
211     slices = Slices(api)
212     slices.refresh()
213     return [hrn_to_urn(slice_hrn, 'slice') for slice_hrn in slices['hrn']]
214      
215 def get_rspec(api, xrn=None, origin_hrn=None):
216     
217     from sfa.plc.nodes import Nodes
218     nodes = Nodes(api, origin_hrn=origin_hrn)
219     if xrn:
220         rspec = nodes.get_rspec(xrn)
221     else:
222         nodes.refresh()
223         rspec = nodes['rspec']
224
225     return rspec
226
227 """
228 Returns the request context required by sfatables. At some point, this mechanism should be changed
229 to refer to "contexts", which is the information that sfatables is requesting. But for now, we just
230 return the basic information needed in a dict.
231 """
232 def fetch_context(slice_hrn, user_hrn, contexts):
233     #slice_hrn = urn_to_hrn(slice_xrn)[0]
234     #user_hrn = urn_to_hrn(user_xrn)[0]
235     base_context = {'sfa':{'user':{'hrn':user_hrn}}}
236     return base_context
237
238 def main():
239     r = RSpec()
240     r.parseFile(sys.argv[1])
241     rspec = r.toDict()
242     create_slice(None,'plc.princeton.tmacktestslice',rspec)
243
244 if __name__ == "__main__":
245     main()
246