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