bug fix, tag_type was undefined
[plcapi.git] / PLC / Methods / AddSliceTag.py
index 9a36711..ef78fa6 100644 (file)
@@ -1,25 +1,34 @@
-# $Id$
+#
+# Thierry Parmentelat - INRIA
+#
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
+from PLC.Auth import Auth
+
 from PLC.TagTypes import TagType, TagTypes
 from PLC.Slices import Slice, Slices
 from PLC.Nodes import Node, Nodes
 from PLC.SliceTags import SliceTag, SliceTags
 from PLC.NodeGroups import NodeGroup, NodeGroups
 from PLC.InitScripts import InitScript, InitScripts
-from PLC.Auth import Auth
+
+# need to import so the core classes get decorated with caller_may_write_tag
+from PLC.AuthorizeHelpers import AuthorizeHelpers
 
 class AddSliceTag(Method):
     """
-    Sets the specified attribute of the slice (or sliver, if
-    node_id_or_hostname is specified) to the specified value.
+    Sets the specified tag of the slice to the specified value.
+    If nodegroup is specified, this applies to all slivers of that group.
+    If node is specified, this only applies to a sliver.
+
+    Admins have full access, including on nodegroups.
 
-    Attributes may require the caller to have a particular role in
-    order to be set or changed. Users may only set attributes of
-    slices or slivers of which they are members. PIs may only set
-    attributes of slices or slivers at their sites, or of which they
-    are members. Admins may set attributes of any slice or sliver.
+    Non-admins need to have at least one of the roles 
+    attached to the tagtype. In addition:
+    (*) Users may only set tags of slices or slivers of which they are members. 
+    (*) PIs may only set tags of slices in their site
+    (*) techs cannot use this method
 
     Returns the new slice_tag_id (> 0) if successful, faults
     otherwise.
@@ -34,11 +43,11 @@ class AddSliceTag(Method):
         Mixed(SliceTag.fields['tag_type_id'],
               SliceTag.fields['tagname']),
         Mixed(SliceTag.fields['value'],
-             InitScript.fields['name']),
+              InitScript.fields['name']),
         Mixed(Node.fields['node_id'],
               Node.fields['hostname'],
-             None),
-       Mixed(NodeGroup.fields['nodegroup_id'],
+              None),
+        Mixed(NodeGroup.fields['nodegroup_id'],
               NodeGroup.fields['groupname'])
         ]
 
@@ -55,23 +64,14 @@ class AddSliceTag(Method):
             raise PLCInvalidArgument, "No such tag type %r"%tag_type_id_or_name
         tag_type = tag_types[0]
 
-        if 'admin' not in self.caller['roles']:
-            if self.caller['person_id'] in slice['person_ids']:
-                pass
-            elif 'pi' not in self.caller['roles']:
-                raise PLCPermissionDenied, "Not a member of the specified slice"
-            elif slice['site_id'] not in self.caller['site_ids']:
-                raise PLCPermissionDenied, "Specified slice not associated with any of your sites"
+        # check authorizations
+        slice.caller_may_write_tag (self.api,self.caller,tag_type,node_id_or_hostname,nodegroup_id_or_name)
 
-            if tag_type['min_role_id'] is not None and \
-               min(self.caller['role_ids']) > tag_type['min_role_id']:
-                raise PLCPermissionDenied, "Not allowed to set the specified slice attribute"
-
-       # if initscript is specified, validate value
-       if tag_type['tagname'] in ['initscript']:
-           initscripts = InitScripts(self.api, {'enabled': True, 'name': value})
-           if not initscripts: 
-               raise PLCInvalidArgument, "No such plc initscript %r"%value
+        # if initscript is specified, validate value
+        if tag_type['tagname'] in ['initscript']:
+            initscripts = InitScripts(self.api, {'enabled': True, 'name': value})
+            if not initscripts:
+                raise PLCInvalidArgument, "No such plc initscript %r"%value
 
         slice_tag = SliceTag(self.api)
         slice_tag['slice_id'] = slice['slice_id']
@@ -79,38 +79,60 @@ class AddSliceTag(Method):
         slice_tag['value'] = unicode(value)
 
         # Sliver attribute if node is specified
-        if node_id_or_hostname is not None:
-            nodes = Nodes(self.api, [node_id_or_hostname])
-            if not nodes:
-                raise PLCInvalidArgument, "No such node"
-            node = nodes[0]
-            
-            if node['node_id'] not in slice['node_ids']:
-                raise PLCInvalidArgument, "Node not in the specified slice"
+        if node_id_or_hostname is not None or isinstance(self.caller, Node):
+            node_id = None
+            if isinstance(self.caller, Node):
+                node = self.caller
+                node_id = node['node_id']
+
+            if node_id_or_hostname is not None:
+                nodes = Nodes(self.api, [node_id_or_hostname])
+                if not nodes:
+                    raise PLCInvalidArgument, "No such node"
+                node = nodes[0]
+                if node_id <> None and node_id <> node['node_id']:
+                    raise PLCPermissionDenied, "Not allowed to set another node's sliver attribute"
+                else:
+                    node_id = node['node_id']
+
+            system_slice_tags = SliceTags(self.api, {'tagname': 'system', 'value': '1'}).dict('slice_id')
+            system_slice_ids = system_slice_tags.keys()
+            if slice['slice_id'] not in system_slice_ids and node_id not in slice['node_ids']:
+                raise PLCInvalidArgument, "AddSliceTag: slice %s not on specified node %s nor is it a system slice (%r)"%\
+                    (slice['name'],node['hostname'],system_slice_ids)
             slice_tag['node_id'] = node['node_id']
 
-       # Sliver attribute shared accross nodes if nodegroup is sepcified
-       if nodegroup_id_or_name is not None:
-           nodegroups = NodeGroups(self.api, [nodegroup_id_or_name])
-           if not nodegroups:
-               raise PLCInvalidArgument, "No such nodegroup %r"%nodegroup_id_or_name
-           nodegroup = nodegroups[0]
-       
-           slice_tag['nodegroup_id'] = nodegroup['nodegroup_id']
-
-       # Check if slice attribute alreay exists
-        slice_tags_check = SliceTags(self.api, {'slice_id': slice['slice_id'], 
-                                                            'tagname': tag_type['tagname'], 
-                                                            'value': value})
+        # Sliver attribute shared accross nodes if nodegroup is sepcified
+        if nodegroup_id_or_name is not None:
+            if isinstance(self.caller, Node):
+                raise PLCPermissionDenied, "Not allowed to set nodegroup slice attributes"
+
+            nodegroups = NodeGroups(self.api, [nodegroup_id_or_name])
+            if not nodegroups:
+                raise PLCInvalidArgument, "No such nodegroup %r"%nodegroup_id_or_name
+            nodegroup = nodegroups[0]
+
+            slice_tag['nodegroup_id'] = nodegroup['nodegroup_id']
+
+        # Check if slice attribute already exists
+        slice_tags_check = SliceTags(self.api, {'slice_id': slice['slice_id'],
+                                                'tagname': tag_type['tagname'],
+                                                'value': value})
         for slice_tag_check in slice_tags_check:
+            # do not compare between slice tag and sliver tag
+            if 'node_id' not in slice_tag and slice_tag_check['node_id'] is not None:
+                continue
+            # do not compare between sliver tag and slice tag
+            if 'node_id' in slice_tag and slice_tag['node_id'] is not None and slice_tag_check['node_id'] is None:
+                continue
             if 'node_id' in slice_tag and slice_tag['node_id'] == slice_tag_check['node_id']:
-               raise PLCInvalidArgument, "Sliver attribute already exists"
-           if 'nodegroup_id' in slice_tag and slice_tag['nodegroup_id'] == slice_tag_check['nodegroup_id']:
-               raise PLCInvalidArgument, "Slice attribute already exists for this nodegroup"
+                raise PLCInvalidArgument, "Sliver attribute already exists"
+            if 'nodegroup_id' in slice_tag and slice_tag['nodegroup_id'] == slice_tag_check['nodegroup_id']:
+                raise PLCInvalidArgument, "Slice attribute already exists for this nodegroup"
             if node_id_or_hostname is None and nodegroup_id_or_name is None:
                 raise PLCInvalidArgument, "Slice attribute already exists"
 
         slice_tag.sync()
-       self.event_objects = {'SliceTag': [slice_tag['slice_tag_id']]}
+        self.event_objects = {'SliceTag': [slice_tag['slice_tag_id']]}
 
         return slice_tag['slice_tag_id']