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
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 from PLC.Logger import logger
18 can_update = ['name', 'instantiation', 'url', 'description', 'max_nodes']
20 class AddSlice(Method):
22 Adds a new slice. Any fields specified in slice_fields are used,
23 otherwise defaults are used.
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.
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
34 Returns the new slice_id (> 0) if successful, faults otherwise.
37 roles = ['admin', 'pi']
39 accepted_fields = Row.accepted_fields(can_update, Slice.fields)
40 accepted_fields.update(Slice.tags)
47 returns = Parameter(int, 'New slice_id (> 0) if successful')
49 def call(self, auth, slice_fields):
51 [native,tags,rejected]=Row.split_fields(slice_fields,[Slice.fields,Slice.tags])
54 native = Row.check_fields (native, self.accepted_fields)
56 raise PLCInvalidArgument("Cannot add Slice with column(s) %r"%rejected)
58 # Authenticated function
59 assert self.caller is not None
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_\.]+$'
68 not re.match(good_name, name):
69 raise PLCInvalidArgument("Invalid slice name")
71 # Get associated site details
72 login_base = name.split("_")[0]
73 sites = Sites(self.api, [login_base])
75 raise PLCInvalidArgument("Invalid slice prefix %s in %s"%(login_base,name))
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)
82 if len(site['slice_ids']) >= site['max_slices']:
83 raise PLCInvalidArgument("Site %s has reached (%d) its maximum allowable slice count (%d)"%(site['name'],
84 len(site['slice_ids']),
86 if not site['enabled']:
87 raise PLCInvalidArgument("Site %s is disabled and can cannot create slices" % (site['name']))
89 slice = Slice(self.api, native)
90 slice['creator_person_id'] = self.caller['person_id']
91 slice['site_id'] = site['site_id']
95 root_auth = self.api.config.PLC_HRN_ROOT
96 tags['hrn'] = '.'.join([root_auth, login_base, name.split("_")[1]])
98 for (tagname,value) in tags.items():
99 # the tagtype instance is assumed to exist, just check that
100 if not TagTypes(self.api,{'tagname':tagname}):
101 raise PLCInvalidArgument("No such TagType %s"%tagname)
102 slice_tags=SliceTags(self.api,{'tagname':tagname,'slice_id':slice['slice_id']})
104 AddSliceTag(self.api).__call__(auth,slice['slice_id'],tagname,value)
106 UpdateSliceTag(self.api).__call__(auth,slice_tags[0]['slice_tag_id'],value)
108 # take PLC_VSYS_DEFAULTS into account for convenience
110 values= [ y for y in [ x.strip() for x in self.api.config.PLC_VSYS_DEFAULTS.split(',') ] if y ]
112 AddSliceTag(self.api).__call__(auth,slice['slice_id'],'vsys',value)
114 logger.exception("Could not set vsys tags as configured in PLC_VSYS_DEFAULTS")
115 self.event_objects = {'Slice': [slice['slice_id']]}
116 self.message = "Slice %d created" % slice['slice_id']
118 return slice['slice_id']