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 $
8 from copy import deepcopy
10 from StringIO import StringIO
11 from types import StringTypes
13 from sfa.util.namespace import *
14 from sfa.util.rspec import *
15 from sfa.util.specdict import *
16 from sfa.util.faults import *
17 from sfa.util.record import SfaRecord
18 from sfa.util.policy import Policy
19 from sfa.util.prefixTree import prefixTree
20 from sfa.util.rspec import *
21 from sfa.util.sfaticket import *
22 from sfa.util.debug import log
23 from sfa.server.registry import Registries
24 from sfa.server.aggregate import Aggregates
25 import sfa.plc.peers as peers
27 def delete_slice(api, xrn, origin_hrn=None):
28 credential = api.getCredential()
29 aggregates = Aggregates(api)
30 for aggregate in aggregates:
32 # request hash is optional so lets try the call without it
34 aggregates[aggregate].delete_slice(credential, xrn, origin_hrn)
37 print >> log, "%s" % (traceback.format_exc())
38 print >> log, "Error calling delete slice at aggregate %s" % aggregate
41 def create_slice(api, xrn, rspec, origin_hrn=None):
42 hrn, type = urn_to_hrn(xrn)
44 # Validate the RSpec against PlanetLab's schema --disabled for now
45 # The schema used here needs to aggregate the PL and VINI schemas
46 # schema = "/var/www/html/schemas/pl.rng"
50 tree = etree.parse(StringIO(rspec))
51 except etree.XMLSyntaxError:
52 message = str(sys.exc_info()[1])
53 raise InvalidRSpec(message)
55 relaxng_doc = etree.parse(schema)
56 relaxng = etree.RelaxNG(relaxng_doc)
59 error = relaxng.error_log.last_error
60 message = "%s (line %s)" % (error.message, error.line)
61 raise InvalidRSpec(message)
63 aggs = Aggregates(api)
64 cred = api.getCredential()
66 if agg not in [api.auth.client_cred.get_gid_caller().get_hrn()]:
68 # Just send entire RSpec to each aggregate
69 aggs[agg].create_slice(cred, xrn, rspec, origin_hrn)
71 print >> log, "Error creating slice %s at %s" % (hrn, agg)
76 def get_ticket(api, xrn, rspec, origin_hrn=None):
77 slice_hrn, type = urn_to_hrn(xrn)
78 # get the netspecs contained within the clients rspec
79 client_rspec = RSpec(xml=rspec)
80 netspecs = client_rspec.getDictsByTagName('NetSpec')
82 # create an rspec for each individual rspec
85 for netspec in netspecs:
86 net_hrn = netspec['name']
87 resources = {'start_time': 0, 'end_time': 0 ,
88 'network': {'NetSpec' : netspec}}
89 resourceDict = {'RSpec': resources}
90 temp_rspec.parseDict(resourceDict)
91 rspecs[net_hrn] = temp_rspec.toxml()
93 # send the rspec to the appropiate aggregate/sm
94 aggregates = Aggregates(api)
95 credential = api.getCredential()
97 for net_hrn in rspecs:
98 net_urn = urn_to_hrn(net_hrn)
100 # if we are directly connected to the aggregate then we can just
101 # send them the request. if not, then we may be connected to an sm
102 # thats connected to the aggregate
103 if net_hrn in aggregates:
104 ticket = aggregates[net_hrn].get_ticket(credential, xrn, \
105 rspecs[net_hrn], origin_hrn)
106 tickets[net_hrn] = ticket
108 # lets forward this rspec to a sm that knows about the network
109 for agg in aggregates:
110 network_found = aggregates[agg].get_aggregates(credential, net_urn)
112 ticket = aggregates[aggregate].get_ticket(credential, \
113 slice_hrn, rspecs[net_hrn], origin_hrn)
114 tickets[aggregate] = ticket
116 print >> log, "Error getting ticket for %(slice_hrn)s at aggregate %(net_hrn)s" % \
119 # create a new ticket
120 new_ticket = SfaTicket(subject = slice_hrn)
121 new_ticket.set_gid_caller(api.auth.client_gid)
122 new_ticket.set_issuer(key=api.key, subject=api.hrn)
127 'timestamp': int(time.time()),
131 # merge data from aggregate ticket into new ticket
132 for agg_ticket in tickets.values():
133 # get data from this ticket
134 agg_ticket = SfaTicket(string=agg_ticket)
135 attributes = agg_ticket.get_attributes()
136 if attributes.get('initscripts', []) != None:
137 valid_data['initscripts'].extend(attributes.get('initscripts', []))
138 if attributes.get('slivers', []) != None:
139 valid_data['slivers'].extend(attributes.get('slivers', []))
142 object_gid = agg_ticket.get_gid_object()
143 new_ticket.set_gid_object(object_gid)
144 new_ticket.set_pubkey(object_gid.get_pubkey())
147 tmp_rspec.parseString(agg_ticket.get_rspec())
148 networks.extend([{'NetSpec': tmp_rspec.getDictsByTagName('NetSpec')}])
150 #new_ticket.set_parent(api.auth.hierarchy.get_auth_ticket(auth_hrn))
151 new_ticket.set_attributes(valid_data)
152 resources = {'networks': networks, 'start_time': 0, 'duration': 0}
153 resourceDict = {'RSpec': resources}
154 tmp_rspec.parseDict(resourceDict)
155 new_ticket.set_rspec(tmp_rspec.toxml())
158 return new_ticket.save_to_string(save_parents=True)
160 def start_slice(api, xrn):
161 hrn, type = urn_to_hrn(xrn)
162 slicename = hrn_to_pl_slicename(hrn)
163 slices = api.plshell.GetSlices(api.plauth, {'name': slicename}, ['slice_id'])
165 raise RecordNotFound(hrn)
167 attributes = api.plshell.GetSliceTags(api.plauth, {'slice_id': slice_id, 'name': 'enabled'}, ['slice_attribute_id'])
168 attribute_id = attreibutes[0]['slice_attribute_id']
169 api.plshell.UpdateSliceTag(api.plauth, attribute_id, "1" )
173 def stop_slice(api, xrn):
174 hrn, type = urn_to_hrn(xrn)
175 slicename = hrn_to_pl_slicename(hrn)
176 slices = api.plshell.GetSlices(api.plauth, {'name': slicename}, ['slice_id'])
178 raise RecordNotFound(hrn)
179 slice_id = slices[0]['slice_id']
180 attributes = api.plshell.GetSliceTags(api.plauth, {'slice_id': slice_id, 'name': 'enabled'}, ['slice_attribute_id'])
181 attribute_id = attributes[0]['slice_attribute_id']
182 api.plshell.UpdateSliceTag(api.plauth, attribute_id, "0")
185 def reset_slice(api, xrn):
186 # XX not implemented at this interface
190 # XX just import the legacy module and excute that until
191 # we transition the code to this module
192 from sfa.plc.slices import Slices
195 return [hrn_to_urn(slice_hrn, 'slice') for slice_hrn in slices['hrn']]
197 def get_rspec(api, xrn=None, origin_hrn=None):
198 hrn, type = urn_to_hrn(xrn)
201 aggs = Aggregates(api)
202 cred = api.getCredential()
204 if agg not in [api.auth.client_cred.get_gid_caller().get_hrn()]:
206 # get the rspec from the aggregate
207 agg_rspec = aggs[agg].get_resources(cred, xrn, origin_hrn)
209 # XX print out to some error log
210 print >> log, "Error getting resources at aggregate %s" % agg
211 traceback.print_exc(log)
212 print >> log, "%s" % (traceback.format_exc())
216 tree = etree.parse(StringIO(agg_rspec))
217 except etree.XMLSyntaxError:
218 message = agg + ": " + str(sys.exc_info()[1])
219 raise InvalidRSpec(message)
221 root = tree.getroot()
222 if root.get("type") in ["SFA"]:
226 for network in root.iterfind("./network"):
227 rspec.append(deepcopy(network))
228 for request in root.iterfind("./request"):
229 rspec.append(deepcopy(request))
231 return etree.tostring(rspec, xml_declaration=True, pretty_print=True)
234 Returns the request context required by sfatables. At some point, this
235 mechanism should be changed to refer to "contexts", which is the
236 information that sfatables is requesting. But for now, we just return
237 the basic information needed in a dict.
239 def fetch_context(slice_hrn, user_hrn, contexts):
240 #slice_hrn = urn_to_hrn(slice_xrn)[0]
241 #user_hrn = urn_to_hrn(user_xrn)[0]
242 base_context = {'sfa':{'user':{'hrn':user_hrn}, 'slice':{'hrn':slice_hrn}}}
247 r.parseFile(sys.argv[1])
249 create_slice(None,'plc.princeton.tmacktestslice',rspec)
251 if __name__ == "__main__":