Rationalize: added associate functions
authorTony Mack <tmack@cs.princeton.edu>
Tue, 6 Nov 2007 03:43:42 +0000 (03:43 +0000)
committerTony Mack <tmack@cs.princeton.edu>
Tue, 6 Nov 2007 03:43:42 +0000 (03:43 +0000)
PLC/Slices.py

index 99054c8..1a1786c 100644 (file)
@@ -3,13 +3,14 @@ import time
 import re
 
 from PLC.Faults import *
-from PLC.Parameter import Parameter
+from PLC.Parameter import Parameter, Mixed
 from PLC.Filter import Filter
 from PLC.Debug import profile
 from PLC.Table import Row, Table
 from PLC.SliceInstantiations import SliceInstantiation, SliceInstantiations
 from PLC.Nodes import Node
 from PLC.Persons import Person, Persons
+from PLC.SliceAttributes import SliceAttribute
 
 class Slice(Row):
     """
@@ -39,6 +40,12 @@ class Slice(Row):
         'peer_id': Parameter(int, "Peer to which this slice belongs", nullok = True),
         'peer_slice_id': Parameter(int, "Foreign slice identifier at peer", nullok = True),
         }
+    related_fields = {
+       'persons': [Mixed(Parameter(int, "Person identifier"),
+                         Parameter(str, "Email address"))],
+       'nodes': [Mixed(Parameter(int, "Node identifier"),
+                       Parameter(str, "Fully qualified hostname"))]
+       }
     # for Cache
     class_key = 'name'
     foreign_fields = ['instantiation', 'url', 'description', 'max_nodes', 'expires']
@@ -97,6 +104,127 @@ class Slice(Row):
     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 += 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 += nodes.keys()
+       
+       # Add new ids, remove stale ids
+       if self['node_ids'] != node_ids:
+           from PLC.Methods.AddSliceToNodes import AddSliceToNodes
+           from PLC.Methods.DeleteSliceFromNodes import DeleteSliceFromNodes
+           new_nodes = set(node_ids).difference(self['node_ids'])
+           stale_nodes = set(self['node_ids']).difference(node_ids)
+           
+           if new_nodes:
+               AddSliceToNodes.__call__(AddSliceToNodes(self.api), auth, self['slice_id'], list(new_nodes))
+           if stale_nodes:
+               DeleteSliceFromNodes.__call__(DeleteSliceFromNodes(self.api), auth, self['slice_id'], list(stale_nodes))                        
+    def associate_slice_attributes(self, auth, fields, value):
+       """
+       Deletes slice_attribute_ids not found in value list (using DeleteSliceAttribute). 
+       Adds slice_attributes if slice_fields w/o slice_id is found (using AddSliceAttribute).
+       Updates slice_attribute if slice_fields w/ slice_id is found (using UpdateSlceiAttribute).  
+       """
+       
+       assert 'slice_attribute_ids' in self
+       assert isinstance(value, list)
+
+       (attribute_ids, blank, attributes) = self.separate_types(value)
+       
+       # There is no way to add attributes by id. They are
+       # associated with a slice when they are created.
+       # So we are only looking to delete here 
+       if self['slice_attribute_ids'] != attribute_ids:
+           from PLC.Methods.DeleteSliceAttribute import DeleteSliceAttribute
+           stale_attributes = set(self['slice_attribute_ids']).difference(attribute_ids)
+       
+           for stale_attribute in stale_attributes:
+               DeleteSliceAttribute.__call__(DeleteSliceAttribute(self.api), auth, stale_attribute['slice_attribute_id'])              
+       
+       # If dictionary exists, we are either adding new
+        # attributes or updating existing ones.
+        if attributes:
+            from PLC.Methods.AddSliceAttribute import AddSliceAttribute
+            from PLC.Methods.UpdateSliceAttribute import UpdateSliceAttribute
+       
+           added_attributes = filter(lambda x: 'slice_attribute_id' not in x, attributes)
+           updated_attributes = filter(lambda x: 'slice_attribute_id' in x, attributes)
+
+           for added_attribute in added_attributes:
+               if 'attribute_type' in added_attribute:
+                   type = added_attribute['attribute_type']
+               elif 'attribute_type_id' in added_attribute:
+                   type = added_attribute['attribute_type_id']
+               else:
+                   raise PLCInvalidArgument, "Must specify attribute_type or attribute_type_id"
+
+               if 'value' in added_attribute:
+                   value = added_attribute['value']
+               else:
+                   raise PLCInvalidArgument, "Must specify a value"
+               
+               if 'node_id' in added_attribute:
+                   node_id = added_attribute['node_id']
+               else:
+                   node_id = None
+
+               if 'nodegroup_id' in added_attribute:
+                   nodegroup_id = added_attribute['nodegroup_id']
+               else:
+                   nodegroup_id = None 
+               AddSliceAttribute.__call__(AddSliceAttribute(self.api), auth, self['slice_id'], type, value, node_id, nodegroup_id)
+           for updated_attribute in updated_attributes:
+               attribute_id = updated_attribute.pop('slice_attribute_id')
+               if attribute_id not in self['slice_attribute_ids']:
+                   raise PLCInvalidArgument, "Attribute doesnt belong to this slice" 
+               else:
+                   UpdateSliceAttribute.__call__(UpdateSliceAttribute(self.api), auth, attribute_id, updated_attribute)                 
+       
     def sync(self, commit = True):
         """
         Add or update a slice.
@@ -126,6 +254,7 @@ class Slice(Row):
         self['is_deleted'] = True
         self.sync(commit)
 
+
 class Slices(Table):
     """
     Representation of row(s) from the slices table in the