+ related_fields = {
+ 'persons': [Mixed(Parameter(int, "Person identifier"),
+ Parameter(str, "Email address"))],
+ 'nodes': [Mixed(Parameter(int, "Node identifier"),
+ Parameter(str, "Fully qualified hostname"))]
+ }
+
+ view_tags_name="view_slice_tags"
+ tags = {}
+
+ def validate_name(self, name):
+ # N.B.: Responsibility of the caller to ensure that login_base
+ # portion of the slice name corresponds to a valid site, if
+ # desired.
+
+ # 1. Lowercase.
+ # 2. Begins with login_base (letters or numbers).
+ # 3. Then single underscore after login_base.
+ # 4. Then letters, numbers, or underscores.
+ good_name = r'^[a-z0-9\.]+_[a-zA-Z0-9_\.]+$'
+ if not name or \
+ not re.match(good_name, name):
+ raise PLCInvalidArgument("Invalid slice name")
+
+ conflicts = Slices(self.api, [name])
+ for slice in conflicts:
+ if 'slice_id' not in self or self['slice_id'] != slice['slice_id']:
+ raise PLCInvalidArgument("Slice name already in use, %s"%name)
+
+ return name
+
+ def validate_instantiation(self, instantiation):
+ instantiations = [row['instantiation'] for row in SliceInstantiations(self.api)]
+ if instantiation not in instantiations:
+ raise PLCInvalidArgument("No such instantiation state")
+
+ return instantiation
+
+ validate_created = Row.validate_timestamp
+
+ def validate_expires(self, expires):
+ # N.B.: Responsibility of the caller to ensure that expires is
+ # not too far into the future.
+ check_future = not ('is_deleted' in self and self['is_deleted'])
+ return Timestamp.sql_validate( expires, check_future = check_future)
+
+ add_person = Row.add_object(Person, 'slice_person')
+ remove_person = Row.remove_object(Person, 'slice_person')
+
+ add_node = Row.add_object(Node, 'slice_node')
+ remove_node = Row.remove_object(Node, 'slice_node')
+
+ add_to_node_whitelist = Row.add_object(Node, 'node_slice_whitelist')
+ delete_from_node_whitelist = Row.remove_object(Node, 'node_slice_whitelist')
+
+ def associate_persons(self, auth, field, value):
+ """
+ Adds persons found in value list to this slice (using AddPersonToSlice).
+ Deletes persons not found in value list from this slice (using DeletePersonFromSlice).
+ """
+
+ assert 'person_ids' in self
+ assert 'slice_id' in self
+ assert isinstance(value, list)
+
+ (person_ids, emails) = self.separate_types(value)[0:2]
+
+ # Translate emails into person_ids
+ if emails:
+ persons = Persons(self.api, emails, ['person_id']).dict('person_id')
+ person_ids += list(persons.keys())
+
+ # Add new ids, remove stale ids
+ if self['person_ids'] != person_ids:
+ from PLC.Methods.AddPersonToSlice import AddPersonToSlice
+ from PLC.Methods.DeletePersonFromSlice import DeletePersonFromSlice
+ new_persons = set(person_ids).difference(self['person_ids'])
+ stale_persons = set(self['person_ids']).difference(person_ids)
+
+ for new_person in new_persons:
+ AddPersonToSlice.__call__(AddPersonToSlice(self.api), auth, new_person, self['slice_id'])
+ for stale_person in stale_persons:
+ DeletePersonFromSlice.__call__(DeletePersonFromSlice(self.api), auth, stale_person, self['slice_id'])
+
+ def associate_nodes(self, auth, field, value):
+ """
+ Adds nodes found in value list to this slice (using AddSliceToNodes).
+ Deletes nodes not found in value list from this slice (using DeleteSliceFromNodes).
+ """
+
+ from PLC.Nodes import Nodes
+
+ assert 'node_ids' in self
+ assert 'slice_id' in self
+ assert isinstance(value, list)
+
+ (node_ids, hostnames) = self.separate_types(value)[0:2]
+
+ # Translate hostnames into node_ids
+ if hostnames:
+ nodes = Nodes(self.api, hostnames, ['node_id']).dict('node_id')
+ node_ids += list(nodes.keys())