Software API Concept

Package database, repositories and the package manager itself are modeled with CIM classes according to several DMTF profiles . Querying a database, installing, updating or removing some package executes some operation on one or more CIM classes. Let’s talk about their relation to managed elements.

OpenLMI-Software class model

Class model for software management provided by OpenLMI-Software provider.

Classes with the blue background belong to Software Inventory Profile. Classes painted yellow belong to Software Update Profile that builds on the former one. Classes painted red/pink are OpenLMI-specific extensions.

Instance and Instance Names

Each CIM class can have several instances. Each instance is uniquely identified by one or several key properties. All properties are defined by corresponding class. For example LMI_SoftwareIdentity has one key property InstanceID that uniquely identifies particular software package. An instance have many other properties - all defined by corresponding class. An instance name is a minimal set of information identifying particular instance. Its string form typically looks like:

[<host>/]<namespace>:<classname>.<keybindings>

For example:

root/cimv2:LMI_SoftwareIdentity.InstanceID="LMI:LMI_SoftwareIdentity:kernel-0:3.17.0-0.rc7.git3.1.fc22.x86_64"

Most methods of OpenLMI-Software provider operate on instance names and they return them as well. They can easily be turned into instances with GetInstance() operation. In LMIShell it is achieved like this:

instance = instance_name.to_instance()

Representing Package

Software package is represented by LMI_SoftwareIdentity. It has single key property InstanceID. It is composed of ORGID prefix, class name and package information:

LMI:LMI_SoftwareIdentity:<package-id>

<package-id> is a NEVRA string as used by RPM tool. It stands for Name, Epoch, Version, Release and Architecture. These are composed in specific way:

<name>-<epoch>:<version>-<release>.<architecture>

This is similar to what rpm tool returns when listing installed packages:

$ rpm -qa 'openlmi-*' vim-enhanced
openlmi-python-base-0.3.0_5_gf056906-2.fc21.noarch
openlmi-providers-0.3.0_5_gf056906-2.fc21.x86_64
vim-enhanced-7.4.027-2.fc20.x86_64
openlmi-logicalfile-0.3.0_5_gf056906-2.fc21.x86_64
openlmi-python-providers-0.3.0_5_gf056906-2.fc21.noarch
openlmi-software-0.3.0_5_gf056906-2.fc21.noarch

There is just one difference – rpm usually omits <epoch>: part. To get an InstanceID of installed packages out of this tool, you need to specify format:

$ rpm --qf 'LMI:LMI_SoftwareIdentity:%{NAME}-%{EPOCH}:%{VERSION}-%{RELEASE}.%{ARCH}\n' -qa 'openlmi-*' | sed 's/(none)/0/'
LMI:LMI_SoftwareIdentity:openlmi-python-base-0:0.3.0_5_gf056906-2.fc21.noarch
LMI:LMI_SoftwareIdentity:openlmi-providers-0:0.3.0_5_gf056906-2.fc21.x86_64
LMI:LMI_SoftwareIdentity:vim-enhanced-2:7.4.027-2.fc20.x86_64
LMI:LMI_SoftwareIdentity:openlmi-logicalfile-0:0.3.0_5_gf056906-2.fc21.x86_64
LMI:LMI_SoftwareIdentity:openlmi-python-providers-0:0.3.0_5_gf056906-2.fc21.noarch
LMI:LMI_SoftwareIdentity:openlmi-software-0:0.3.0_5_gf056906-2.fc21.noarch

Some RPM packages do not define Epoch part, which means it’s 0. rpm returns (none) though. Therefore we need to substitute it with 0. Although C implementation of software provider uses PackageKit supporting many non-RPM backends that don’t have any notion about epoch, the epoch part stays (set to zero).

When installing, updating or removing package, we operate upon an instance or object path of this class.

Representing Repository

Package repository is represented by LMI_SoftwareIdentityResource.

All its key properties are:

Only Name differs on particular system. Others are the same e.g. (using MOF syntax)

instance of LMI_SoftwareIdentityResource {
    CreationClassName = 'LMI_SoftwareIdentityResource';
    Name = 'rawhide';
    SystemCreationClassName = 'PG_ComputerSystem';
    SystemName = 'myhost.example.org';
    /* other non-key properties omitted */
};

