add new slice functions
[plcapi.git] / PLC / Methods / AddSlice.py
1 import re
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 PasswordAuth
8 from PLC.Sites import Site, Sites
9
10 class AddSlice(Method):
11     """
12     Adds a new slice. Any fields specified in optional_vals are used,
13     otherwise defaults are used.
14
15     Valid slice names are lowercase and begin with the login_base
16     (slice prefix) of a valid site, followed by a single
17     underscore. Thereafter, only letters, numbers, or additional
18     underscores may be used.
19
20     PIs may only add slices associated with their own sites (i.e.,
21     slice prefixes must always be the login_base of one of their
22     sites).
23
24     Returns the new slice_id (> 0) if successful, faults otherwise.
25     """
26
27     roles = ['admin', 'pi']
28
29     can_update = lambda (field, value): field in \
30                  ['instantiation', 'url', 'description', 'max_nodes']
31     update_fields = dict(filter(can_update, Slice.fields.items()))
32
33     accepts = [
34         PasswordAuth(),
35         Slice.fields['name'],
36         update_fields
37         ]
38
39     returns = Parameter(int, 'New slice_id (> 0) if successful')
40
41     def call(self, auth, name, optional_vals = {}):
42         if filter(lambda field: field not in self.update_fields, optional_vals):
43             raise PLCInvalidArgument, "Invalid field specified"
44
45         # 1. Lowercase.
46         # 2. Begins with login_base (only letters).
47         # 3. Then single underscore after login_base.
48         # 4. Then letters, numbers, or underscores.
49         good_name = r'^[a-z]+_[a-z0-9_]+$'
50         if not name or \
51            not re.match(good_name, name):
52             raise PLCInvalidArgument, "Invalid slice name"
53
54         # Get associated site details
55         login_base = name.split("_")[0]
56         sites = Sites(self.api, [login_base]).values()
57         if not sites:
58             raise PLCInvalidArgument, "Invalid slice prefix"
59         site = sites[0]
60
61         if 'admin' not in self.caller['roles']:
62             if site['site_id'] not in self.caller['site_ids']:
63                 raise PLCPermissionDenied, "Slice prefix must be the same as the login_base of one of your sites"
64
65         if len(site['slice_ids']) >= site['max_slices']:
66             raise PLCInvalidArgument, "Site has reached its maximum allowable slice count"
67
68         slice = Slice(self.api, optional_vals)
69         slice['creator_person_id'] = self.caller['person_id']
70         slice['name'] = name
71         slice['site_id'] = site['site_id']
72         slice.sync()
73
74         return slice['slice_id']