summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Minar <miminar@redhat.com>2014-03-17 15:35:46 +0100
committerMichal Minar <miminar@redhat.com>2014-03-17 16:26:36 +0100
commitb76c8e39759316247e34a1a54aad07097691e38c (patch)
tree09b64b2affec3097cb8dcafab661b5865a90c10b
parentaf8b59124f1eab1d21765e5b1a3f2443fc5ff70b (diff)
downloadopenlmi-scripts-b76c8e39759316247e34a1a54aad07097691e38c.tar.gz
openlmi-scripts-b76c8e39759316247e34a1a54aad07097691e38c.tar.xz
openlmi-scripts-b76c8e39759316247e34a1a54aad07097691e38c.zip
updated doc for version requirement specification
-rw-r--r--doc/command-properties.rst46
-rw-r--r--doc/script-development.rst117
2 files changed, 163 insertions, 0 deletions
diff --git a/doc/command-properties.rst b/doc/command-properties.rst
index cfba558..d45f8d9 100644
--- a/doc/command-properties.rst
+++ b/doc/command-properties.rst
@@ -288,6 +288,8 @@ They are:
``FMT_HUMAN_FRIENDLY`` : ``bool`` (defaults to ``False``)
Forces the output to be more pleasant to read by human beings.
+.. _specifying_requirements:
+
Command specific properties
---------------------------
Each command class can have its own specific properties. Let's take a look on
@@ -350,6 +352,50 @@ them.
to behave exactly as ``All`` subcommand in case that no command
is given on command line.
+.. _lmi_select_command_properties:
+
+``LmiSelectCommand`` properties
+-------------------------------
+Following properties allow to define profile and class requirements for
+commands.
+
+.. _select:
+
+``SELECT`` : ``list`` (mandatory)
+ Is a list of pairs ``(condition, command)`` where ``condition`` is an
+ expression in *LMIReSpL* language. And ``command`` is either a string with
+ absolute path to command that shall be loaded or the command class itself.
+
+ Small example: ::
+
+ SELECT = [
+ ( 'OpenLMI-Hardware < 0.4.2'
+ , 'lmi.scripts.hardware.pre042.PreCmd'
+ )
+ , ('OpenLMI-Hardware >= 0.4.2 & class LMI_Chassis == 0.3.0'
+ , HwCmd
+ )
+ ]
+
+ It says: Let the ``PreHwCmd`` command do the job on brokers having
+ ``openlmi-hardware`` package older than ``0.4.2``. Use the ``HwCmd``
+ anywhere else where also the ``LMI_Chassis`` CIM class in version ``0.3.0``
+ is available.
+
+ First matching condition wins and assigned command will be passed all the
+ arguments. If no condition can be satisfied and no default command is set,
+ an exception will be raised.
+
+ .. seealso::
+ Definition of *LMIReSpL* mini-language:
+ :py:mod:`~lmi.scripts.common.versioncheck.parser`
+
+.. _default:
+
+``DEFAULT`` : ``string`` or reference to command class
+ Defines fallback command used in case no condition in ``SELECT`` can be
+ satisfied.
+
.. _lmi_lister_properties:
``LmiLister`` properties
diff --git a/doc/script-development.rst b/doc/script-development.rst
index 5871aa1..040895f 100644
--- a/doc/script-development.rst
+++ b/doc/script-development.rst
@@ -306,6 +306,116 @@ of options to it. In this way we can create arbitrarily tall command trees.
Top-level command is nothing else than a subclass of ``LmiCommandMultiplexer``.
+Specifying profile and class requirements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Most commands require some provider installed on managed machine to work
+properly. Each such provider should be represented by an instance of
+``CIM_RegisteredProfile`` on remote broker. This instance looks like
+this (in MOF syntax): ::
+
+ instance of CIM_RegisteredProfile {
+ InstanceID = "OpenLMI+OpenLMI-Software+0.4.2";
+ RegisteredOrganization = 1;
+ OtherRegisteredOrganization = "OpenLMI";
+ RegisteredVersion = "0.4.2";
+ AdvertiseTypes = [2];
+ RegisteredName = "OpenLMI-Software";
+ };
+
+We are interested just in ``RegisteredName`` and ``RegisteredVersion``
+properties that we'll use for requirement specification.
+
+Requirement is written in *LMIReSpL* language. For its formal definition
+refer to documentation of :py:mod:`~lmi.scripts.common.versioncheck.parser`.
+Since the language is quite simple, few examples should suffice:
+
+ ``'OpenLMI-Software < 0.4.2'``
+ Requires OpenLMI Software provider to be installed in version lower
+ than ``0.4.2``.
+ ``'OpenLMI-Hardware == 0.4.2 & Openlmi-Software >= 0.4.2'``
+ Requires both hardware and software providers to be installed in
+ particular version. Short-circuit evaluation is utilized here. It
+ means that in this example OpenLMI Software won't be queried unless
+ OpenLMI Hardware is installed and having desired version.
+ ``'profile "OpenLMI-Logical File" > 0.4.2'``
+ If you have spaces in the name of profile, surround it in double
+ quotes. ``profile`` keyword is optional. It could be also present in
+ previous examples.
+
+Version requirements are not limited to profiles only. CIM classes may be
+specified as well:
+
+ ``'class LMI_SoftwareIdentity >= 0.3.0 & OpenLMI-LogicalFile'``
+ In case of class requirements the ``class`` keyword is mandatory. As
+ you can see, version requirement is optional.
+ ``'! (class LMI_SoftwareIdentity | class LMI_UnixFile)'``
+ Complex expressions can be created with the use of brackets and other
+ operators.
+
+One requirement is evaluated in these steps:
+
+ Profile requirement
+ 1. Query ``CIM_RegisteredProfile`` for instances with
+ ``RegisteredName`` matching given name. If found, go to 2. Otherwise
+ query ``CIM_RegisteredSubProfile`` [#subprof]_ for instances with
+ ``RegisteredName`` matching given name. If not found return
+ ``False``.
+ 2. Select the (sub)profile with highest version and go to 3.
+ 3. If the requirement has version specification then compare it to the
+ value of ``RegisteredVersion`` using given operator. If the relation
+ does not apply, return ``False``.
+ 4. Return ``True``.
+
+ Class requirement
+ 1. Get specified class. If not found, return ``False``.
+ 2. If the requirement has version specification then compare it to the
+ value of ``Version`` [#missing_version]_ qualifier of
+ obtained class using given operator. And if the relation
+ does not apply, return ``False``.
+ 3. Return ``True``.
+
+Now let's take a look, where these requirements can be specified.
+There is special select command used to specify which command to load
+for particular version on remote broker. It's defined like this: ::
+
+ from lmi.scripts.common.command import LmiSelectCommand
+
+ class SoftwareCMD(LmiSelectCommand):
+
+ SELECT = [
+ ( 'OpenLMI-Software >= 0.4.2' & 'OpenLMI-LogicalFile'
+ , 'lmi.scripts.software.current.SwLFCmd')
+ , ( 'OpenLMI-Software >= 0.4.2'
+ , 'lmi.scripts.software.current.SwCmd')
+ , ('OpenLMI-Software', 'lmi.scripts.software.pre042.SwCmd')
+ ]
+
+It says to load ``SwLFCmd`` command in case both OpenLMI Software and
+OpenLMI LogicalFile providers are installed. If not, load the ``SwCMD`` from
+``current`` module for OpenLMI Software with recent version and fallback to
+``SwCmd`` for anything else. If the OpenLMI Software provider is not available
+at all, no command will be loaded and exception will be raised.
+
+Previous command could be used as an entry point in your ``setup.py`` script
+(see the :ref:`entry_points`). There is also a utility that makes it look
+better: ::
+
+ from lmi.scripts.common.command import select_command
+
+ SoftwareCMD = select_command('SoftwareCMD',
+ ( 'OpenLMI-Software >= 0.4.2' & 'OpenLMI-LogicalFile'
+ , 'lmi.scripts.software.current.SwLFCmd'),
+ ( 'OpenLMI-Software >= 0.4.2', 'lmi.scripts.software.current.SwCmd'),
+ ('OpenLMI-Software', 'lmi.scripts.software.pre042.SwCmd')
+ )
+
+.. seealso::
+ Documentation of
+ :py:class:`~lmi.scripts.common.command.select.LmiSelectCommand` and
+ :py:class:`~lmi.scripts.common.command.helper.select_command`.
+
+ And also notes on related :ref:`lmi_select_command_properties`.
+
Command wrappers module
~~~~~~~~~~~~~~~~~~~~~~~
Usually consists of:
@@ -413,6 +523,8 @@ Follows a minimal example of ``setup.py`` script for service library. ::
.. _entry_points:
+Entry points
+~~~~~~~~~~~~
The most notable argument here is ``entry_points`` which is a dictionary
containing python namespaces where plugins are registered. In this case, we
register single top-level command (see `Top-level commands`_) called
@@ -541,6 +653,11 @@ Tutorial
.. [#] Precisely in an ``__init__.py`` module of this package.
.. [#] These names must exactly match the names in usage strings.
+.. [#subprof] This is a subclass of ``CIM_RegisteredProfile`` thus it has the
+ same properties.
+.. [#missing_version] If the Version qualifier is missing, -1 will be used
+ for comparison instead of empty string.
+
.. ****************************************************************************
.. _CIM: http://dmtf.org/standards/cim