From ae247e567468efe3fd5e54488a6fdd32da11fa96 Mon Sep 17 00:00:00 2001 From: Thierry Parmentelat Date: Mon, 6 Dec 2010 16:43:07 +0100 Subject: [PATCH] updated doc and comments --- PLC/Accessors/Accessors_site.py | 13 ++- doc/PLCAPI.xml.in | 145 ++++++++++++++++++++++++++------ 2 files changed, 128 insertions(+), 30 deletions(-) diff --git a/PLC/Accessors/Accessors_site.py b/PLC/Accessors/Accessors_site.py index cce0c51..a9f35be 100644 --- a/PLC/Accessors/Accessors_site.py +++ b/PLC/Accessors/Accessors_site.py @@ -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']) +# +# diff --git a/doc/PLCAPI.xml.in b/doc/PLCAPI.xml.in index 183a059..af48f91 100644 --- a/doc/PLCAPI.xml.in +++ b/doc/PLCAPI.xml.in @@ -165,6 +165,19 @@ +
+ Filtering on a sequence field + A field starting with '&' or '|' should refer to a sequence type; + the semantics is then that the object's value (expected to be a list) + should contain all (&) or any (|) value specified in the corresponding + filter value. + GetPersons ( { '|role_ids' : [ 20, 40 ] } ) + GetPersons ( { '|roles' : ['tech', 'pi'] } ) + GetPersons ( { '&roles' : ['admin', 'tech'] } ) + GetPersons ( { '&roles' : 'tech' } ) + +
+
Sorting and Clipping The following 3 special fields can be used to extract only a subset of the results for pagination: @@ -173,13 +186,23 @@
+
+ All criteria / Any criteria + 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: + GetPersons ( { '-OR' : 'anything', 'site_id':2, '&roles':['admin'] } ) + +
+
Tags The PLC API comes with a feature called tags, 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. @@ -194,23 +217,64 @@ Low level The low level interface to tags relies on the following items: + + A TagType 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 + hostname , tagtypes are named with a + tagname, plus additional information + (category, + description). + + + + description is mostly informative, it + is used by the web interface to provide more details on + the meaning of that tag. + + - - A TagType 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 - hostname , tagtypes are named with a - tagname, 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. - node/config - + + category 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 :). + + - You would then be allowed to attach a value to, say, - a Node, by calling AddNodeTag , and - then as usual change this value with + + The convention is to set in category a set of slash-separated + fields, like the following real examples demonstrate. + +>>> 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 + + + + + roles 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. + + + + 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 AddNodeTag , + and then as usual change this value with UpdateNodeTag , or delete it with DeleteNodeTag . @@ -229,22 +293,38 @@ greatly simplify tags manipulation as they take care of - Lazily create TagTypes when - needed, + Creating and enforcing TagTypes + ; 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). Create or update the, say, NodeTag object, as needed. + In addition, an accessor definition mentions + get_roles (defaults to all_roles), and + set_roles . These values are used as + follows. get_roles is attached to the + Get accessor, so callers that do not have this role cannot run + the Get accessor. set_roles 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. + - + + Site-specific accessors can be defined in /usr/share/plc_api/PLC/Accessors/Accessors_site.py - that will be preserved across updates of the PLCAPI rpm. + and will be preserved across updates of the + plcapi rpm. + - 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.
@@ -319,21 +399,32 @@ False something like the following, using the built-in deployment tag that is created for that purpose: +### 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]} @@ -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 -- 2.43.0