added slice_status()
[sfa.git] / sfa / managers / aggregate_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.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 *
25
26 def get_version():
27     version = {}
28     version['geni_api'] = 1
29     return version
30
31 def slice_status(api, slice_xrn, creds):
32     result = {}
33     result['geni_urn'] = slice_xrn
34     result['geni_status'] = 'unknown'
35     result['geni_resources'] = {}
36     return result
37
38 def __get_hostnames(nodes):
39     hostnames = []
40     for node in nodes:
41         hostnames.append(node.hostname)
42     return hostnames
43     
44 def create_slice(api, slice_xrn, creds, rspec, users):
45     """
46     Create the sliver[s] (slice) at this aggregate.    
47     Verify HRN and initialize the slice record in PLC if necessary.
48     """
49
50     reg_objects = __get_registry_objects(slice_xrn, creds, users)
51
52     hrn, type = urn_to_hrn(slice_xrn)
53     peer = None
54     slices = Slices(api)
55     peer = slices.get_peer(hrn)
56     sfa_peer = slices.get_sfa_peer(hrn)
57     registry = api.registries[api.hrn]
58     credential = api.getCredential()
59     site_id, remote_site_id = slices.verify_site(registry, credential, hrn, 
60                                                  peer, sfa_peer, reg_objects)
61
62     slice = slices.verify_slice(registry, credential, hrn, site_id, 
63                                 remote_site_id, peer, sfa_peer, reg_objects)
64
65     network = Network(api)
66
67     slice = network.get_slice(api, hrn)
68     current = __get_hostnames(slice.get_nodes())
69     
70     network.addRSpec(rspec, api.config.SFA_AGGREGATE_RSPEC_SCHEMA)
71     request = __get_hostnames(network.nodesWithSlivers())
72     
73     # remove nodes not in rspec
74     deleted_nodes = list(set(current).difference(request))
75
76     # add nodes from rspec
77     added_nodes = list(set(request).difference(current))
78     
79     if peer:
80         api.plshell.UnBindObjectFromPeer(api.plauth, 'slice', slice.id, peer)
81
82     api.plshell.AddSliceToNodes(api.plauth, slice.name, added_nodes) 
83     api.plshell.DeleteSliceFromNodes(api.plauth, slice.name, deleted_nodes)
84
85     network.updateSliceTags()
86
87     if peer:
88         api.plshell.BindObjectToPeer(api.plauth, 'slice', slice.id, peer, 
89                                      slice.peer_id)
90
91     # print network.toxml()
92
93     return True
94
95
96 def __get_registry_objects(slice_xrn, creds, users):
97     """
98     
99     """
100     hrn, type = urn_to_hrn(slice_xrn)
101
102     hrn_auth = get_authority(hrn)
103
104     # Build up objects that an SFA registry would return if SFA
105     # could contact the slice's registry directly
106     reg_objects = None
107
108     if users:
109         reg_objects = {}
110
111         site = {}
112         site['site_id'] = 0
113         site['name'] = 'geni.%s' % hrn_auth
114         site['enabled'] = True
115         site['max_slices'] = 100
116
117         # Note:
118         # Is it okay if this login base is the same as one already at this myplc site?
119         # Do we need uniqueness?  Should use hrn_auth instead of just the leaf perhaps?
120         site['login_base'] = get_leaf(hrn_auth)
121         site['abbreviated_name'] = hrn
122         site['max_slivers'] = 1000
123         reg_objects['site'] = site
124
125         slice = {}
126         slice['expires'] = int(mktime(Credential(string=creds[0]).get_lifetime().timetuple()))
127         slice['hrn'] = hrn
128         slice['name'] = site['login_base'] + "_" +  get_leaf(hrn)
129         slice['url'] = hrn
130         slice['description'] = hrn
131         slice['pointer'] = 0
132         reg_objects['slice_record'] = slice
133
134         reg_objects['users'] = {}
135         for user in users:
136             user['key_ids'] = []
137             hrn, _ = urn_to_hrn(user['urn'])
138             user['email'] = hrn + "@geni.net"
139             user['first_name'] = hrn
140             user['last_name'] = hrn
141             reg_objects['users'][user['email']] = user
142
143         return reg_objects        
144
145 def get_ticket(api, xrn, rspec, origin_hrn=None, reg_objects=None):
146
147     slice_hrn, type = urn_to_hrn(xrn)
148     slices = Slices(api)
149     peer = slices.get_peer(slice_hrn)
150     sfa_peer = slices.get_sfa_peer(slice_hrn)
151     
152     # get the slice record
153     registry = api.registries[api.hrn]
154     credential = api.getCredential()
155     records = registry.resolve(credential, xrn)
156
157     # similar to create_slice, we must verify that the required records exist
158     # at this aggregate before we can issue a ticket   
159     site_id, remote_site_id = slices.verify_site(registry, credential, slice_hrn,
160                                                  peer, sfa_peer, reg_objects)
161     slice = slices.verify_slice(registry, credential, slice_hrn, site_id,
162                                 remote_site_id, peer, sfa_peer, reg_objects)
163
164     # make sure we get a local slice record
165     record = None  
166     for tmp_record in records:
167         if tmp_record['type'] == 'slice' and \
168            not tmp_record['peer_authority']:
169             record = SliceRecord(dict=tmp_record)
170     if not record:
171         raise RecordNotFound(slice_hrn)
172
173     # get sliver info
174     slivers = Slices(api).get_slivers(slice_hrn)
175     if not slivers:
176         raise SliverDoesNotExist(slice_hrn)
177     
178     # get initscripts
179     initscripts = []
180     data = {
181         'timestamp': int(time.time()),
182         'initscripts': initscripts,
183         'slivers': slivers
184     }
185
186     # create the ticket
187     object_gid = record.get_gid_object()
188     new_ticket = SfaTicket(subject = object_gid.get_subject())
189     new_ticket.set_gid_caller(api.auth.client_gid)
190     new_ticket.set_gid_object(object_gid)
191     new_ticket.set_issuer(key=api.key, subject=api.hrn)
192     new_ticket.set_pubkey(object_gid.get_pubkey())
193     new_ticket.set_attributes(data)
194     new_ticket.set_rspec(rspec)
195     #new_ticket.set_parent(api.auth.hierarchy.get_auth_ticket(auth_hrn))
196     new_ticket.encode()
197     new_ticket.sign()
198     
199     return new_ticket.save_to_string(save_parents=True)
200
201 def start_slice(api, xrn):
202     hrn, type = urn_to_hrn(xrn)
203     slicename = hrn_to_pl_slicename(hrn)
204     slices = api.plshell.GetSlices(api.plauth, {'name': slicename}, ['slice_id'])
205     if not slices:
206         raise RecordNotFound(hrn)
207     slice_id = slices[0]
208     attributes = api.plshell.GetSliceTags(api.plauth, {'slice_id': slice_id, 'name': 'enabled'}, ['slice_attribute_id'])
209     attribute_id = attributes[0]['slice_attribute_id']
210     api.plshell.UpdateSliceTag(api.plauth, attribute_id, "1" )
211
212     return 1
213  
214 def stop_slice(api, xrn, creds):
215     hrn, type = urn_to_hrn(xrn)
216     slicename = hrn_to_pl_slicename(hrn)
217     slices = api.plshell.GetSlices(api.plauth, {'name': slicename}, ['slice_id'])
218     if not slices:
219         raise RecordNotFound(hrn)
220     slice_id = slices[0]['slice_id']
221     attributes = api.plshell.GetSliceTags(api.plauth, {'slice_id': slice_id, 'name': 'enabled'}, ['slice_attribute_id'])
222     attribute_id = attributes[0]['slice_attribute_id']
223     api.plshell.UpdateSliceTag(api.plauth, attribute_id, "0")
224     return 1
225
226 def reset_slice(api, xrn):
227     # XX not implemented at this interface
228     return 1
229
230 def delete_slice(api, xrn, creds):
231     hrn, type = urn_to_hrn(xrn)
232     slicename = hrn_to_pl_slicename(hrn)
233     slices = api.plshell.GetSlices(api.plauth, {'name': slicename})
234     if not slices:
235         return 1
236     slice = slices[0]
237
238     # determine if this is a peer slice
239     peer = peers.get_peer(api, hrn)
240     if peer:
241         api.plshell.UnBindObjectFromPeer(api.plauth, 'slice', slice['slice_id'], peer)
242     api.plshell.DeleteSliceFromNodes(api.plauth, slicename, slice['node_ids'])
243     if peer:
244         api.plshell.BindObjectToPeer(api.plauth, 'slice', slice['slice_id'], peer, slice['peer_slice_id'])
245     return 1
246
247 def get_slices(api):
248     # look in cache first
249     if api.cache:
250         slices = api.cache.get('slices')
251         if slices:
252             return slices
253
254     # get data from db 
255     slices = api.plshell.GetSlices(api.plauth, {'peer_id': None}, ['name'])
256     slice_hrns = [slicename_to_hrn(api.hrn, slice['name']) for slice in slices]
257     slice_urns = [hrn_to_urn(slice_hrn, 'slice') for slice_hrn in slice_hrns]
258
259     # cache the result
260     if api.cache:
261         api.cache.add('slices', slice_urns) 
262
263     return slice_urns
264     
265 def get_rspec(api, creds, options):
266     # get slice's hrn from options
267     xrn = options.get('geni_slice_urn', None)
268     hrn, type = urn_to_hrn(xrn)
269
270     # get hrn of the original caller
271     origin_hrn = options.get('origin_hrn', None)
272     if not origin_hrn:
273         origin_hrn = Credential(string=creds[0]).get_gid_caller().get_hrn()
274     
275     # look in cache first
276     if api.cache and not xrn:
277         rspec = api.cache.get('nodes')
278         if rspec:
279             return rspec 
280
281     network = Network(api)
282     if (hrn):
283         if network.get_slice(api, hrn):
284             network.addSlice()
285
286     rspec = network.toxml()
287
288     # cache the result
289     if api.cache and not xrn:
290         api.cache.add('nodes', rspec)
291
292     return rspec
293
294
295 def main():
296     api = SfaAPI()
297     """
298     rspec = get_rspec(api, "plc.princeton.sapan", None)
299     #rspec = get_rspec(api, "plc.princeton.coblitz", None)
300     #rspec = get_rspec(api, "plc.pl.sirius", None)
301     print rspec
302     """
303     f = open(sys.argv[1])
304     xml = f.read()
305     f.close()
306     create_slice(api, "plc.princeton.sapan", xml)
307
308 if __name__ == "__main__":
309     main()