updated doc and comments
authorThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Mon, 6 Dec 2010 15:43:07 +0000 (16:43 +0100)
committerThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Mon, 6 Dec 2010 15:43:07 +0000 (16:43 +0100)
PLC/Accessors/Accessors_site.py
doc/PLCAPI.xml.in

index cce0c51..a9f35be 100644 (file)
@@ -32,9 +32,18 @@ import sys
 current_module = sys.modules[__name__]
 
 #### example : attach vlan ids on interfaces
-# The third argument expose_in_api is a boolean flag that tells whether this tag may be handled
-#   through the Add/Get/Update methods as a native field
 #
 #define_accessors(current_module, Interface, "Vlan", "vlan",
 #                  "interface/general", "tag for setting VLAN id",
 #                  get_roles=all_roles, set_roles=tech_roles)
+#
+# The optional expose_in_api is a boolean flag that tells whether this tag may be handled
+#   through the Add/Get/Update methods as a native field
+# e.g. 
+#define_accessors(current_module, Node, "Foo", "foo",
+#                  "node/example", "my own description for foo",
+#                  get_roles=all_roles, set_roles=all_roles)
+# will let you do
+# GetNodes ( {'foo':'*bar*'},['hostname','foo'])
+#
+# 
index 183a059..af48f91 100644 (file)
        </para>
       </section>
 
+      <section id="sequence">
+       <title> Filtering on a sequence field </title>
+       <para> A field starting with '&amp;' or '|' should refer to a sequence type;
+      the semantics is then that the object's value (expected to be a list)
+      should contain all (&amp;) or any (|) value specified in the corresponding
+      filter value. 
+      <programlisting> GetPersons ( { '|role_ids' : [ 20, 40 ] } ) </programlisting>
+      <programlisting> GetPersons ( { '|roles' : ['tech', 'pi'] } ) </programlisting>
+      <programlisting> GetPersons ( { '&amp;roles' : ['admin', 'tech'] } ) </programlisting>
+      <programlisting> GetPersons ( { '&amp;roles' : 'tech' } ) </programlisting>
+       </para>
+      </section>
+
       <section id="sort-clip">
        <title> Sorting and Clipping </title> 
        <para> The following 3 special fields can be used to extract only a subset of the results for pagination:
       </section>
     </section>
 
+    <section id="and-or">
+      <title> All criteria / Any criteria </title>
+      <para> The default in the vast majority of the code is to select
+      objects that match ALL the criteria specified in the struct. It
+      is possible to search for objects that match ANY of these by
+      adding the special '-OR' key (the value is then ignored), as in:
+      <programlisting> GetPersons ( { '-OR' : 'anything', 'site_id':2, '&amp;roles':['admin'] } ) </programlisting>
+      </para>
+    </section>
+
     <section id="tags">
       <title>Tags</title>
 
       <para> The PLC API comes with a feature called
       <emphasis>tags</emphasis>, that basically aims at supporting an
       extensible data model. A few classes (as of this writing, Nodes,
-      Interfaces and Slices) are eligible for being dynamically
+      Interfaces, Sites, Persons and Slices) are eligible for being dynamically
       extended beyond the basic set of fields that are built into the
       database schema.</para>
 
        <title> Low level </title>
        <para> The low level interface to tags relies on the following items:
       <itemizedlist>
+       <listitem><para> 
+         A <emphasis> TagType </emphasis> object basically models a
+         new column that needs to be added to other objects. In much
+         the same way as nodes are named through a <emphasis>
+         hostname </emphasis>, tagtypes are named with a
+         <emphasis>tagname</emphasis>, plus additional information
+         (<emphasis>category</emphasis>,
+         <emphasis>description</emphasis>).  
+       </para> </listitem>
+
+       <listitem><para>
+         <emphasis>description</emphasis> is mostly informative, it
+           is used by the web interface to provide more details on
+           the meaning of that tag. 
+       </para> </listitem>
+
        <listitem>
-         <para> 
-           A <emphasis> TagType </emphasis> object basically models a
-           new column that needs to be added to other objects. In
-           much the same way as nodes are named through a <emphasis>
-           hostname </emphasis>, tagtypes are named with a
-           <emphasis>tagname</emphasis>, plus additional information
-           (category, description) that is mostly informative. The
-           convention is to use a category that depicts the type of
-           objects that the tag type, like e.g. <emphasis>
-           node/config </emphasis> 
-         </para>
+         <para>
+         <emphasis>category</emphasis> is used in a variety of ways,
+         in the web interface again.  Over time this has become a
+         means to attach various information to a tag type, so it is
+         used as some sort of a poorman's tag tag system :).
+        </para>
        </listitem>
+
        <listitem>
