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
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
16 can_update = ['instantiation', 'url', 'description', 'max_nodes', 'expires']
18 class UpdateSlice(Method):
20 Updates the parameters of an existing slice with the values in
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.
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
31 Returns 1 if successful, faults otherwise.
34 roles = ['admin', 'pi', 'user']
36 accepted_fields = Row.accepted_fields(can_update, Slice.fields)
37 # xxx check the related_fields feature
38 accepted_fields.update(Slice.related_fields)
39 accepted_fields.update(Slice.tags)
43 Mixed(Slice.fields['slice_id'],
44 Slice.fields['name']),
48 returns = Parameter(int, '1 if successful')
50 def call(self, auth, slice_id_or_name, slice_fields):
52 # split provided fields
53 [native,related,tags,rejected] = Row.split_fields(slice_fields,[Slice.fields,Slice.related_fields,Slice.tags])
56 native = Row.check_fields (native, self.accepted_fields)
58 raise PLCInvalidArgument, "Cannot update Slice column(s) %r"%rejected
60 slices = Slices(self.api, [slice_id_or_name])
62 raise PLCInvalidArgument, "No such slice %r"%slice_id_or_name
65 if slice['peer_id'] is not None:
66 raise PLCInvalidArgument, "Not a local slice"
68 # Authenticated function
69 assert self.caller is not None
71 if 'admin' not in self.caller['roles']:
72 if self.caller['person_id'] in slice['person_ids']:
74 elif 'pi' not in self.caller['roles']:
75 raise PLCPermissionDenied, "Not a member of the specified slice"
76 elif slice['site_id'] not in self.caller['site_ids']:
77 raise PLCPermissionDenied, "Specified slice not associated with any of your sites"
81 if 'expires' in slice_fields and slice_fields['expires'] > slice['expires']:
82 sites = Sites(self.api, [slice['site_id']])
86 if site['max_slices'] <= 0:
87 raise PLCInvalidArgument, "Slice creation and renewal have been disabled for the site"
89 # Maximum expiration date is 8 weeks from now
90 # XXX Make this configurable
91 max_expires = time.time() + (8 * 7 * 24 * 60 * 60)
93 if 'admin' not in self.caller['roles'] and slice_fields['expires'] > max_expires:
94 raise PLCInvalidArgument, "Cannot renew a slice beyond 8 weeks from now"
96 # XXX Make this a configurable policy
97 if slice['description'] is None or not slice['description'].strip():
98 if 'description' not in slice_fields or slice_fields['description'] is None or \
99 not slice_fields['description'].strip():
100 raise PLCInvalidArgument, "Cannot renew a slice with an empty description or URL"
102 if slice['url'] is None or not slice['url'].strip():
103 if 'url' not in slice_fields or slice_fields['url'] is None or \
104 not slice_fields['url'].strip():
105 raise PLCInvalidArgument, "Cannot renew a slice with an empty description or URL"
108 if 'max_nodes' in slice_fields and slice_fields['max_nodes'] != slice['max_nodes']:
109 if 'admin' not in self.caller['roles'] and \
110 'pi' not in self.caller['roles']:
111 raise PLCInvalidArgument, "Only admins and PIs may update max_nodes"
113 # Make requested associations
114 for (k,v) in related.iteritems():
115 slice.associate(auth,k,v)
117 slice.update(slice_fields)
118 slice.sync(commit=True)
120 for (tagname,value) in tags.iteritems():
121 # the tagtype instance is assumed to exist, just check that
122 if not TagTypes(self.api,{'tagname':tagname}):
123 raise PLCInvalidArgument,"No such TagType %s"%tagname
124 slice_tags=SliceTags(self.api,{'tagname':tagname,'slice_id':slice['slice_id']})
126 AddSliceTag(self.api).__call__(auth,slice['slice_id'],tagname,value)
128 UpdateSliceTag(self.api).__call__(auth,slice_tags[0]['slice_tag_id'],value)
130 self.event_objects = {'Slice': [slice['slice_id']]}
132 self.message='Slice %s updated'%slice['name']
134 self.message='Slice %d updated'%slice['slice_id']
136 # it appears that slice['expires'] may be either an int, or a formatted string
138 expire_date=time.strftime('%Y-%m-%d:%H:%M',time.localtime(float(slice['expires'])))
140 expire_date=slice['expires']
141 self.message += ' renewed until %s'%expire_date