instance of LMI_SoftwareIdentityResource {
    CreationClassName = 'LMI_SoftwareIdentityResource';
    Name = 'rawhide-source';
    SystemCreationClassName = 'PG_ComputerSystem';
    SystemName = 'myhost.example.org';
    /* other non-key properties omitted */
};

On systems using yum the Name is repository’s name written in square brackets in its configuration file:

$ cat /etc/yum.repos.d/fedora-rawhide.repo
[rawhide]
name=Fedora - Rawhide - Developmental packages for the next Fedora release
failovermethod=priority
metalink=https://mirrors.fedoraproject.org/metalink?repo=rawhide&arch=$basearch
enabled=1
metadata_expire=12h

Representing installed file

Warning

This feature is available only on RPM based distributions.

Installed file is represented by LMI_SoftwareIdentityFileCheck. Its another meaning is a result of package’s verification for its particular file. It contains attributes being verified such as

  • User ID
  • Group ID
  • Checksum
  • Link Target
  • File Mode

Each is present twice. First property represents the current value of installed file and the other the value stored in RPM package that the file should have. Second property have Original suffix. So for example:

Mentioned attributes are compared when the package verification is done. Single file can also be easily checked. Either by running LMI_SoftwareIdentityFileCheck.Invoke() method on particular object path or by testing the FailedFlags property for emptiness. If its empty, the file or directory passed the verification test.

Asynchronous jobs

Most of Software manipulation methods, for example InstallFromSoftwareIdentity(), can be time-consuming. Therefore the methods only check input parameters and return immediately with a reference to LMI_SoftwareJob instance. The operation itself is performed asynchronously on the server in a separate thread or process.

The returned LMI_SoftwareJob instance can be then used to either pull the operation status or applications can subscribe for job events and get an indication when a job status changes.

Currently, only one job is being executed at a time, all others are enqueued and executed later.

Job status

The job status is exposed in OperationalStatus and JobState properties. Their combination compose unique job status:

Job is OperationalStatus JobState
Queued Dormant New
Suspended [*] OK Suspended
Running OK Running
Finished OK Completed, OK Completed
Failed Completed, Error Exception
Cancelled Stopped Terminated
[*]Software job cannot be suspended as of now.

Job.RequestStateChange method can be used to cancel a job. Only Queued or Running job can be cancelled. Cancellation of a running job succeeds rarely though.

Job state machine.

By default, all job instances disappear automatically 5 minutes after they reach any final state. This can be overridden by setting TimeBeforeRemoval and DeleteOnCompletion properties of a job.

Software job types

There are two descendants of LMI_SoftwareJob used in different contexts:

LMI_SoftwareInstallationJob

Is an output parameter of:

Its InstanceID looks like:

LMI:LMI_SoftwareInstallationJob:<jobnumber>
LMI_SoftwareVerificationJob

Is an output parameter of VerifyInstalledIdentity().

Its InstanceID looks like:

LMI:LMI_SoftwareVerificationJob:<jobnumber>

<jobnumber> is an integer being incremented with each new instance of LMI_SoftwareJob. Thus Installation and verification jobs won’t ever have the same number.

Return value and output parameters

Return value and output parameters of an asynchronous method call are stored in LMI_SoftwareJob.JobOutParameters property, which is EmbeddedObject of a class, which has property for each output parameter of the asynchronous method. The method return value itself is available there too, as __ReturnValue property.

The output parameters are also included in LMI_SoftwareMethodResult.PostCallIndication property. Method Result is associated to the job via LMI_AssociatedSoftwareJobMethodResult. The property itself is embedded instance of CIM_InstMethodCall class. Return value is stored in its ReturnValue property. Output parameters are stored in its MethodParameters property.

Due to broker’s limitations it’s not yet possible to include array of references among output parameters. Therefore several most important output parameters can be obtained only via LMI_AffectedSoftwareJobElement association.

Instance diagram of a job before finishing.

Instance diagram of a job after finishing.

Use this association on successfully completed job to: