Add 'php/phpxmlrpc/' from commit 'cd5dbb4a511e7a616a61187a5de1a611a9748cbd'
[plcapi.git] / PLC / Methods / GetSliceTicket.py
1 import time
2
3 from PLC.Faults import *
4 from PLC.Method import Method
5 from PLC.Parameter import Parameter, Mixed
6 from PLC.Slices import Slice, Slices
7 from PLC.Auth import Auth
8 from PLC.GPG import gpg_sign, gpg_verify
9 from PLC.InitScripts import InitScript, InitScripts
10
11 from PLC.Methods.GetSlivers import get_slivers
12
13 class GetSliceTicket(Method):
14     """
15     Returns a ticket for, or signed representation of, the specified
16     slice. Slice tickets may be used to manually instantiate or update
17     a slice on a node. Present this ticket to the local Node Manager
18     interface to redeem it.
19
20     If the slice has not been added to a node with AddSliceToNodes,
21     and the ticket is redeemed on that node, it will be deleted the
22     next time the Node Manager contacts the API.
23
24     Users may only obtain tickets for slices of which they are
25     members. PIs may obtain tickets for any of the slices at their
26     sites, or any slices of which they are members. Admins may obtain
27     tickets for any slice.
28
29     Returns 1 if successful, faults otherwise.
30     """
31
32     roles = ['admin', 'pi', 'user', 'peer']
33
34     accepts = [
35         Auth(),
36         Mixed(Slice.fields['slice_id'],
37               Slice.fields['name']),
38         ]
39
40     returns = Parameter(str, 'Signed slice ticket')
41
42     def call(self, auth, slice_id_or_name):
43         slices = Slices(self.api, [slice_id_or_name])
44         if not slices:
45             raise PLCInvalidArgument, "No such slice"
46         slice = slices[0]
47
48         # Allow peers to obtain tickets for their own slices
49         if slice['peer_id'] is not None:
50             if not isinstance(self.caller, Peer):
51                 raise PLCInvalidArgument, "Not a local slice"
52             elif slice['peer_id'] != self.caller['peer_id']:
53                 raise PLCInvalidArgument, "Only the authoritative peer may obtain tickets for that slice"
54
55         # Tickets are the canonicalized XML-RPC methodResponse
56         # representation of a partial GetSlivers() response, i.e.,
57
58         initscripts = InitScripts(self.api, {'enabled': True})
59
60         data = {
61             'timestamp': int(time.time()),
62             'initscripts': initscripts,
63             'slivers': get_slivers(self.api, self.caller, auth, [slice['slice_id']]),
64             }
65
66         # Sign ticket
67         signed_ticket = gpg_sign((data,),
68                                  self.api.config.PLC_ROOT_GPG_KEY,
69                                  self.api.config.PLC_ROOT_GPG_KEY_PUB,
70                                  methodresponse = True,
71                                  detach_sign = False)
72
73         # Verify ticket
74         gpg_verify(signed_ticket,
75                    self.api.config.PLC_ROOT_GPG_KEY_PUB)
76
77         return signed_ticket