bug fixes
[plcapi.git] / PLC / Methods / UpdateSlice.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.Table import Row
7 from PLC.Auth import Auth
8
9 from PLC.Slices import Slice, Slices
10 from PLC.Sites import Site, Sites
11 from PLC.TagTypes import TagTypes
12 from PLC.SliceTags import SliceTags
13 from PLC.Methods.AddSliceTag import AddSliceTag
14 from PLC.Methods.UpdateSliceTag import UpdateSliceTag
15
16 can_update = ['instantiation', 'url', 'description', 'max_nodes', 'expires']
17
18 class UpdateSlice(Method):
19     """
20     Updates the parameters of an existing slice with the values in
21     slice_fields.
22
23     Users may only update slices of which they are members. PIs may
24     update any of the slices at their sites, or any slices of which
25     they are members. Admins may update any slice.
26
27     Only PIs and admins may update max_nodes. Slices cannot be renewed
28     (by updating the expires parameter) more than 8 weeks into the
29     future.
30
31     Returns 1 if successful, faults otherwise.
32     """
33
34     roles = ['admin', 'pi', 'user']
35
36     accepted_fields = Row.accepted_fields(can_update, Slice.fields)
37
38     accepts = [
39         Auth(),
40         Mixed(Slice.fields['slice_id'],
41               Slice.fields['name']),
42         accepted_fields
43         ]
44
45     returns = Parameter(int, '1 if successful')
46
47     def call(self, auth, slice_id_or_name, slice_fields):
48
49         slices = Slices(self.api, [slice_id_or_name])
50         if not slices:
51             raise PLCInvalidArgument, "No such slice %r"%slice_id_or_name
52         slice = slices[0]
53
54         if slice['peer_id'] is not None:
55             raise PLCInvalidArgument, "Not a local slice"
56
57         # Authenticated function
58         assert self.caller is not None
59
60         if 'admin' not in self.caller['roles']:
61             if self.caller['person_id'] in slice['person_ids']:
62                 pass
63             elif 'pi' not in self.caller['roles']:
64                 raise PLCPermissionDenied, "Not a member of the specified slice"
65             elif slice['site_id'] not in self.caller['site_ids']:
66                 raise PLCPermissionDenied, "Specified slice not associated with any of your sites"
67
68         # Renewing
69         renewing=False
70         if 'expires' in slice_fields and slice_fields['expires'] > slice['expires']:
71             sites = Sites(self.api, [slice['site_id']])
72             assert sites
73             site = sites[0]
74
75             if site['max_slices'] <= 0:
76                 raise PLCInvalidArgument, "Slice creation and renewal have been disabled for the site"
77
78             # Maximum expiration date is 8 weeks from now
79             # XXX Make this configurable
80             max_expires = time.time() + (8 * 7 * 24 * 60 * 60)
81
82             if 'admin' not in self.caller['roles'] and slice_fields['expires'] > max_expires:
83                 raise PLCInvalidArgument, "Cannot renew a slice beyond 8 weeks from now"
84
85             # XXX Make this a configurable policy
86             if slice['description'] is None or not slice['description'].strip():
87                 if 'description' not in slice_fields or slice_fields['description'] is None or \
88                    not slice_fields['description'].strip():
89                     raise PLCInvalidArgument, "Cannot renew a slice with an empty description or URL"
90
91             if slice['url'] is None or not slice['url'].strip():
92                 if 'url' not in slice_fields or slice_fields['url'] is None or \
93                    not slice_fields['url'].strip():
94                     raise PLCInvalidArgument, "Cannot renew a slice with an empty description or URL"
95             renewing=True
96
97         if 'max_nodes' in slice_fields and slice_fields['max_nodes'] != slice['max_nodes']:
98             if 'admin' not in self.caller['roles'] and \
99                'pi' not in self.caller['roles']:
100                 raise PLCInvalidArgument, "Only admins and PIs may update max_nodes"
101
102         slice.update(slice_fields)
103         slice.sync(commit=True)
104
105         return 1