summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Minar <miminar@redhat.com>2013-10-07 17:27:16 +0200
committerMichal Minar <miminar@redhat.com>2013-10-08 12:54:18 +0200
commit100b3e0d5747b5da7c7b07aad14506a2d7b38f39 (patch)
treeacb1a0743f062127f30221645354b262776b5998
parentd6c05eaa4feb338305405d0ab9c7bd343544cbfb (diff)
downloadopenlmi-providers-100b3e0d5747b5da7c7b07aad14506a2d7b38f39.tar.gz
openlmi-providers-100b3e0d5747b5da7c7b07aad14506a2d7b38f39.tar.xz
openlmi-providers-100b3e0d5747b5da7c7b07aad14506a2d7b38f39.zip
added admin documentation for software
-rw-r--r--src/software/doc/admin/Makefile159
-rw-r--r--src/software/doc/admin/conf.py294
-rw-r--r--src/software/doc/admin/dmtf.rst231
-rw-r--r--src/software/doc/admin/index.rst27
-rw-r--r--src/software/doc/admin/mof/Makefile15
-rw-r--r--src/software/doc/admin/mof/header.txt2
-rw-r--r--src/software/doc/admin/usage.rst617
7 files changed, 1345 insertions, 0 deletions
diff --git a/src/software/doc/admin/Makefile b/src/software/doc/admin/Makefile
new file mode 100644
index 0000000..bad1f79
--- /dev/null
+++ b/src/software/doc/admin/Makefile
@@ -0,0 +1,159 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp \
+ devhelp epub latex latexpdf text man changes linkcheck doctest \
+ gettext mof
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " texinfo to make Texinfo files"
+ @echo " info to make Texinfo files and run them through makeinfo"
+ @echo " gettext to make PO message catalogs"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+
+mof:
+ make -C mof
+
+clean:
+ -rm -rf $(BUILDDIR)/*
+ make -C mof clean
+
+html: mof
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/OpenLMISoftwareProvider.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/OpenLMISoftwareProvider.qhc"
+
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/OpenLMISoftwareProvider"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/OpenLMISoftwareProvider"
+ @echo "# devhelp"
+
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex: mof
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf: mof
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo
+ @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+ @echo "Run \`make' in that directory to run these through makeinfo" \
+ "(use \`make info' here to do that automatically)."
+
+info:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo "Running Texinfo files through makeinfo..."
+ make -C $(BUILDDIR)/texinfo info
+ @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+ $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+ @echo
+ @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
diff --git a/src/software/doc/admin/conf.py b/src/software/doc/admin/conf.py
new file mode 100644
index 0000000..16381bb
--- /dev/null
+++ b/src/software/doc/admin/conf.py
@@ -0,0 +1,294 @@
+# -*- coding: utf-8 -*-
+#
+# OpenLMI Software Provider documentation build configuration file, created by
+# sphinx-quickstart on Thu Oct 3 14:25:59 2013.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+def setup(app):
+ # Register new option to include class list and class tree in index.rst
+ app.add_config_value('includeClasses', 'True', True)
+includeClasses = True
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.pngmath', 'sphinx.ext.ifconfig']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'OpenLMI Software Provider'
+copyright = u'2013, Michal Minar'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '0.3.0'
+# The full version, including alpha/beta/rc tags.
+release = '0.3.0'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+html_theme = 'openlmitheme'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+html_theme_path = ["../../../../tools"]
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'OpenLMISoftwareProviderdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ('index', 'OpenLMISoftwareProvider.tex', u'OpenLMI Software Provider Documentation',
+ u'Michal Minar', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('index', 'openlmisoftwareprovider', u'OpenLMI Software Provider Documentation',
+ [u'Michal Minar'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output ------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ ('index', 'OpenLMISoftwareProvider', u'OpenLMI Software Provider Documentation',
+ u'Michal Minar', 'OpenLMISoftwareProvider', 'One line description of project.',
+ 'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+
+# -- Options for Epub output ---------------------------------------------------
+
+# Bibliographic Dublin Core info.
+epub_title = u'OpenLMI Software Provider'
+epub_author = u'Michal Minar'
+epub_publisher = u'Michal Minar'
+epub_copyright = u'2013, Michal Minar'
+
+# The language of the text. It defaults to the language option
+# or en if the language is not set.
+#epub_language = ''
+
+# The scheme of the identifier. Typical schemes are ISBN or URL.
+#epub_scheme = ''
+
+# The unique identifier of the text. This can be a ISBN number
+# or the project homepage.
+#epub_identifier = ''
+
+# A unique identification for the text.
+#epub_uid = ''
+
+# A tuple containing the cover image and cover page html template filenames.
+#epub_cover = ()
+
+# HTML files that should be inserted before the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_pre_files = []
+
+# HTML files shat should be inserted after the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_post_files = []
+
+# A list of files that should not be packed into the epub file.
+#epub_exclude_files = []
+
+# The depth of the table of contents in toc.ncx.
+#epub_tocdepth = 3
+
+# Allow duplicate toc entries.
+#epub_tocdup = True
+
+
+# Example configuration for intersphinx: refer to the Python standard library.
+intersphinx_mapping = {'http://docs.python.org/': None}
diff --git a/src/software/doc/admin/dmtf.rst b/src/software/doc/admin/dmtf.rst
new file mode 100644
index 0000000..d048f78
--- /dev/null
+++ b/src/software/doc/admin/dmtf.rst
@@ -0,0 +1,231 @@
+DMTF profiles
+=============
+OpenLMI Software providers implement two *DMTF* profiles:
+
+ * `Software Inventory Profile`_
+ * `Software Update Profile`_
+
+Software Inventory Profile
+--------------------------
+Implemented *DMTF* version: ``1.0.1``
+
+Described by `DSP1023`_
+
+The Software Inventory Profile describes the CIM schema elements required to
+provide an inventory of installed BIOS, firmware, drivers, and related
+software in a managed system. This profile also describes the CIM schema
+elements required to represent the software that can be installed on a
+managed system.
+
+
+Not implemented optional features
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+This implementation does not support:
+
+ Representing a Software Bundle
+ Software bundle is represented by LMI_SoftwareIndentity instance
+ having ``"Software Bundle"`` value present in its ``Classifications``
+ property. It shall prepresent software groups. It extends the profile
+ for subclasses of ``CIM_OrderedComponent``.
+
+ Representing Installation Dependencies
+ Dependencies between software packages are also unimplemented. This
+ also extends the profile for subclasses of ``CIM_OrderedDependency``
+ referencing :ref:`CIM-SoftwareIdentity` instances.
+
+Deviations
+~~~~~~~~~~
+Version Comparison
+^^^^^^^^^^^^^^^^^^
+Version comparison is based on different approach than in *Software Inventory
+Profile* where the following properties are present to uniquely specify
+package version:
+
+ * ``uint16`` :ref:`MajorVersion<CIM-SoftwareIdentity-MajorVersion>`
+ * ``uint16`` :ref:`MinorVersion<CIM-SoftwareIdentity-MinorVersion>`
+ * ``uint16`` :ref:`RevisionNumber<CIM-SoftwareIdentity-RevisionNumber>`
+ * ``uint16`` :ref:`BuildNumber<CIM-SoftwareIdentity-BuildNumber>`
+
+And also a :ref:`VersionString<LMI-SoftwareIdentity-VersionString>` property
+which is a composition of previous ones separed with dots.
+
+Unfortunately versioning of RPM packages is incompatible with this scheme.
+Version of RPM package is composed of following properties:
+
+.. _version_properties:
+
+ * ``uint32`` :ref:`Epoch<LMI-SoftwareIdentity-Epoch>`
+ * ``string`` :ref:`Version<LMI-SoftwareIdentity-Version>`
+ * ``string`` :ref:`Release<LMI-SoftwareIdentity-Release>`
+
+Where ``Version`` and ``Release`` can contain arbitrary set of characters (not
+just digits). These attributes were added to ``LMI_SoftwareIdentity`` class and
+will be filled for every RPM package. On the other hand ``MajorVersion``,
+``MinorVersion``, ``RevisionNumber`` and ``BuildNumber`` will not be filled.
+
+This implementetion composes ``VersionString`` in following way: ::
+
+ <Epoch>:<Version>-<Release>.<Architecture>
+
+The algorithm for comparing two RPM packages version is following:
+
+ 1. Compare the ``Epoch`` (which is a number) of both packages. The one
+ with higher epoch is newer. If they match, continue to point 2.
+ 2. Compare their ``Version`` attributes with `rpmvercmp`_ algorithm.
+ Package with larger ``Version`` (according to `rpmvercmp`_) is newer.
+ If they match, continue to point 3.
+ 3. Compare their ``Release`` attributes with `rpmvercmp`_ algorithm.
+ Package with larger ``Release`` string is newer. Otherwise packages
+ have the same version.
+
+Relationships between *Software Identity* and *Managed Element*
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+are not modeled. RPM package database does not provide such informations
+that would allow to associate particular package with a piece of hardware
+it relates to.
+
+Querying for packages
+^^^^^^^^^^^^^^^^^^^^^
+Since enumeration of *Software Identities* is disabled due to a huge
+amount of data generated by large package database, the query
+execution on them is also disallowed [1]_. The only way how to search
+for packages is using the method
+:ref:`LMI_SoftwareInstallationService.FindIdentity<LMI-SoftwareInstallationService-FindIdentity>`.
+
+.. _identifying_software_identity:
+
+Identifying software identity
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+:ref:`InstanceID<LMI-SoftwareIdentity-InstanceID>` key property is the one
+and only identification string of :ref:`LMI-SoftwareIdentity` instances
+representing RPM packages. It's composed of following strings: ::
+
+ LMI:LMI_SoftwareIdentity:<Name>-<Epoch>:<Version>-<Release>.<Architecture>
+
+Where the prefix ``"LMI:LMI_SoftwareIdentity:"`` is compared case-insensitively.
+The rest is also known as a *NEVRA*. When calling ``GetInstance()`` on this
+class, the ``"<Epoch>:"`` part can be omitted in the ``InstanceID`` key property
+of passed ``InstanceName``.
+
+Example
+^^^^^^^
+Take for example package ``vim-enhanced`` installed on Fedora 18: ::
+
+ $ yum info vim-enhanced
+ Installed Packages
+ Name : vim-enhanced
+ Arch : x86_64
+ Epoch : 2
+ Version : 7.4.027
+ Release : 2.fc18
+ Size : 2.1 M
+ Repo : installed
+ From repo : updates-testing
+
+The output has been shortened. This package is represented by
+an instance of ``LMI_SoftwareIdentity`` with ``InstanceID`` equal to: ::
+
+ LMI:LMI_SoftwareIdentity:vim-enhanced-2:7.4.027-2.fc18.x86_64
+
+Profile extensions
+~~~~~~~~~~~~~~~~~~
+List of additional attributes of ``LMI_SoftwareIdentity``:
+
+ * version properties mentioned above (`version_properties`_)
+ * ``string Architecture`` - Target machine architecture. Packages
+ with architecture independent content will have ``"noarch"`` value
+ set.
+
+List of additional attributes of ``LMI_SoftwareIdentityResource``:
+
+ ``Cost`` : sint32
+ Relative cost of accessing this repository.
+ ``GPGCheck`` : boolean
+ Whether the GPG signature check should be performed.
+ ``TimeOfLastUpdate`` : datetime
+ Time of repository's last update on server.
+
+Software Update Profile
+-----------------------
+Implemented *DMTF* version: ``1.0.0``
+
+Described by `DSP1025`_.
+
+The Software Update Profile describes the classes, associations, properties,
+and methods used to support the installation and update of BIOS, firmware,
+drivers and related software on a managed element within a managed system.
+
+
+Implemented optional features
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+This implementation supports:
+
+ Advertising the Location Information of a Software Identity
+ This optional feature provides association of *Software Identity* to
+ its resource. In other words each available package is associated to
+ a corresponding repository defined in configuration files of *YUM*.
+ Repositories are represented with
+ :ref:`LMI_SoftwareIdentityResource<LMI-SoftwareIdentityResource>` and
+ are associated to :ref:`LMI_SoftwareIdentity<LMI-SoftwareIdentity>`
+ via
+ :ref:`LMI_ResourceForSoftwareIdentity<LMI-ResourceForSoftwareIdentity>`.
+
+Not implemented features
+~~~~~~~~~~~~~~~~~~~~~~~~
+Following methods are not implemented:
+
+ * :ref:`CIM_SoftwareInstallationService.InstallFromByteStream<CIM-SoftwareInstallationService-InstallFromByteStream>`
+ * :ref:`LMI_SoftwareInstallationService.CheckSoftwareIdentity<LMI-SoftwareInstallationService-CheckSoftwareIdentity>`
+
+Profile extensions
+~~~~~~~~~~~~~~~~~~
+
+RPM package verification
+^^^^^^^^^^^^^^^^^^^^^^^^
+*Software Inventory* and *Softare Update* profiles don't allow for software
+verification. That is quite useful and desired operation done on RPM packages.
+Following additions has been added to provide such a functionality.
+
+Following classes have been added:
+
+ :ref:`LMI_SoftwareIdentityFileCheck<LMI-SoftwareIdentityFileCheck>`
+ Represents single file contained and installed by *RPM* package.
+ It contains properties allowing for comparison of installed file
+ attributes with those stored in a package database. In case those
+ attributes do not match, file fails the verification test.
+
+ :ref:`LMI_SoftwareIdentityChecks<LMI-SoftwareIdentityChecks>`
+ Associates *Software Identity File Check* to corresponding
+ *Software Identity*.
+
+Following methods have been added:
+
+ :ref:`LMI_SoftwareInstallationService.VerifyInstalledIdentity<LMI-SoftwareInstallationService-VerifyInstalledIdentity>`
+ This allows to run verification test on particular *Software Identity*
+ and returns a list of files that failed.
+
+Package searching
+^^^^^^^^^^^^^^^^^
+On modern Linux distributions we have thousands of software packages
+available for installation making it nearly impossible for *CIMOM* to
+enumerate them all because it consumes a lot of resources. That's why
+the ``EnumerateInstances()`` and ``EnumerateInstanceNames()`` calls have been
+disabled *Software Identities*. As a consequence the ``ExecQuery()`` call is prohibited also.
+
+But the ability to search for packages is so important that a fallback
+solution has been provided. Method
+:ref:`FindIdentity()<LMI-SoftwareInstallationService-FindIdentity>` has been
+added to
+:ref:`LMI_SoftwareInstallationService<LMI-SoftwareInstallationService>`
+allowing to create complex queries on package database.
+
+..
+ ***************************************************************************
+.. _DSP1023: http://www.dmtf.org/sites/default/files/standards/documents/DSP1023_1.0.1.pdf
+.. _DSP1025: http://www.dmtf.org/sites/default/files/standards/documents/DSP1025_1.0.0.pdf
+.. _rpmvercmp: http://fedoraproject.org/wiki/Tools/RPM/VersionComparison
+
+------------------------------------------------------------------------------
+
+.. [1] Because internally the query is executed upon the list obtained by
+ enumeration of instances.
diff --git a/src/software/doc/admin/index.rst b/src/software/doc/admin/index.rst
new file mode 100644
index 0000000..35e57c3
--- /dev/null
+++ b/src/software/doc/admin/index.rst
@@ -0,0 +1,27 @@
+.. OpenLMI Software Provider documentation master file, created by
+ sphinx-quickstart on Thu Oct 3 14:25:59 2013.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Welcome to OpenLMI Software Provider's documentation!
+=====================================================
+
+Contents:
+
+.. toctree::
+ :maxdepth: 2
+
+ dmtf
+ usage
+
+.. ifconfig:: includeClasses
+
+ OpenLMI Storage CIM classes:
+
+ .. toctree::
+ :maxdepth: 1
+
+ mof/tree
+ mof/index
+
+
diff --git a/src/software/doc/admin/mof/Makefile b/src/software/doc/admin/mof/Makefile
new file mode 100644
index 0000000..8884274
--- /dev/null
+++ b/src/software/doc/admin/mof/Makefile
@@ -0,0 +1,15 @@
+src: index.rst
+
+TOPDIR=../../../../..
+MOFS=$(TOPDIR)/mof/60_LMI_Software.mof
+
+index.rst: $(MOFS)
+ $(TOPDIR)/tools/openlmi-doc-class2rst -H header.txt \
+ -M `echo $(MOFS) | sed 's/ / -M /g'` \
+ -S /usr/share/mof/cim-current/CIM_Schema.mof \
+ -S $(TOPDIR)/mof/05_LMI_Qualifiers.mof \
+ -S $(TOPDIR)/mof/30_LMI_Jobs.mof \
+ `cat $(MOFS) | grep "^class" | cut -d ' ' -f 2 | sed 's/://'`
+
+clean:
+ rm -f *.rst
diff --git a/src/software/doc/admin/mof/header.txt b/src/software/doc/admin/mof/header.txt
new file mode 100644
index 0000000..cc06402
--- /dev/null
+++ b/src/software/doc/admin/mof/header.txt
@@ -0,0 +1,2 @@
+Class reference
+===============
diff --git a/src/software/doc/admin/usage.rst b/src/software/doc/admin/usage.rst
new file mode 100644
index 0000000..0f5205d
--- /dev/null
+++ b/src/software/doc/admin/usage.rst
@@ -0,0 +1,617 @@
+*OpenLMI Software* usage
+========================
+Examples for common use cases listed below are written in `lmishell`_. Where
+appropriate, an example for ``lmi`` meta-command, which is a part of
+*OpenLMI-Scripts* project, is added. Please refer to its `documentation`_
+for installation notes and usage.
+
+Listing installed packages
+--------------------------
+Simple
+~~~~~~
+Simple but very slow way: ::
+
+ c = connect("host", "user", "pass")
+ cs = c.root.cimv2.Linux_ComputerSystem.first_instance()
+ for identity in cs.associators(
+ AssocClass="LMI_InstalledSoftwareIdentity",
+ Role="System",
+ ResultRole="InstalledSoftware",
+ ResultClass="LMI_SoftwareIdentity"):
+ print(identity.ElementName)
+
+.. note::
+ Here we use ``Linux_ComputerSystem`` as a class representing computer
+ system. It is part of ``sblim-cmpi-base`` package, which is obsoleted.
+ If you use *Pegasus* as your *CIMOM* you may safely switch to
+ ``PG_ComputerSystem``.
+
+.. seealso::
+ :ref:`LMI_InstalledSoftwareIdentity<LMI-InstalledSoftwareIdentity>`
+
+Faster
+~~~~~~
+This is much faster. Here we enumerate association class
+:ref:`LMI_InstalledSoftwareIdentity<LMI-InstalledSoftwareIdentity>` and
+get information from its key properties. ::
+
+ c = connect("host", "user", "pass")
+ for iname in c.root.cimv2.LMI_InstalledSoftwareIdentity.instance_names():
+ print(iname.path["InstalledSoftware"]["InstanceID"]
+ [len("LMI:LMI_SoftwareIdentity:"):])
+
+.. note::
+ Whole instance is not available. To get it from association instance name,
+ you need to add: ::
+
+ iname.path["InstalledSoftware"].to_instance()
+
+
+``lmi`` meta-command
+~~~~~~~~~~~~~~~~~~~~
+::
+
+ lmi -h $HOST sw list pkgs
+
+Listing repositories
+--------------------
+lmishell
+~~~~~~~~
+::
+
+ c = connect("host", "user", "pass")
+ for repo in c.root.cimv2.LMI_SoftwareIdentityResource.instance_names():
+ print(repo.path["Name"])
+
+.. seealso::
+ :ref:`LMI_SoftwareIdentityResource<LMI-SoftwareIdentityResource>`
+
+``lmi`` meta-command
+~~~~~~~~~~~~~~~~~~~~
+::
+
+ lmi -h $HOST sw list pkgs
+
+Listing available packages
+--------------------------
+lmishell
+~~~~~~~~
+Enumerating of :ref:`LMI_SoftwareIdentity<LMI-SoftwareIdentity>` is
+disabled due to a huge amount of data being generated. That's why we
+enumerate them for particular repository represented by
+:ref:`LMI_SoftwareIdentityResource<LMI-SoftwareIdentityResource>`. ::
+
+ c = connect("host", "user", "pass")
+ for repo in c.root.cimv2.LMI_SoftwareIdentityResource.instances():
+ if repo.EnabledState != 2: # != Enabled
+ continue # skip disabled repositories
+ print(repo.Name)
+ for identity in repo.associator_names(
+ AssocClass="LMI_ResourceForSoftwareIdentity",
+ Role="AvailableSAP",
+ ResultRole="ManagedElement",
+ ResultClass="LMI_SoftwareIdentity"):
+ print(" " + identity.path["InstanceID"]
+ [len("LMI:LMI_SoftwareIdentity:"):])
+
+.. seealso::
+ :ref:`LMI_ResourceForSoftwareIdentity<LMI-ResourceForSoftwareIdentity>`
+
+``lmi`` meta-command
+~~~~~~~~~~~~~~~~~~~~
+::
+
+ lmi -h $HOST sw list --available pkgs
+
+Listing files of package
+------------------------
+Let's list files of packages ``openlmi-tools``. Note that package must
+be installed on system in order to list its files.
+
+lmishell
+~~~~~~~~
+We need to know exact *NEVRA* [1]_ of package we want to operate on. If
+we don't know it, we can find out using
+:ref:`FindIdentity()<LMI-SoftwareInstallationService-FindIdentity>` method.
+See example under `Searching for packages`_. ::
+
+ c = connect("host", "user", "pass")
+ identity = c.root.cimv2.LMI_SoftwareIdentity.new_instance_name(
+ {"InstanceID" : "LMI:LMI_SoftwareIdentity:openlmi-tools-0:0.5-2.fc18.noarch"})
+ for filecheck in identity.to_instance().associator_names(
+ AssocClass="LMI_SoftwareIdentityChecks",
+ Role="Element",
+ ResultRole="Check",
+ ResultClass="LMI_SoftwareIdentityFileCheck"):
+ print("%s" % filecheck.path["Name"])
+
+.. seealso::
+ :ref:`LMI_SoftwareIdentityFileCheck<LMI-SoftwareIdentityFileCheck>`
+
+``lmi`` meta-command
+~~~~~~~~~~~~~~~~~~~~
+::
+
+ lmi -h $HOST sw list files openlmi-tools
+
+Searching for packages
+----------------------
+If we know just a fraction of informations needed to identify a package,
+we may query package database in the following way.
+
+``lmishell``
+~~~~~~~~~~~~
+::
+
+ c = connect("host", "user", "pass")
+ service = LMI_SoftwareInstallationService.first_instance()
+ # let's find all packages with "openlmi" in Name or Summary without
+ # architecture specific code
+ ret = service.FindIdentity(Name="openlmi", Architecture="noarch")
+ for identity in ret.rparams["Matches"]:
+ # we've got only references to instances
+ print identity.path["Name"][len("LMI:LMI_SoftwareIdentity:"):]
+
+.. seealso::
+ :ref:`FindIdentity()<LMI-SoftwareInstallationService-FindIdentity>` method
+
+Please don't use this method to get an instance of package you know
+precisely. If you know all the identification details, you may just
+construct the instance name this way: ::
+
+ c = connect("host", "user", "pass")
+ iname = c.root.cimv2.LMI_SoftwareIdentity.new_instance_name(
+ {"InstanceID" : "LMI:LMI_SoftwareIdentity:openlmi-software-0:0.1.1-2.fc20.noarch"})
+ identity = iname.to_instance()
+
+``lmi`` meta-command
+~~~~~~~~~~~~~~~~~~~~
+See help on ``sw`` command for more information on this. ::
+
+ lmi -h $HOST sw list pkgs openlmi
+
+Package installation
+--------------------
+There are two approaches to package installation. One is synchronous
+and the other asynchronous.
+
+Synchronous installation
+~~~~~~~~~~~~~~~~~~~~~~~~
+This is a very simple and straightforward approach. We install package by
+creating a new instance of
+:ref:`LMI_InstalledSoftwareIdentity<LMI-InstalledSoftwareIdentity>`
+with a reference to some available software identity. ::
+
+ c = connect("host", "user", "pass")
+ identity = c.root.cimv2.LMI_SoftwareIdentity.new_instance_name(
+ {"InstanceID" : "LMI:LMI_SoftwareIdentity:sblim-sfcb-0:1.3.16-3.fc19.x86_64"})
+ cs = c.root.cimv2.Linux_ComputerSystem.first_instance_name()
+ installed_assoc = c.root.cimv2.LMI_InstalledSoftwareIdentity.create_instance(
+ properties={
+ "InstalledSoftware" : identity.path,
+ "System" : cs.path
+ })
+
+If the package is already installed, this operation will fail with
+the :py:class:`pywbem.CIMError` exception being raised initialized with
+``CIM_ERR_ALREADY_EXISTS`` error code.
+
+Asynchronous installation
+~~~~~~~~~~~~~~~~~~~~~~~~~
+Method
+:ref:`InstallFromSoftwareIdentity()<LMI-SoftwareInstallationService-InstallFromSoftwareIdentity>`
+needs to be invoked with desired options. After the options are checked
+by provider, a job will be returned representing installation process running
+at background. Please refer to `Asynchronous Jobs`_ for more details.
+
+::
+
+ c = connect("host", "user", "pass")
+ service = c.root.cimv2.LMI_SoftwareInstallationService.first_instance()
+ identity = c.root.cimv2.LMI_SoftwareIdentity.new_instance_name(
+ {"InstanceID" : "LMI:LMI_SoftwareIdentity:sblim-sfcb-0:1.3.16-5.fc19.x86_64"})
+ cs = c.root.cimv2.Linux_ComputerSystem.first_instance_name()
+ ret = service.InstallFromSoftwareIdentity(
+ Source=identity.path,
+ Target=cs.path,
+ # these options request to install available, not installed package
+ InstallOptions=[4] # [Install]
+ # this will force installation if package is already installed
+ # (possibly in different version)
+ #InstallOptions=[4, 3] # [Install, Force installation]
+ )
+
+The result can be checked by polling resulting job for finished status: ::
+
+ finished_statuses = {
+ c.root.cimv2.CIM_ConcreteJob.JobState.Completed
+ , c.root.cimv2.CIM_ConcreteJob.JobState.Exception
+ , c.root.cimv2.CIM_ConcreteJob.JobState.Terminated
+ }
+ job = ret.rparams["Job"].to_instance()
+ while job.JobStatus not in finished_statuses:
+ # wait for job to complete
+ time.sleep(1)
+ job.refresh()
+ print c.root.cimv2.LMI_SoftwareJob.JobStateValues.value_name(job.JobState)
+ # get an associated job method result and check the return value
+ print "result: %s" % job.first_associator(
+ AssocClass='LMI_AssociatedSoftwareJobMethodResult').__ReturnValue
+ # get installed software identity
+ installed = job.first_associator(
+ Role='AffectingElement',
+ ResultRole='AffectedElement',
+ AssocClass="LMI_AffectedSoftwareJobElement",
+ ResultClass='LMI_SoftwareIdentity')
+ print "installed %s at %s" % (installed.ElementName, installed.InstallDate)
+
+You may also subscribe to indications related to
+:ref:`LMI_SoftwareInstallationJob<LMI-SoftwareInstallationJob>` and listen for
+events instead of the polling done above
+
+As you can see, you may force the installation allowing for reinstallation
+of already installed package. For more options please refer to the
+documentation of this method.
+
+Combined way
+~~~~~~~~~~~~
+We can combine both approaches by utilizing a feature of lmishell_. Method
+above can be called in a synchronous way (from the perspective of script's
+code). It's done like this: ::
+
+ # note the use of "Sync" prefix
+ ret = service.SyncInstallFromSoftwareIdentity(
+ Source=identity.path,
+ Target=cs.path,
+ # these options request to install available, not installed package
+ InstallOptions=[4] # [Install]
+ # this will force installation if package is already installed
+ # (possibly in different version)
+ #InstallOptions=[4, 3] # [Install, Force installation]
+ )
+ print "result: %s" % ret.rval
+
+The value of
+:ref:`LMI_SoftwareMethodResult<LMI-SoftwareMethodResult>` ``.__ReturnValue`` is
+placed to the ``ret.rval`` attribute. Waiting for job's completion is taken care
+of by lmishell_. But we lose the reference to the job itself and we can not
+enumerate affected elements (that contain, among other things, installed
+package).
+
+Installation from URI
+~~~~~~~~~~~~~~~~~~~~~
+This is also possible with: ::
+
+ c = connect("host", "user", "pass")
+ service = c.root.cimv2.LMI_SoftwareInstallationService.first_instance()
+ cs = c.root.cimv2.Linux_ComputerSystem.first_instance_name()
+ ret = service.to_instance().InstallFromSoftwareURI(
+ Source="http://someserver.com/fedora/repo/package.rpm",
+ Target=cs.path,
+ InstallOptions=[4]) # [Install]
+
+Supported *URI* schemes are:
+
+ * ``http``
+ * ``https``
+ * ``ftp``
+ * ``file``
+
+In the last cast, the file must be located on the remote system hosting
+the *CIMOM*.
+
+
+.. seealso::
+ :ref:`InstallFromURI()<LMI-SoftwareInstallationService-InstallFromURI>`
+ method
+
+ Please refer to `Asynchronous installation`_ above for the consequent
+ procedure and how to deal with ``ret`` value.
+
+``lmi`` meta-command
+~~~~~~~~~~~~~~~~~~~~
+::
+
+ lmi -h $HOST sw install sblim-sfcb
+
+Package removal
+---------------
+Again both asynchronous and synchronous approaches are available.
+
+Synchronous removal
+~~~~~~~~~~~~~~~~~~~
+The aim is achieved by issuing an opposite operation than before. The instance
+of :ref:`LMI_InstalledSoftwareIdentity<LMI-InstalledSoftwareIdentity>` is
+deleted here. ::
+
+ c = connect("host", "user", "pass")
+ identity = c.root.cimv2.LMI_SoftwareIdentity.new_instance_name(
+ {"InstanceID" : "LMI:LMI_SoftwareIdentity:sblim-sfcb-0:1.3.16-3.fc19.x86_64"})
+ installed_assocs = identity.to_instance().reference_names(
+ Role="InstalledSoftware",
+ ResultClass="LMI_InstalledSoftwareIdentity")
+ if len(installed_assocs) > 0:
+ for assoc in installed_assocs:
+ assoc.to_instance().delete()
+ print("deleted %s" % assoc.path["InstalledSoftware"]["InstanceID"])
+ else:
+ print("no package removed")
+
+Asynchronous removal
+~~~~~~~~~~~~~~~~~~~~
+::
+
+ c = connect("host", "user", "pass")
+ service = c.root.cimv2.LMI_SoftwareInstallationService.first_instance()
+ identity = c.root.cimv2.LMI_SoftwareIdentity.new_instance_name(
+ {"InstanceID" : "LMI:LMI_SoftwareIdentity:sblim-sfcb-0:1.3.16-5.fc19.x86_64"})
+ cs = c.root.cimv2.Linux_ComputerSystem.first_instance_name()
+ ret = service.InstallFromSoftwareIdentity(
+ Source=identity.path,
+ Target=cs.path,
+ InstallOptions=[9]) # [Uninstall]
+
+Again please refer to `Asynchronous installation`_ for examples on how to
+deal with the ``ret`` value.
+
+``lmi`` meta-command
+~~~~~~~~~~~~~~~~~~~~
+::
+
+ lmi -h $HOST sw remove sblim-sfcb
+
+Package update
+--------------
+Only asynchronous method is provided for this purpose. But with the possibility
+of synchronous invocation.
+
+``lmishell``
+~~~~~~~~~~~~
+Example below shows the synchronous invocation of asynchronous method. ::
+
+ c = connect("host", "user", "pass")
+ service = c.root.cimv2.LMI_SoftwareInstallationService.first_instance()
+ identity = c.root.cimv2.LMI_SoftwareIdentity.new_instance_name(
+ {"InstanceID" : "LMI:LMI_SoftwareIdentity:sblim-sfcb-0:1.3.16-5.fc19.x86_64"})
+ cs = c.root.cimv2.Linux_ComputerSystem.first_instance_name()
+ ret = service.SyncInstallFromSoftwareIdentity(
+ Source=identity.path,
+ Target=cs.path,
+ InstallOptions=[5] # [Update]
+ # to force update, when package is not installed
+ #InstallOptions=[4, 5] # [Install, Update]
+ )
+ print "installation " + ("successful" if rval == 0 else "failed")
+
+``lmi`` meta-command
+~~~~~~~~~~~~~~~~~~~~
+::
+
+ lmi -h $HOST sw update sblim-sfcb
+
+Package verification
+--------------------
+Installed *RPM* packages can be verified. Attributes of installed files
+are compared with those stored in particular *RPM* package. If some value
+of attribute does not match or the file does not exist, it fails the
+verification test. Following attributes come into play in this process:
+
+ * File size - in case of regular file
+ * User ID
+ * Group ID
+ * Last modification time
+ * Mode
+ * Device numbers - in case of device file
+ * Link Target - in case the file is a symbolic link
+ * Checksum - in case of regular file
+
+``lmishell``
+~~~~~~~~~~~~
+It's done via invocation of
+:ref:`VerifyInstalledIdentity()<LMI-SoftwareInstallationService-VerifyInstalledIdentity>`.
+This is an asynchronous method. We can not use synchronous invocation
+if we want to be able to list failed files.
+
+::
+
+ c = connect("host", "user", "pass")
+ service = ns.LMI_SoftwareInstallationService.first_instance()
+ identity = c.root.cimv2.LMI_SoftwareIdentity.new_instance_name(
+ {"InstanceID" : "LMI:LMI_SoftwareIdentity:sblim-sfcb-0:1.3.16-5.fc19.x86_64"})
+ results = service.VerifyInstalledIdentity(
+ Source=identity.path,
+ Target=ns.Linux_ComputerSystem.first_instance().path)
+ nevra = ( identity.path['InstanceId']
+ if isinstance(identity, LMIInstanceName)
+ else identity.InstanceId)[len('LMI:LMI_SoftwareIdentity:'):]
+ if results.rval != 4096:
+ msg = 'failed to verify identity "%s (rval=%d)"' % (nevra, results.rval)
+ if results.errorstr:
+ msg += ': ' + results.errorstr
+ raise Exception(msg)
+
+ job = results.rparams['Job'].to_instance()
+
+ # wait by polling or listening for indication
+ wait_for_job_finished(job)
+
+ if not LMIJob.lmi_is_job_completed(job):
+ msg = 'failed to verify package "%s"' % nevra
+ if job.ErrorDescription:
+ msg += ': ' + job.ErrorDescription
+ raise Exception(msg)
+
+ # get the failed files
+ failed = job.associators(
+ AssocClass="LMI_AffectedSoftwareJobElement",
+ Role='AffectingElement',
+ ResultRole='AffectedElement',
+ ResultClass='LMI_SoftwareIdentityFileCheck')
+ for iname in failed:
+ print iname.Name # print their paths
+
+Polling, as a way of waiting for job completion, has been already shown in the
+example under `Asynchronous installation`_.
+
+.. seealso::
+ :ref:`LMI_SoftwareIdentityFileCheck<LMI-SoftwareIdentityFileCheck>`
+
+``lmi`` meta-command
+~~~~~~~~~~~~~~~~~~~~
+::
+
+ lmi -h $HOST sw verify sblim-sfcb
+
+Enable and disable repository
+-----------------------------
+
+``lmishell``
+~~~~~~~~~~~~
+::
+
+ c = connect("host", "user", "pass")
+ repo = c.root.cimv2.LMI_SoftwareIdentityResource.first_instance_name(
+ key="Name",
+ value="fedora-updates-testing")
+ # disable repository
+ repo.to_instance().RequestStateChange(
+ RequestedState=c.root.cimv2.LMI_SoftwareIdentityResource. \
+ RequestedStateValues.Disabled)
+ repo = c.root.cimv2.LMI_SoftwareIdentityResource.first_instance_name(
+ key="Name",
+ value="fedora-updates")
+ # enable repository
+ repo.to_instance().RequestStateChange(
+ RequestedState=c.root.cimv2.LMI_SoftwareIdentityResource. \
+ RequestedStateValues.Enabled)
+
+``lmi`` meta-command
+~~~~~~~~~~~~~~~~~~~~
+::
+
+ lmi -h $HOST sw disable fedora-updates-testing
+ lmi -h $HOST sw enable fedora-updates
+
+
+Supported event filters
+-----------------------
+There are various events related to asynchronous job you may be interested
+about. All of them can be suscribed to with static filters presented below.
+Usage of custom query strings is not supported due to a complexity of
+its parsing. These filters should be already registered in *CIMOM* if
+*OpenLMI Software* providers are installed. You may check them by enumerating
+``LMI_IndicationFilter`` class located in ``root/interop`` namespace.
+All of them apply to two different software job classes you may want to
+subscribe to:
+
+ :ref:`LMI_SoftwareInstallationJob<LMI-SoftwareInstallationJob>`
+ Represents a job requesting to install, update or remove some package.
+
+ :ref:`LMI_SoftwareVerificationJob<LMI-SoftwareVerificationJob>`
+ Represents a job requesting verification of installed package.
+
+Filters below are written for :ref:`LMI_SoftwareInstallationJob<LMI-SoftwareInstallationJob>` only. If you deal with the other one, just replace the
+class name right after the ``ISA`` operator and classname in filter's name.
+
+Percent Updated
+~~~~~~~~~~~~~~~
+Indication is sent when the
+:ref:`LMI_SoftwareJob.PercentComplete<LMI-ConcreteJob-PercentComplete>`
+property of a job changes.
+
+::
+
+ SELECT * FROM LMI_SoftwareInstModification WHERE
+ SourceInstance ISA LMI_SoftwareInstallationJob AND
+ SourceInstance.CIM_ConcreteJob::PercentComplete <>
+ PreviousInstance.CIM_ConcreteJob::PercentComplete
+
+Registered under filter name
+``"LMI:LMI_SoftwareInstallationJob:PercentUpdated"``.
+
+Job state change
+~~~~~~~~~~~~~~~~
+Indication is sent when the
+:ref:`LMI_SoftwareJob.JobState<LMI-ConcreteJob-JobState>`
+property of a job changes.
+
+::
+
+ SELECT * FROM LMI_SoftwareInstModification WHERE
+ SourceInstance ISA LMI_SoftwareInstallationJob AND
+ SourceInstance.CIM_ConcreteJob::JobState <>
+ PreviousInstance.CIM_ConcreteJob::JobState
+
+Registered under filter name ``"LMI:LMI_SoftwareInstallationJob:Changed"``.
+
+Job Completed
+~~~~~~~~~~~~~
+This event occurs when the state of job becomes ``COMPLETED/OK`` [2]_.
+
+::
+
+ SELECT * FROM LMI_SoftwareInstModification WHERE
+ SourceInstance ISA LMI_SoftwareInstallationJob AND
+ SourceInstance.CIM_ConcreteJob::JobState = 17
+
+Registered under filter name ``"LMI:LMI_SoftwareInstallationJob:Succeeded"``.
+
+Error
+~~~~~
+This event occurs when the state of job becomes ``COMPLETED/Error`` [3]_.
+
+::
+
+ SELECT * FROM LMI_SoftwareInstModification WHERE
+ SourceInstance ISA LMI_SoftwareInstallationJob AND
+ SourceInstance.CIM_ConcreteJob::JobState = 10
+
+Registered under filter name ``"LMI:LMI_SoftwareInstallationJob:Failed"``.
+
+New Job
+~~~~~~~
+This event occurs when the new instance of
+:ref:`LMI_SoftwareJob<LMI-SoftwareJob>` is created.
+
+::
+
+ SELECT * FROM LMI_SoftwareInstCreation WHERE
+ SourceInstance ISA LMI_SoftwareInstallationJob
+
+Registered under filter name ``"LMI:LMI_SoftwareInstallationJob:Created"``.
+
+------------------------------------------------------------------------------
+
+.. [1] Stands for
+
+ .. raw:: html
+
+ <b>N</b>ame, <b>E</b>poch, <b>V</b>ersion, <b>R</b>elease,
+ <b>A</b>rchitecure.
+
+ .. raw:: latex
+
+ \textbf{N}ame, \textbf{E}poch, \textbf{V}ersion, \textbf{R}elease,
+ \textbf{A}rchitecture.
+
+ .. only:: not html and not latex
+
+ Name, Epoch, Version, Release, Architecure.
+
+ Please refer to :ref:`identifying_software_identity` for more details.
+
+.. [2] This is a composition of values in
+ :ref:`OperationalStatus<LMI-ConcreteJob-OperationalStatus>` array.
+ It corresponds to value ``Completed`` of
+ :ref:`JobState<LMI-ConcreteJob-JobState>` property.
+
+.. [3] This is a composition of values in
+ :ref:`OperationalStatus<LMI-ConcreteJob-OperationalStatus>` array.
+ It corresponds to value ``Exception`` of
+ :ref:`JobState<LMI-ConcreteJob-JobState>` property.
+
+
+.. *****************************************************************************
+.. _documentation: https://fedorahosted.org/openlmi/wiki/scripts
+.. _lmishell: https://fedorahosted.org/openlmi/wiki/shell
+.. _`Asynchronous Jobs`: http://jsafrane.fedorapeople.org/openlmi-storage/api/0.6.0/concept-job.html#asynchronous-jobs