addeg get_version method
[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 import sfa.plc.peers as peers
21 from sfa.plc.network import *
22 from sfa.plc.api import SfaAPI
23 from sfa.plc.slices import *
24
25 def get_version():
26     version = {}
27     version['geni_api'] = 1
28     return version
29
30 def delete_slice(api, xrn):
31     hrn, type = urn_to_hrn(xrn)
32     slicename = hrn_to_pl_slicename(hrn)
33     slices = api.plshell.GetSlices(api.plauth, {'name': slicename})
34     if not slices:
35         return 1
36     slice = slices[0]
37
38     # determine if this is a peer slice
39     peer = peers.get_peer(api, hrn)
40     if peer:
41         api.plshell.UnBindObjectFromPeer(api.plauth, 'slice', slice['slice_id'], peer)
42     api.plshell.DeleteSliceFromNodes(api.plauth, slicename, slice['node_ids'])
43     if peer:
44         api.plshell.BindObjectToPeer(api.plauth, 'slice', slice['slice_id'], peer, slice['peer_slice_id'])
45     return 1
46
47 def __get_hostnames(nodes):
48     hostnames = []
49     for node in nodes:
50         hostnames.append(node.hostname)
51     return hostnames
52     
53 def create_slice(api, xrn, xml, reg_objects=None):
54     """
55     Verify HRN and initialize the slice record in PLC if necessary.
56     """
57
58     hrn, type = urn_to_hrn(xrn)
59     peer = None
60     slices = Slices(api)
61     peer = slices.get_peer(hrn)
62     sfa_peer = slices.get_sfa_peer(hrn)
63     registry = api.registries[api.hrn]
64     credential = api.getCredential()
65     site_id, remote_site_id = slices.verify_site(registry, credential, hrn, 
66                                                  peer, sfa_peer, reg_objects)
67
68     slice = slices.verify_slice(registry, credential, hrn, site_id, 
69                                 remote_site_id, peer, sfa_peer, reg_objects)
70
71     network = Network(api)
72
73     slice = network.get_slice(api, hrn)
74     current = __get_hostnames(slice.get_nodes())
75     
76     network.addRSpec(xml, api.config.SFA_AGGREGATE_RSPEC_SCHEMA)
77     request = __get_hostnames(network.nodesWithSlivers())
78     
79     # remove nodes not in rspec
80     deleted_nodes = list(set(current).difference(request))
81
82     # add nodes from rspec
83     added_nodes = list(set(request).difference(current))
84     
85
86
87     if peer:
88         api.plshell.UnBindObjectFromPeer(api.plauth, 'slice', slice.id, peer)
89
90     api.plshell.AddSliceToNodes(api.plauth, slice.name, added_nodes) 
91     api.plshell.DeleteSliceFromNodes(api.plauth, slice.name, deleted_nodes)
92
93     network.updateSliceTags()
94
95     if peer:
96         api.plshell.BindObjectToPeer(api.plauth, 'slice', slice.id, peer, 
97                                      slice.peer_id)
98
99     # print network.toxml()
100
101     return True
102
103
104 def get_ticket(api, xrn, rspec, origin_hrn=None, reg_objects=None):
105
106     slice_hrn, type = urn_to_hrn(xrn)
107     slices = Slices(api)
108     peer = slices.get_peer(slice_hrn)
109     sfa_peer = slices.get_sfa_peer(slice_hrn)
110     
111     # get the slice record
112     registry = api.registries[api.hrn]
113     credential = api.getCredential()
114     records = registry.resolve(credential, xrn)
115
116     # similar to create_slice, we must verify that the required records exist
117     # at this aggregate before we can issue a ticket   
118     site_id, remote_site_id = slices.verify_site(registry, credential, slice_hrn,
119                                                  peer, sfa_peer, reg_objects)
120     slice = slices.verify_slice(registry, credential, slice_hrn, site_id,
121                                 remote_site_id, peer, sfa_peer, reg_objects)
122
123     # make sure we get a local slice record
124     record = None  
125     for tmp_record in records:
126         if tmp_record['type'] == 'slice' and \
127            not tmp_record['peer_authority']:
128             record = SliceRecord(dict=tmp_record)
129     if not record:
130         raise RecordNotFound(slice_hrn)
131
132     # get sliver info
133     slivers = Slices(api).get_slivers(slice_hrn)
134     if not slivers:
135         raise SliverDoesNotExist(slice_hrn)
136     
137     # get initscripts
138     initscripts = []
139     data = {
140         'timestamp': int(time.time()),
141         'initscripts': initscripts,
142         'slivers': slivers
143     }
144
145     # create the ticket
146     object_gid = record.get_gid_object()
147     new_ticket = SfaTicket(subject = object_gid.get_subject())
148     new_ticket.set_gid_caller(api.auth.client_gid)
149     new_ticket.set_gid_object(object_gid)
150     new_ticket.set_issuer(key=api.key, subject=api.hrn)
151     new_ticket.set_pubkey(object_gid.get_pubkey())
152     new_ticket.set_attributes(data)
153     new_ticket.set_rspec(rspec)
154     #new_ticket.set_parent(api.auth.hierarchy.get_auth_ticket(auth_hrn))
155     new_ticket.encode()
156     new_ticket.sign()
157     
158     return new_ticket.save_to_string(save_parents=True)
159
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'])
164     if not slices:
165         raise RecordNotFound(hrn)
166     slice_id = slices[0]
167     attributes = api.plshell.GetSliceTags(api.plauth, {'slice_id': slice_id, 'name': 'enabled'}, ['slice_attribute_id'])
168     attribute_id = attributes[0]['slice_attribute_id']
169     api.plshell.UpdateSliceTag(api.plauth, attribute_id, "1" )
170
171     return 1
172  
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'])
177     if not slices:
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")
183     return 1
184
185 def reset_slice(api, xrn):
186     # XX not implemented at this interface
187     return 1
188
189 def get_slices(api):
190     # look in cache first
191     if api.cache:
192         slices = api.cache.get('slices')
193         if slices:
194             return slices
195
196     # get data from db 
197     slices = api.plshell.GetSlices(api.plauth, {'peer_id': None}, ['name'])
198     slice_hrns = [slicename_to_hrn(api.hrn, slice['name']) for slice in slices]
199     slice_urns = [hrn_to_urn(slice_hrn, 'slice') for slice_hrn in slice_hrns]
200
201     # cache the result
202     if api.cache:
203         api.cache.add('slices', slice_urns) 
204
205     return slice_urns
206     
207 def get_rspec(api, xrn=None, origin_hrn=None):
208     # look in cache first
209     if api.cache and not xrn:
210         rspec = api.cache.get('nodes')
211         if rspec:
212             return rspec 
213
214     hrn, type = urn_to_hrn(xrn)
215     network = Network(api)
216     if (hrn):
217         if network.get_slice(api, hrn):
218             network.addSlice()
219
220     rspec = network.toxml()
221
222     # cache the result
223     if api.cache and not xrn:
224         api.cache.add('nodes', rspec)
225
226     return rspec
227
228 """
229 Returns the request context required by sfatables. At some point, this
230 mechanism should be changed to refer to "contexts", which is the
231 information that sfatables is requesting. But for now, we just return
232 the basic information needed in a dict.
233 """
234 def fetch_context(slice_xrn, user_xrn, contexts):
235     slice_hrn, type = urn_to_hrn(slice_xrn)
236     user_hrn, type = urn_to_hrn(user_xrn)
237     base_context = {'sfa':{'user':{'hrn':user_hrn}, 'slice':{'hrn':slice_hrn}}}
238     return base_context
239
240 def main():
241     api = SfaAPI()
242     """
243     rspec = get_rspec(api, "plc.princeton.sapan", None)
244     #rspec = get_rspec(api, "plc.princeton.coblitz", None)
245     #rspec = get_rspec(api, "plc.pl.sirius", None)
246     print rspec
247     """
248     f = open(sys.argv[1])
249     xml = f.read()
250     f.close()
251     create_slice(api, "plc.princeton.sapan", xml)
252
253 if __name__ == "__main__":
254     main()