added support for urn name format. urn is the default name format used over the wire
[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}
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}
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, 'authority')     
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    
141     tmp_rspec = RSpec()
142     networks = []
143     valid_data = {} 
144     # merge data from aggregate ticket into new ticket 
145     for agg_ticket in tickets.values():
146         agg_ticket = SfaTicket(string=agg_ticket)
147         object_gid = agg_ticket.get_gid_object()
148         new_ticket.set_gid_object(object_gid)
149         new_ticket.set_issuer(key=api.key, subject=api.hrn)
150         new_ticket.set_pubkey(object_gid.get_pubkey())
151         
152         #new_ticket.set_attributes(data)
153         tmp_rspec.parseString(agg_ticket.get_rspec())
154         networks.extend([{'NetSpec': tmp_rspec.getDictsByTagName('NetSpec')}])
155     
156     #new_ticket.set_parent(api.auth.hierarchy.get_auth_ticket(auth_hrn))
157     resources = {'networks': networks, 'start_time': 0, 'duration': 0}
158     resourceDict = {'RSpec': resources}
159     tmp_rspec.parseDict(resourceDict)
160     new_ticket.set_rspec(tmp_rspec.toxml())
161         
162     new_ticket.encode()
163     new_ticket.sign()          
164     return new_ticket.save_to_string(save_parents=True)
165
166 def start_slice(api, xrn):
167     hrn, type = urn_to_hrn(xrn)
168     slicename = hrn_to_pl_slicename(hrn)
169     slices = api.plshell.GetSlices(api.plauth, {'name': slicename}, ['slice_id'])
170     if not slices:
171         raise RecordNotFound(hrn)
172     slice_id = slices[0]
173     attributes = api.plshell.GetSliceTags(api.plauth, {'slice_id': slice_id, 'name': 'enabled'}, ['slice_attribute_id'])
174     attribute_id = attreibutes[0]['slice_attribute_id']
175     api.plshell.UpdateSliceTag(api.plauth, attribute_id, "1" )
176
177     return 1
178  
179 def stop_slice(api, xrn):
180     hrn, type = urn_to_hrn(xrn)
181     slicename = hrn_to_pl_slicename(hrn)
182     slices = api.plshell.GetSlices(api.plauth, {'name': slicename}, ['slice_id'])
183     if not slices:
184         raise RecordNotFound(hrn)
185     slice_id = slices[0]['slice_id']
186     attributes = api.plshell.GetSliceTags(api.plauth, {'slice_id': slice_id, 'name': 'enabled'}, ['slice_attribute_id'])
187     attribute_id = attributes[0]['slice_attribute_id']
188     api.plshell.UpdateSliceTag(api.plauth, attribute_id, "0")
189     return 1
190
191 def reset_slice(api, xrn):
192     # XX not implemented at this interface
193     return 1
194
195 def get_slices(api):
196     # XX just import the legacy module and excute that until
197     # we transition the code to this module
198     from sfa.plc.slices import Slices
199     slices = Slices(api)
200     slices.refresh()
201     return [hrn_to_urn(slice_hrn, 'slice') for slice_hrn in slices['hrn']]
202      
203 def get_rspec(api, xrn=None, origin_hrn=None):
204     
205     from sfa.plc.nodes import Nodes
206     nodes = Nodes(api, origin_hrn=origin_hrn)
207     if hrn:
208         rspec = nodes.get_rspec(xrn)
209     else:
210         nodes.refresh()
211         rspec = nodes['rspec']
212
213     return rspec
214
215 """
216 Returns the request context required by sfatables. At some point, this mechanism should be changed
217 to refer to "contexts", which is the information that sfatables is requesting. But for now, we just
218 return the basic information needed in a dict.
219 """
220 def fetch_context(slice_hrn, user_hrn, contexts):
221     slice_hrn = urn_to_hrn(slice_xrn)[0]
222     user_hrn = urn_to_hrn(user_xrn)[0]
223     base_context = {'sfa':{'user':{'hrn':user_hrn}}}
224     return base_context
225
226 def main():
227     r = RSpec()
228     r.parseFile(sys.argv[1])
229     rspec = r.toDict()
230     create_slice(None,'plc.princeton.tmacktestslice',rspec)
231
232 if __name__ == "__main__":
233     main()
234