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 $
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.record import *
17 from sfa.util.sfaticket import SfaTicket
18 from sfa.util.debug import log
19 from sfa.plc.slices import Slices
20 from sfa.trust.credential import Credential
21 import sfa.plc.peers as peers
22 from sfa.plc.network import *
23 from sfa.plc.api import SfaAPI
24 from sfa.plc.slices import *
28 version['geni_api'] = 1
31 def delete_slice(api, xrn):
32 hrn, type = urn_to_hrn(xrn)
33 slicename = hrn_to_pl_slicename(hrn)
34 slices = api.plshell.GetSlices(api.plauth, {'name': slicename})
39 # determine if this is a peer slice
40 peer = peers.get_peer(api, hrn)
42 api.plshell.UnBindObjectFromPeer(api.plauth, 'slice', slice['slice_id'], peer)
43 api.plshell.DeleteSliceFromNodes(api.plauth, slicename, slice['node_ids'])
45 api.plshell.BindObjectToPeer(api.plauth, 'slice', slice['slice_id'], peer, slice['peer_slice_id'])
48 def __get_hostnames(nodes):
51 hostnames.append(node.hostname)
54 def create_slice(api, slice_xrn, creds, rspec, users):
56 Create the sliver[s] (slice) at this aggregate.
57 Verify HRN and initialize the slice record in PLC if necessary.
60 reg_objects = __get_registry_objects(slice_xrn, creds, users)
62 hrn, type = urn_to_hrn(slice_xrn)
65 peer = slices.get_peer(hrn)
66 sfa_peer = slices.get_sfa_peer(hrn)
67 registry = api.registries[api.hrn]
68 credential = api.getCredential()
69 site_id, remote_site_id = slices.verify_site(registry, credential, hrn,
70 peer, sfa_peer, reg_objects)
72 slice = slices.verify_slice(registry, credential, hrn, site_id,
73 remote_site_id, peer, sfa_peer, reg_objects)
75 network = Network(api)
77 slice = network.get_slice(api, hrn)
78 current = __get_hostnames(slice.get_nodes())
80 network.addRSpec(rspec, api.config.SFA_AGGREGATE_RSPEC_SCHEMA)
81 request = __get_hostnames(network.nodesWithSlivers())
83 # remove nodes not in rspec
84 deleted_nodes = list(set(current).difference(request))
86 # add nodes from rspec
87 added_nodes = list(set(request).difference(current))
92 api.plshell.UnBindObjectFromPeer(api.plauth, 'slice', slice.id, peer)
94 api.plshell.AddSliceToNodes(api.plauth, slice.name, added_nodes)
95 api.plshell.DeleteSliceFromNodes(api.plauth, slice.name, deleted_nodes)
97 network.updateSliceTags()
100 api.plshell.BindObjectToPeer(api.plauth, 'slice', slice.id, peer,
103 # print network.toxml()
108 def __get_registry_objects(slice_xrn, creds, users):
112 hrn, type = urn_to_hrn(slice_xrn)
114 hrn_auth = get_authority(hrn)
116 # Build up objects that an SFA registry would return if SFA
117 # could contact the slice's registry directly
125 site['name'] = 'geni.%s' % hrn_auth
126 site['enabled'] = True
127 site['max_slices'] = 100
130 # Is it okay if this login base is the same as one already at this myplc site?
131 # Do we need uniqueness? Should use hrn_auth instead of just the leaf perhaps?
132 site['login_base'] = get_leaf(hrn_auth)
133 site['abbreviated_name'] = hrn
134 site['max_slivers'] = 1000
135 reg_objects['site'] = site
138 slice['expires'] = int(mktime(Credential(string=creds[0]).get_lifetime().timetuple()))
140 slice['name'] = site['login_base'] + "_" + get_leaf(hrn)
142 slice['description'] = hrn
144 reg_objects['slice_record'] = slice
146 reg_objects['users'] = {}
149 hrn, _ = urn_to_hrn(user['urn'])
150 user['email'] = hrn + "@geni.net"
151 user['first_name'] = hrn
152 user['last_name'] = hrn
153 reg_objects['users'][user['email']] = user
157 def get_ticket(api, xrn, rspec, origin_hrn=None, reg_objects=None):
159 slice_hrn, type = urn_to_hrn(xrn)
161 peer = slices.get_peer(slice_hrn)
162 sfa_peer = slices.get_sfa_peer(slice_hrn)
164 # get the slice record
165 registry = api.registries[api.hrn]
166 credential = api.getCredential()
167 records = registry.resolve(credential, xrn)
169 # similar to create_slice, we must verify that the required records exist
170 # at this aggregate before we can issue a ticket
171 site_id, remote_site_id = slices.verify_site(registry, credential, slice_hrn,
172 peer, sfa_peer, reg_objects)
173 slice = slices.verify_slice(registry, credential, slice_hrn, site_id,
174 remote_site_id, peer, sfa_peer, reg_objects)
176 # make sure we get a local slice record
178 for tmp_record in records:
179 if tmp_record['type'] == 'slice' and \
180 not tmp_record['peer_authority']:
181 record = SliceRecord(dict=tmp_record)
183 raise RecordNotFound(slice_hrn)
186 slivers = Slices(api).get_slivers(slice_hrn)
188 raise SliverDoesNotExist(slice_hrn)
193 'timestamp': int(time.time()),
194 'initscripts': initscripts,
199 object_gid = record.get_gid_object()
200 new_ticket = SfaTicket(subject = object_gid.get_subject())
201 new_ticket.set_gid_caller(api.auth.client_gid)
202 new_ticket.set_gid_object(object_gid)
203 new_ticket.set_issuer(key=api.key, subject=api.hrn)
204 new_ticket.set_pubkey(object_gid.get_pubkey())
205 new_ticket.set_attributes(data)
206 new_ticket.set_rspec(rspec)
207 #new_ticket.set_parent(api.auth.hierarchy.get_auth_ticket(auth_hrn))
211 return new_ticket.save_to_string(save_parents=True)
213 def start_slice(api, xrn):
214 hrn, type = urn_to_hrn(xrn)
215 slicename = hrn_to_pl_slicename(hrn)
216 slices = api.plshell.GetSlices(api.plauth, {'name': slicename}, ['slice_id'])
218 raise RecordNotFound(hrn)
220 attributes = api.plshell.GetSliceTags(api.plauth, {'slice_id': slice_id, 'name': 'enabled'}, ['slice_attribute_id'])
221 attribute_id = attributes[0]['slice_attribute_id']
222 api.plshell.UpdateSliceTag(api.plauth, attribute_id, "1" )
226 def stop_slice(api, xrn):
227 hrn, type = urn_to_hrn(xrn)
228 slicename = hrn_to_pl_slicename(hrn)
229 slices = api.plshell.GetSlices(api.plauth, {'name': slicename}, ['slice_id'])
231 raise RecordNotFound(hrn)
232 slice_id = slices[0]['slice_id']
233 attributes = api.plshell.GetSliceTags(api.plauth, {'slice_id': slice_id, 'name': 'enabled'}, ['slice_attribute_id'])
234 attribute_id = attributes[0]['slice_attribute_id']
235 api.plshell.UpdateSliceTag(api.plauth, attribute_id, "0")
238 def reset_slice(api, xrn):
239 # XX not implemented at this interface
243 # look in cache first
245 slices = api.cache.get('slices')
250 slices = api.plshell.GetSlices(api.plauth, {'peer_id': None}, ['name'])
251 slice_hrns = [slicename_to_hrn(api.hrn, slice['name']) for slice in slices]
252 slice_urns = [hrn_to_urn(slice_hrn, 'slice') for slice_hrn in slice_hrns]
256 api.cache.add('slices', slice_urns)
260 def get_rspec(api, creds, options):
261 # get slice's hrn from options
262 xrn = options.get('geni_slice_urn', None)
263 hrn, type = urn_to_hrn(xrn)
265 # get hrn of the original caller
266 origin_hrn = options.get('origin_hrn', None)
268 origin_hrn = Credential(string=creds[0]).get_gid_caller().get_hrn()
270 # look in cache first
271 if api.cache and not xrn:
272 rspec = api.cache.get('nodes')
276 network = Network(api)
278 if network.get_slice(api, hrn):
281 rspec = network.toxml()
284 if api.cache and not xrn:
285 api.cache.add('nodes', rspec)
291 Returns the request context required by sfatables. At some point, this
292 mechanism should be changed to refer to "contexts", which is the
293 information that sfatables is requesting. But for now, we just return
294 the basic information needed in a dict.
296 def fetch_context(slice_xrn, user_xrn, contexts):
297 slice_hrn, type = urn_to_hrn(slice_xrn)
298 user_hrn, type = urn_to_hrn(user_xrn)
299 base_context = {'sfa':{'user':{'hrn':user_hrn}, 'slice':{'hrn':slice_hrn}}}
305 rspec = get_rspec(api, "plc.princeton.sapan", None)
306 #rspec = get_rspec(api, "plc.princeton.coblitz", None)
307 #rspec = get_rspec(api, "plc.pl.sirius", None)
310 f = open(sys.argv[1])
313 create_slice(api, "plc.princeton.sapan", xml)
315 if __name__ == "__main__":