-         <para> You would then be allowed to attach a value to, say,
-         a Node, by calling <emphasis> AddNodeTag </emphasis>, and
-         then as usual change this value with <emphasis>
+       <para>
+          The convention is to set in category a set of slash-separated
+          fields, like the following real examples demonstrate.
+<programlisting> 
+>>> tagnames=['arch','fcdistro','hrn','hmac','exempt_node_until']
+>>> for tt in GetTagTypes(tagnames,['tagname','category']): 
+>>> ... print "tagname=%-18s category=%s"%(tt['tagname'], tt['category'])
+tagname=hrn                category=node/sfa
+tagname=hmac               category=slice/auth  
+tagname=exempt_node_until  category=node/myops
+tagname=fcdistro           category=node/slice/config/ui/header=f/rank=w
+tagname=arch               category=node/slice/config/ui/header=A/rank=x
+</programlisting>
+        </para>
+       </listitem>
+
+       <listitem> <para> <emphasis>roles</emphasis> may also be
+       attached to a given tag_type (use AddRoleToTagType or
+       DeleteRoleFromTagType). This is an evolution over the former
+       system based on so-called 'min_role_id', and now any set of
+       roles may be mentioned. More importantly, each type (Node,
+       Person, ...) implements its own policy to let or not non-admin
+       callers change their tags. For example in the current
+       implementation, non-admin users can only change their own
+       person tags. See PLC/AuthorizeHelpers.py for that code.
+       </para> </listitem>
+
+       <listitem>
+         <para> The low-level method for managaing tags is then, once
+         the TagType is known to the system, to attach a value to,
+         say, a Node, by calling <emphasis> AddNodeTag </emphasis>,
+         and then as usual change this value with <emphasis>
          UpdateNodeTag </emphasis>, or delete it with <emphasis>
          DeleteNodeTag </emphasis>. </para>
        </listitem>
       greatly simplify tags manipulation as they take care of
       <itemizedlist>
        <listitem>
-         <para> Lazily create <emphasis> TagTypes </emphasis> when
-         needed,</para>
+         <para> Creating and enforcing <emphasis> TagTypes
+         </emphasis>; each time you restart your plc, the tag_types
+         mentioned in accessor definitions are created and checked
+         (in terms of the category, description and roles defined in
+         the various calls to define_accessors).</para>
        </listitem>
        <listitem>
          <para> Create or update the, say, <emphasis> NodeTag
          </emphasis> object, as needed.</para>
        </listitem>
+       <listitem> <para> In addition, an accessor definition mentions
+       <emphasis> get_roles </emphasis> (defaults to all_roles), and
+       <emphasis>set_roles </emphasis>. These values are used as
+       follows. <emphasis> get_roles </emphasis> is attached to the
+       Get accessor, so callers that do not have this role cannot run
+       the Get accessor. <emphasis> set_roles </emphasis> is attached
+       to the Set accessor, as well as to the corresponding TagType,
+       which in turn is used for checking write access to the tag
+       type. </para>
+       </listitem>
       </itemizedlist>
-      </para>
+    </para>
+
       <para> <emphasis> Site-specific </emphasis> accessors can be
       defined in <emphasis>
       /usr/share/plc_api/PLC/Accessors/Accessors_site.py </emphasis>
-      that will be preserved across updates of the PLCAPI rpm. 
+      and will be preserved across updates of the
+      <emphasis>plcapi</emphasis> rpm.
       </para>
+
       <para> 
-       This mechanism does not currently support setting slice
+       The accessors mechanism does not currently support setting slice
        tags that apply only on a given node or nodegroup. 
       </para>
       </section>
@@ -319,21 +399,32 @@ False
     something like the following, using the built-in <literal>
     deployment </literal> tag that is created for that purpose:
 <programlisting>
+### creating node groups
 >>> AddNodeGroup('alphanodes','deployment','alpha')
 21
 >>> AddNodeGroup('betanodes','deployment','beta')
-21
+22
+### checking contents (no node has 'deployment' set to either 'alpha' or 'beta' yet)
 >>> for ng in GetNodeGroups(['alphanodes','betanodes'],['groupname','node_ids']): print ng
 {'groupname': u'alphanodes', 'node_ids': []}
 {'groupname': u'betanodes', 'node_ids': []}
+
+### displaying node ids 
+>>> for n in GetNodes({'hostname':'*.inria.fr'},['hostname','node_id']): print n
+{'hostname': u'vnode01.inria.fr', 'node_id': 1}
+{'hostname': u'vnode02.inria.fr', 'node_id': 2}
+
+### setting 'deployment' for these two nodes
 >>> SetNodeDeployment('vnode01.inria.fr','alpha')
 >>> for ng in GetNodeGroups(['alphanodes','betanodes'],['groupname','node_ids']): print ng
 {'groupname': u'alphanodes', 'node_ids': [1]}
 {'groupname': u'betanodes', 'node_ids': []}
->>> SetNodeDeployment('vnode01.inria.fr','beta')
+>>> SetNodeDeployment('vnode02.inria.fr','beta')
+
+### checking contents again
 >>> for ng in GetNodeGroups(['alphanodes','betanodes'],['groupname','node_ids']): print ng
-{'groupname': u'alphanodes', 'node_ids': []}
-{'groupname': u'betanodes', 'node_ids': [1]}
+{'groupname': u'alphanodes', 'node_ids': [1]}
+{'groupname': u'betanodes', 'node_ids': [2]}
 </programlisting>
 </para>  
 
@@ -435,14 +526,12 @@ nodes = plc.GetNodes([121], ['node_id', 'hostname'])
 import xmlrpclib
 
 plc_host='www.planet-lab.eu'
-login='thierry.parmentelat@sophia.inria.fr'
-password='xxxxxxxx'
 
 slice_name='inria_heartbeat'
 
 auth = { 'AuthMethod' : 'password',
-           'Username' : login,
-           'AuthString' : password,
+         'Username' : 'thierry.parmentelat@inria.fr',
+         'AuthString' : 'xxxxxx',
 }
 
 api_url="https://%s:443/PLCAPI/"%plc_host