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