merged in from trunk -r 17776:17849
[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     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
80
81     if peer:
82         api.plshell.UnBindObjectFromPeer(api.plauth, 'slice', slice.id, peer)
83
84     api.plshell.AddSliceToNodes(api.plauth, slice.name, added_nodes) 
85     api.plshell.DeleteSliceFromNodes(api.plauth, slice.name, deleted_nodes)
86
87     network.updateSliceTags()
88
89     if peer:
90         api.plshell.BindObjectToPeer(api.plauth, 'slice', slice.id, peer, 
91                                      slice.peer_id)
92
93     # print network.toxml()
94
95     return True
96
97
98 def get_ticket(api, xrn, rspec, origin_hrn=None):
99     slice_hrn, type = urn_to_hrn(xrn)
100     # the the slice record
101     registry = api.registries[api.hrn]
102     credential = api.getCredential()
103     records = registry.resolve(credential, xrn)
104     
105     # make sure we get a local slice record
106     record = None  
107     for tmp_record in records:
108         if tmp_record['type'] == 'slice' and \
109            not tmp_record['peer_authority']:
110             record = SliceRecord(dict=tmp_record)
111     if not record:
112         raise RecordNotFound(slice_hrn)
113
114     # get sliver info
115     slivers = Slices(api).get_slivers(slice_hrn)
116     if not slivers:
117         raise SliverDoesNotExist(slice_hrn)
118     
119     # get initscripts
120     initscripts = []
121     data = {
122         'timestamp': int(time.time()),
123         'initscripts': initscripts,
124         'slivers': slivers
125     }
126
127     # create the ticket
128     object_gid = record.get_gid_object()
129     new_ticket = SfaTicket(subject = object_gid.get_subject())
130     new_ticket.set_gid_caller(api.auth.client_gid)
131     new_ticket.set_gid_object(object_gid)
132     new_ticket.set_issuer(key=api.key, subject=api.hrn)
133     new_ticket.set_pubkey(object_gid.get_pubkey())
134     new_ticket.set_attributes(data)
135     new_ticket.set_rspec(rspec)
136     #new_ticket.set_parent(api.auth.hierarchy.get_auth_ticket(auth_hrn))
137     new_ticket.encode()
138     new_ticket.sign()
139     
140     return new_ticket.save_to_string(save_parents=True)
141
142 def start_slice(api, xrn):
143     hrn, type = urn_to_hrn(xrn)
144     slicename = hrn_to_pl_slicename(hrn)
145     slices = api.plshell.GetSlices(api.plauth, {'name': slicename}, ['slice_id'])
146     if not slices:
147         raise RecordNotFound(hrn)
148     slice_id = slices[0]
149     attributes = api.plshell.GetSliceTags(api.plauth, {'slice_id': slice_id, 'name': 'enabled'}, ['slice_attribute_id'])
150     attribute_id = attributes[0]['slice_attribute_id']
151     api.plshell.UpdateSliceTag(api.plauth, attribute_id, "1" )
152
153     return 1
154  
155 def stop_slice(api, xrn):
156     hrn, type = urn_to_hrn(xrn)
157     slicename = hrn_to_pl_slicename(hrn)
158     slices = api.plshell.GetSlices(api.plauth, {'name': slicename}, ['slice_id'])
159     if not slices:
160         raise RecordNotFound(hrn)
161     slice_id = slices[0]['slice_id']
162     attributes = api.plshell.GetSliceTags(api.plauth, {'slice_id': slice_id, 'name': 'enabled'}, ['slice_attribute_id'])
163     attribute_id = attributes[0]['slice_attribute_id']
164     api.plshell.UpdateSliceTag(api.plauth, attribute_id, "0")
165     return 1
166
167 def reset_slice(api, xrn):
168     # XX not implemented at this interface
169     return 1
170
171 def get_slices(api):
172     # look in cache first
173     if api.cache:
174         slices = api.cache.get('slices')
175         if slices:
176             return slices
177
178     # get data from db 
179     slices = api.plshell.GetSlices(api.plauth, {'peer_id': None}, ['name'])
180     slice_hrns = [slicename_to_hrn(api.hrn, slice['name']) for slice in slices]
181     slice_urns = [hrn_to_urn(slice_hrn, 'slice') for slice_hrn in slice_hrns]
182
183     # cache the result
184     if api.cache:
185         api.cache.add('slices', slice_urns) 
186
187     return slice_urns
188     
189 def get_rspec(api, xrn=None, origin_hrn=None):
190     # look in cache first
191     if api.cache and not xrn:
192         rspec = api.cache.get('nodes')
193         if rspec:
194             return rspec 
195
196     hrn, type = urn_to_hrn(xrn)
197     network = Network(api)
198     if (hrn):
199         if network.get_slice(api, hrn):
200             network.addSlice()
201
202     rspec = network.toxml()
203
204     # cache the result
205     if api.cache and not xrn:
206         api.cache.add('nodes', rspec)
207
208     return rspec
209
210 """
211 Returns the request context required by sfatables. At some point, this
212 mechanism should be changed to refer to "contexts", which is the
213 information that sfatables is requesting. But for now, we just return
214 the basic information needed in a dict.
215 """
216 def fetch_context(slice_xrn, user_xrn, contexts):
217     slice_hrn, type = urn_to_hrn(slice_xrn)
218     user_hrn, type = urn_to_hrn(user_xrn)
219     base_context = {'sfa':{'user':{'hrn':user_hrn}, 'slice':{'hrn':slice_hrn}}}
220     return base_context
221
222 def main():
223     api = SfaAPI()
224     """
225     rspec = get_rspec(api, "plc.princeton.sapan", None)
226     #rspec = get_rspec(api, "plc.princeton.coblitz", None)
227     #rspec = get_rspec(api, "plc.pl.sirius", None)
228     print rspec
229     """
230     f = open(sys.argv[1])
231     xml = f.read()
232     f.close()
233     create_slice(api, "plc.princeton.sapan", xml)
234
235 if __name__ == "__main__":
236     main()