r2lab is migrating from a previous depl. based on omf_sfa
[plcapi.git] / PLC / Methods / AddSlice.py
1 import re
2
3 from PLC.Faults import *
4 from PLC.Auth import Auth
5 from PLC.Method import Method
6 from PLC.Parameter import Parameter, Mixed
7 from PLC.Table import Row
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 from PLC.Debug import log
17
18 can_update = ['name', 'instantiation', 'url', 'description', 'max_nodes']
19
20 class AddSlice(Method):
21     """
22     Adds a new slice. Any fields specified in slice_fields are used,
23     otherwise defaults are used.
24
25     Valid slice names are lowercase and begin with the login_base
26     (slice prefix) of a valid site, followed by a single
27     underscore. Thereafter, only letters, numbers, or additional
28     underscores may be used.
29
30     PIs may only add slices associated with their own sites (i.e.,
31     slice prefixes must always be the login_base of one of their
32     sites).
33
34     Returns the new slice_id (> 0) if successful, faults otherwise.
35     """
36
37     roles = ['admin', 'pi']
38
39     accepted_fields = Row.accepted_fields(can_update, Slice.fields)
40     accepted_fields.update(Slice.tags)
41
42     accepts = [
43         Auth(),
44         accepted_fields
45         ]
46
47     returns = Parameter(int, 'New slice_id (> 0) if successful')
48
49     def call(self, auth, slice_fields):
50
51         [native,tags,rejected]=Row.split_fields(slice_fields,[Slice.fields,Slice.tags])
52
53         # type checking
54         native = Row.check_fields (native, self.accepted_fields)
55         if rejected:
56             raise PLCInvalidArgument, "Cannot add Slice with column(s) %r"%rejected
57
58         # Authenticated function
59         assert self.caller is not None
60
61         # 1. Lowercase.
62         # 2. Begins with login_base (letters or numbers).
63         # 3. Then single underscore after login_base.
64         # 4. Then letters, numbers, or underscores.
65         name = slice_fields['name']
66         good_name = r'^[a-z0-9\.]+_[a-zA-Z0-9_\.]+$'
67         if not name or \
68            not re.match(good_name, name):
69             raise PLCInvalidArgument, "Invalid slice name"
70
71         # Get associated site details
72         login_base = name.split("_")[0]
73         sites = Sites(self.api, [login_base])
74         if not sites:
75             raise PLCInvalidArgument, "Invalid slice prefix %s in %s"%(login_base,name)
76         site = sites[0]
77
78         if 'admin' not in self.caller['roles']:
79             if site['site_id'] not in self.caller['site_ids']:
80                 raise PLCPermissionDenied, "Slice prefix %s must match one of your sites' login_base"%login_base
81
82         if len(site['slice_ids']) >= site['max_slices']:
83             raise PLCInvalidArgument, \
84                 "Site %s has reached (%d) its maximum allowable slice count (%d)"%(site['name'],
85                                                                                    len(site['slice_ids']),
86                                                                                    site['max_slices'])
87         if not site['enabled']:
88             raise PLCInvalidArgument, "Site %s is disabled and can cannot create slices" % (site['name'])
89
90         slice = Slice(self.api, native)
91         slice['creator_person_id'] = self.caller['person_id']
92         slice['site_id'] = site['site_id']
93         slice.sync()
94
95         # Set Slice HRN
96         root_auth = self.api.config.PLC_HRN_ROOT
97         tags['hrn'] = '.'.join([root_auth, login_base, name.split("_")[1]])
98
99         for (tagname,value) in tags.iteritems():
100             # the tagtype instance is assumed to exist, just check that
101             if not TagTypes(self.api,{'tagname':tagname}):
102                 raise PLCInvalidArgument,"No such TagType %s"%tagname
103             slice_tags=SliceTags(self.api,{'tagname':tagname,'slice_id':slice['slice_id']})
104             if not slice_tags:
105                 AddSliceTag(self.api).__call__(auth,slice['slice_id'],tagname,value)
106             else:
107                 UpdateSliceTag(self.api).__call__(auth,slice_tags[0]['slice_tag_id'],value)
108
109         # take PLC_VSYS_DEFAULTS into account for convenience
110         try:
111             values= [ y for y in [ x.strip() for x in self.api.config.PLC_VSYS_DEFAULTS.split(',') ] if y ]
112             for value in values:
113                 AddSliceTag(self.api).__call__(auth,slice['slice_id'],'vsys',value)
114         except:
115             print >> log, "Could not set vsys tags as configured in PLC_VSYS_DEFAULTS"
116             import traceback
117             traceback.print_exc(file=log)
118         self.event_objects = {'Slice': [slice['slice_id']]}
119         self.message = "Slice %d created" % slice['slice_id']
120
121         return slice['slice_id']