summaryrefslogtreecommitdiffstats
path: root/doc/admin/software/usage.rst
diff options
context:
space:
mode:
Diffstat (limited to 'doc/admin/software/usage.rst')
-rw-r--r--doc/admin/software/usage.rst625
1 files changed, 625 insertions, 0 deletions
diff --git a/doc/admin/software/usage.rst b/doc/admin/software/usage.rst
new file mode 100644
index 0000000..5bc034f
--- /dev/null
+++ b/doc/admin/software/usage.rst
@@ -0,0 +1,625 @@
+*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.PG_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 ``PG_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:
+
+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.PG_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.PG_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.PG_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:
+
+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.PG_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:
+
+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.PG_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:
+
+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.PG_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