Chapter 22. OpenLMI

The Open Linux Management Infrastructure, commonly abbreviated as OpenLMI, is a common infrastructure for the management of Linux systems. It builds on top of existing tools and serves as an abstraction layer in order to hide much of the complexity of the underlying system from system administrators. OpenLMI is distributed with a set of services that can be accessed locally or remotely and provides multiple language bindings, standard APIs, and standard scripting interfaces that can be used to manage and monitor hardware, operating systems, and system services.

22.1. About OpenLMI

OpenLMI is designed to provide a common management interface to production servers running the Red Hat Enterprise Linux system on both physical and virtual machines. It consists of the following three components:

  1. System management agents — these agents are installed on a managed system and implement an object model that is presented to a standard object broker. The initial agents implemented in OpenLMI include storage configuration and network configuration, but later work will address additional elements of system management. The system management agents are commonly referred to as Common Information Model providers or CIM providers.
  2. A standard object broker — the object broker manages system management agents and provides an interface to them. The standard object broker is also known as a CIM Object Monitor or CIMOM.
  3. Client applications and scripts — the client applications and scripts call the system management agents through the standard object broker.

The OpenLMI project complements existing management initiatives by providing a low-level interface that can be used by scripts or system management consoles. Interfaces distributed with OpenLMI include C, C++, Python, Java, and an interactive command line client, and all of them offer the same full access to the capabilities implemented in each agent. This ensures that you always have access to exactly the same capabilities no matter which programming interface you decide to use.

22.1.1. Main Features

The following are key benefits of installing and using OpenLMI on your system:

  • OpenLMI provides a standard interface for configuration, management, and monitoring of your local and remote systems.
  • It allows you to configure, manage, and monitor production servers running on both physical and virtual machines.
  • It is distributed with a collection of CIM providers that allow you to configure, manage, and monitor storage devices and complex networks.
  • It allows you to call system management functions from C, C++, Python, and Java programs, and includes LMIShell, which provides a command line interface.
  • It is free software based on open industry standards.

22.1.2. Management Capabilities

Key capabilities of OpenLMI include the management of storage devices, networks, system services, user accounts, hardware and software configuration, power management, and interaction with Active Directory. For a complete list of CIM providers that are distributed with Red Hat Enterprise Linux 7, see Table 22.1, “Available CIM Providers”.

Table 22.1. Available CIM Providers

Package NameDescription

openlmi-account

A CIM provider for managing user accounts.

openlmi-logicalfile

A CIM provider for reading files and directories.

openlmi-networking

A CIM provider for network management.

openlmi-powermanagement

A CIM provider for power management.

openlmi-service

A CIM provider for managing system services.

openlmi-storage

A CIM provider for storage management.

openlmi-fan

A CIM provider for controlling computer fans.

openlmi-hardware

A CIM provider for retrieving hardware information.

openlmi-realmd

A CIM provider for configuring realmd.

openlmi-software[a]

A CIM provider for software management.

[a] In Red Hat Enterprise Linux 7, the OpenLMI Software provider is included as a Technology Preview. This provider is fully functional, but has a known performance scaling issue where listing large numbers of software packages may consume excessive amount of memory and time. To work around this issue, adjust package searches to return as few packages as possible.

22.2. Installing OpenLMI

OpenLMI is distributed as a collection of RPM packages that include the CIMOM, individual CIM providers, and client applications. This allows you distinguish between a managed and client system and install only those components you need.

22.2.1. Installing OpenLMI on a Managed System

A managed system is the system you intend to monitor and manage by using the OpenLMI client tools. To install OpenLMI on a managed system, complete the following steps:

  1. Install the tog-pegasus package by typing the following at a shell prompt as root:

    yum install tog-pegasus

    This command installs the OpenPegasus CIMOM and all its dependencies to the system and creates a user account for the pegasus user.

  2. Install required CIM providers by running the following command as root:

    yum install openlmi-{storage,networking,service,account,powermanagement}

    This command installs the CIM providers for storage, network, service, account, and power management. For a complete list of CIM providers distributed with Red Hat Enterprise Linux 7, see Table 22.1, “Available CIM Providers”.

  3. Edit the /etc/Pegasus/access.conf configuration file to customize the list of users that are allowed to connect to the OpenPegasus CIMOM. By default, only the pegasus user is allowed to access the CIMOM both remotely and locally. To activate this user account, run the following command as root to set the user’s password:

    passwd pegasus
  4. Start the OpenPegasus CIMOM by activating the tog-pegasus.service unit. To activate the tog-pegasus.service unit in the current session, type the following at a shell prompt as root:

    systemctl start tog-pegasus.service

    To configure the tog-pegasus.service unit to start automatically at boot time, type as root:

    systemctl enable tog-pegasus.service
  5. If you intend to interact with the managed system from a remote machine, enable TCP communication on port 5989 (wbem-https). To open this port in the current session, run the following command as root:

    firewall-cmd --add-port 5989/tcp

    To open port 5989 for TCP communication permanently, type as root:

    firewall-cmd --permanent --add-port 5989/tcp

You can now connect to the managed system and interact with it by using the OpenLMI client tools as described in Section 22.4, “Using LMIShell”. If you intend to perform OpenLMI operations directly on the managed system, also complete the steps described in Section 22.2.2, “Installing OpenLMI on a Client System”.

22.2.2. Installing OpenLMI on a Client System

A client system is the system from which you intend to interact with the managed system. In a typical scenario, the client system and the managed system are installed on two separate machines, but you can also install the client tools on the managed system and interact with it directly.

To install OpenLMI on a client system, complete the following steps:

  1. Install the openlmi-tools package by typing the following at a shell prompt as root:

    yum install openlmi-tools

    This command installs LMIShell, an interactive client and interpreter for accessing CIM objects provided by OpenPegasus, and all its dependencies to the system.

  2. Configure SSL certificates for OpenPegasus as described in Section 22.3, “Configuring SSL Certificates for OpenPegasus”.

You can now use the LMIShell client to interact with the managed system as described in Section 22.4, “Using LMIShell”.

22.3. Configuring SSL Certificates for OpenPegasus

OpenLMI uses the Web-Based Enterprise Management (WBEM) protocol that functions over an HTTP transport layer. Standard HTTP Basic authentication is performed in this protocol, which means that the user name and password are transmitted alongside the requests.

Configuring the OpenPegasus CIMOM to use HTTPS for communication is necessary to ensure secure authentication. A Secure Sockets Layer (SSL) or Transport Layer Security (TLS) certificate is required on the managed system to establish an encrypted channel.

There are two ways of managing SSL/TLS certificates on a system:

  • Self-signed certificates require less infrastructure to use, but are more difficult to deploy to clients and manage securely.
  • Authority-signed certificates are easier to deploy to clients once they are set up, but may require a greater initial investment.

When using an authority-signed certificate, it is necessary to configure a trusted certificate authority on the client systems. The authority can then be used for signing all of the managed systems' CIMOM certificates. Certificates can also be part of a certificate chain, so the certificate used for signing the managed systems' certificates may in turn be signed by another, higher authority (such as Verisign, CAcert, RSA and many others).

The default certificate and trust store locations on the file system are listed in Table 22.2, “Certificate and Trust Store Locations”.

Table 22.2. Certificate and Trust Store Locations

Configuration OptionLocationDescription

sslCertificateFilePath

/etc/Pegasus/server.pem

Public certificate of the CIMOM.

sslKeyFilePath

/etc/Pegasus/file.pem

Private key known only to the CIMOM.

sslTrustStore

/etc/Pegasus/client.pem

The file or directory providing the list of trusted certificate authorities.

Important

If you modify any of the files mentioned in Table 22.2, “Certificate and Trust Store Locations”, restart the tog-pegasus service to make sure it recognizes the new certificates. To restart the service, type the following at a shell prompt as root:

systemctl restart tog-pegasus.service

For more information on how to manage system services in Red Hat Enterprise Linux 7, see Chapter 10, Managing Services with systemd.

22.3.1. Managing Self-signed Certificates

A self-signed certificate uses its own private key to sign itself and it is not connected to any chain of trust. On a managed system, if certificates have not been provided by the administrator prior to the first time that the tog-pegasus service is started, a set of self-signed certificates will be automatically generated using the system’s primary host name as the certificate subject.

Important

The automatically generated self-signed certificates are valid by default for 10 years, but they have no automatic-renewal capability. Any modification to these certificates will require manually creating new certificates following guidelines provided by the OpenSSL or Mozilla NSS documentation on the subject.

To configure client systems to trust the self-signed certificate, complete the following steps:

  1. Copy the /etc/Pegasus/server.pem certificate from the managed system to the /etc/pki/ca-trust/source/anchors/ directory on the client system. To do so, type the following at a shell prompt as root:

    scp root@hostname:/etc/Pegasus/server.pem /etc/pki/ca-trust/source/anchors/pegasus-hostname.pem

    Replace hostname with the host name of the managed system. Note that this command only works if the sshd service is running on the managed system and is configured to allow the root user to log in to the system over the SSH protocol. For more information on how to install and configure the sshd service and use the scp command to transfer files over the SSH protocol, see Chapter 12, OpenSSH.

  2. Verify the integrity of the certificate on the client system by comparing its check sum with the check sum of the original file. To calculate the check sum of the /etc/Pegasus/server.pem file on the managed system, run the following command as root on that system:

    sha1sum /etc/Pegasus/server.pem

    To calculate the check sum of the /etc/pki/ca-trust/source/anchors/pegasus-hostname.pem file on the client system, run the following command on this system:

    sha1sum /etc/pki/ca-trust/source/anchors/pegasus-hostname.pem

    Replace hostname with the host name of the managed system.

  3. Update the trust store on the client system by running the following command as root:

    update-ca-trust extract

22.3.2. Managing Authority-signed Certificates with Identity Management (Recommended)

The Identity Management feature of Red Hat Enterprise Linux provides a domain controller which simplifies the management of SSL certificates within systems joined to the domain. Among others, the Identity Management server provides an embedded Certificate Authority. See the Red Hat Enterprise Linux 7 Linux Domain Identity, Authentication, and Policy Guide or the FreeIPA documentation for information on how to join the client and managed systems to the domain.

It is necessary to register the managed system to Identity Management; for client systems the registration is optional.

The following steps are required on the managed system:

  1. Install the ipa-client package and register the system to Identity Management as described in the Red Hat Enterprise Linux 7 Linux Domain Identity, Authentication, and Policy Guide.
  2. Copy the Identity Management signing certificate to the trusted store by typing the following command as root:

    cp /etc/ipa/ca.crt /etc/pki/ca-trust/source/anchors/ipa.crt
  3. Update the trust store by running the following command as root:

    update-ca-trust extract
  4. Register Pegasus as a service in the Identity Management domain by running the following command as a privileged domain user:

    ipa service-add CIMOM/hostname

    Replace hostname with the host name of the managed system.

    This command can be run from any system in the Identity Management domain that has the ipa-admintools package installed. It creates a service entry in Identity Management that can be used to generate signed SSL certificates.

  5. Back up the PEM files located in the /etc/Pegasus/ directory (recommended).
  6. Retrieve the signed certificate by running the following command as root:

    ipa-getcert request -f /etc/Pegasus/server.pem -k /etc/Pegasus/file.pem -N CN=hostname -K CIMOM/hostname

    Replace hostname with the host name of the managed system.

    The certificate and key files are now kept in proper locations. The certmonger daemon installed on the managed system by the ipa-client-install script ensures that the certificate is kept up-to-date and renewed as necessary.

    For more information, see the Red Hat Enterprise Linux 7 Linux Domain Identity, Authentication, and Policy Guide.

To register the client system and update the trust store, follow the steps below.

  1. Install the ipa-client package and register the system to Identity Management as described in the Red Hat Enterprise Linux 7 Linux Domain Identity, Authentication, and Policy Guide.
  2. Copy the Identity Management signing certificate to the trusted store by typing the following command as root:

    cp /etc/ipa/ca.crt /etc/pki/ca-trust/source/anchors/ipa.crt
  3. Update the trust store by running the following command as root:

    update-ca-trust extract

If the client system is not meant to be registered in Identity Management, complete the following steps to update the trust store.

  1. Copy the /etc/ipa/ca.crt file securely from any other system joined to the same Identity Management domain to the trusted store /etc/pki/ca-trust/source/anchors/ directory as root.
  2. Update the trust store by running the following command as root:

    update-ca-trust extract

22.3.3. Managing Authority-signed Certificates Manually

Managing authority-signed certificates with other mechanisms than Identity Management requires more manual configuration.

It is necessary to ensure that all of the clients trust the certificate of the authority that will be signing the managed system certificates:

  • If a certificate authority is trusted by default, it is not necessary to perform any particular steps to accomplish this.
  • If the certificate authority is not trusted by default, the certificate has to be imported on the client and managed systems.

    1. Copy the certificate to the trusted store by typing the following command as root:

      cp /path/to/ca.crt /etc/pki/ca-trust/source/anchors/ca.crt
    2. Update the trust store by running the following command as root:

      update-ca-trust extract

On the managed system, complete the following steps:

  1. Create a new SSL configuration file /etc/Pegasus/ssl.cnf to store information about the certificate. The contents of this file must be similar to the following example:

    [ req ]
    distinguished_name   = req_distinguished_name
    prompt         = no
    [ req_distinguished_name ]
    C           = US
    ST           = Massachusetts
    L           = Westford
    O           = Fedora
    OU           = Fedora OpenLMI
    CN           = hostname

    Replace hostname with the fully qualified domain name of the managed system.

  2. Generate a private key on the managed system by using the following command as root:

    openssl genrsa -out /etc/Pegasus/file.pem 1024
  3. Generate a certificate signing request (CSR) by running this command as root:

    openssl req -config /etc/Pegasus/ssl.cnf -new -key /etc/Pegasus/file.pem -out /etc/Pegasus/server.csr
  4. Send the /etc/Pegasus/server.csr file to the certificate authority for signing. The detailed procedure of submitting the file depends on the particular certificate authority.
  5. When the signed certificate is received from the certificate authority, save it as /etc/Pegasus/server.pem.
  6. Copy the certificate of the trusted authority to the Pegasus trust store to make sure that Pegasus is capable of trusting its own certificate by running as root:

    cp /path/to/ca.crt /etc/Pegasus/client.pem

After accomplishing all the described steps, the clients that trust the signing authority are able to successfully communicate with the managed server’s CIMOM.

Important

Unlike the Identity Management solution, if the certificate expires and needs to be renewed, all of the described manual steps have to be carried out again. It is recommended to renew the certificates before they expire.

22.4. Using LMIShell

LMIShell is an interactive client and non-interactive interpreter that can be used to access CIM objects provided by the OpenPegasus CIMOM. It is based on the Python interpreter, but also implements additional functions and classes for interacting with CIM objects.

22.4.1. Starting, Using, and Exiting LMIShell

Similarly to the Python interpreter, you can use LMIShell either as an interactive client, or as a non-interactive interpreter for LMIShell scripts.

Starting LMIShell in Interactive Mode

To start the LMIShell interpreter in interactive mode, run the lmishell command with no additional arguments:

lmishell

By default, when LMIShell attempts to establish a connection with a CIMOM, it validates the server-side certificate against the Certification Authorities trust store. To disable this validation, run the lmishell command with the --noverify or -n command line option:

lmishell --noverify
Using Tab Completion

When running in interactive mode, the LMIShell interpreter allows you press the Tab key to complete basic programming structures and CIM objects, including namespaces, classes, methods, and object properties.

Browsing History

By default, LMIShell stores all commands you type at the interactive prompt in the ~/.lmishell_history file. This allows you to browse the command history and re-use already entered lines in interactive mode without the need to type them at the prompt again. To move backward in the command history, press the Up Arrow key or the Ctrl+p key combination. To move forward in the command history, press the Down Arrow key or the Ctrl+n key combination.

LMIShell also supports an incremental reverse search. To look for a particular line in the command history, press Ctrl+r and start typing any part of the command. For example:

> (reverse-i-search)`connect': c = connect("server.example.com", "pegasus")

To clear the command history, use the clear_history() function as follows:

clear_history()

You can configure the number of lines that are stored in the command history by changing the value of the history_length option in the ~/.lmishellrc configuration file. In addition, you can change the location of the history file by changing the value of the history_file option in this configuration file. For example, to set the location of the history file to ~/.lmishell_history and configure LMIShell to store the maximum of 1000 lines in it, add the following lines to the ~/.lmishellrc file:

history_file = "~/.lmishell_history"
history_length = 1000
Handling Exceptions

By default, the LMIShell interpreter handles all exceptions and uses return values. To disable this behavior in order to handle all exceptions in the code, use the use_exceptions() function as follows:

use_exceptions()

To re-enable the automatic exception handling, use:

use_exception(False)

You can permanently disable the exception handling by changing the value of the use_exceptions option in the ~/.lmishellrc configuration file to True:

use_exceptions = True
Configuring a Temporary Cache

With the default configuration, LMIShell connection objects use a temporary cache for storing CIM class names and CIM classes in order to reduce network communication. To clear this temporary cache, use the clear_cache() method as follows:

object_name.clear_cache()

Replace object_name with the name of a connection object.

To disable the temporary cache for a particular connection object, use the use_cache() method as follows:

object_name.use_cache(False)

To enable it again, use:

object_name.use_cache(True)

You can permanently disable the temporary cache for connection objects by changing the value of the use_cache option in the ~/.lmishellrc configuration file to False:

use_cache = False
Exiting LMIShell

To terminate the LMIShell interpreter and return to the shell prompt, press the Ctrl+d key combination or issue the quit() function as follows:

> quit()
~]$
Running an LMIShell Script

To run an LMIShell script, run the lmishell command as follows:

lmishell file_name

Replace file_name with the name of the script. To inspect an LMIShell script after its execution, also specify the --interact or -i command line option:

lmishell --interact file_name

The preferred file extension of LMIShell scripts is .lmi.

22.4.2. Connecting to a CIMOM

LMIShell allows you to connect to a CIMOM that is running either locally on the same system, or on a remote machine accessible over the network.

Connecting to a Remote CIMOM

To access CIM objects provided by a remote CIMOM, create a connection object by using the connect() function as follows:

connect(host_name, user_name, password)

Replace host_name with the host name of the managed system, user_name with the name of a user that is allowed to connect to the OpenPegasus CIMOM running on that system, and password with the user’s password. If the password is omitted, LMIShell prompts the user to enter it. The function returns an LMIConnection object.

Example 22.1. Connecting to a Remote CIMOM

To connect to the OpenPegasus CIMOM running on server.example.com as user pegasus, type the following at the interactive prompt:

> c = connect("server.example.com", "pegasus")
password:
>
Connecting to a Local CIMOM

LMIShell allows you to connect to a local CIMOM by using a Unix socket. For this type of connection, you must run the LMIShell interpreter as the root user and the /var/run/tog-pegasus/cimxml.socket socket must exist.

To access CIM objects provided by a local CIMOM, create a connection object by using the connect() function as follows:

connect(host_name)

Replace host_name with localhost, 127.0.0.1, or ::1. The function returns an LMIConnection object or None.

Example 22.2. Connecting to a Local CIMOM

To connect to the OpenPegasus CIMOM running on localhost as the root user, type the following at the interactive prompt:

> c = connect("localhost")
>
Verifying a Connection to a CIMOM

The connect() function returns either an LMIConnection object, or None if the connection could not be established. In addition, when the connect() function fails to establish a connection, it prints an error message to standard error output.

To verify that a connection to a CIMOM has been established successfully, use the isinstance() function as follows:

isinstance(object_name, LMIConnection)

Replace object_name with the name of the connection object. This function returns True if object_name is an LMIConnection object, or False otherwise.

Example 22.3. Verifying a Connection to a CIMOM

To verify that the c variable created in Example 22.1, “Connecting to a Remote CIMOM” contains an LMIConnection object, type the following at the interactive prompt:

> isinstance(c, LMIConnection)
True
>

Alternatively, you can verify that c is not None:

> c is None
False
>

22.4.3. Working with Namespaces

LMIShell namespaces provide a natural means of organizing available classes and serve as a hierarchic access point to other namespaces and classes. The root namespace is the first entry point of a connection object.

Listing Available Namespaces

To list all available namespaces, use the print_namespaces() method as follows:

object_name.print_namespaces()

Replace object_name with the name of the object to inspect. This method prints available namespaces to standard output.

To get a list of available namespaces, access the object attribute namespaces:

object_name.namespaces

This returns a list of strings.

Example 22.4. Listing Available Namespaces

To inspect the root namespace object of the c connection object created in Example 22.1, “Connecting to a Remote CIMOM” and list all available namespaces, type the following at the interactive prompt:

> c.root.print_namespaces()
cimv2
interop
PG_InterOp
PG_Internal
>

To assign a list of these namespaces to a variable named root_namespaces, type:

> root_namespaces = c.root.namespaces
>
Accessing Namespace Objects

To access a particular namespace object, use the following syntax:

object_name.namespace_name

Replace object_name with the name of the object to inspect and namespace_name with the name of the namespace to access. This returns an LMINamespace object.

Example 22.5. Accessing Namespace Objects

To access the cimv2 namespace of the c connection object created in Example 22.1, “Connecting to a Remote CIMOM” and assign it to a variable named ns, type the following at the interactive prompt:

> ns = c.root.cimv2
>

22.4.4. Working with Classes

LMIShell classes represent classes provided by a CIMOM. You can access and list their properties, methods, instances, instance names, and ValueMap properties, print their documentation strings, and create new instances and instance names.

Listing Available Classes

To list all available classes in a particular namespace, use the print_classes() method as follows:

namespace_object.print_classes()

Replace namespace_object with the namespace object to inspect. This method prints available classes to standard output.

To get a list of available classes, use the classes() method:

namespace_object.classes()

This method returns a list of strings.

Example 22.6. Listing Available Classes

To inspect the ns namespace object created in Example 22.5, “Accessing Namespace Objects” and list all available classes, type the following at the interactive prompt:

> ns.print_classes()
CIM_CollectionInSystem
CIM_ConcreteIdentity
CIM_ControlledBy
CIM_DeviceSAPImplementation
CIM_MemberOfStatusCollection
...
>

To assign a list of these classes to a variable named cimv2_classes, type:

> cimv2_classes = ns.classes()
>
Accessing Class Objects

To access a particular class object that is provided by the CIMOM, use the following syntax:

namespace_object.class_name

Replace namespace_object with the name of the namespace object to inspect and class_name with the name of the class to access.

Example 22.7. Accessing Class Objects

To access the LMI_IPNetworkConnection class of the ns namespace object created in Example 22.5, “Accessing Namespace Objects” and assign it to a variable named cls, type the following at the interactive prompt:

> cls = ns.LMI_IPNetworkConnection
>
Examining Class Objects

All class objects store information about their name and the namespace they belong to, as well as detailed class documentation. To get the name of a particular class object, use the following syntax:

class_object.classname

Replace class_object with the name of the class object to inspect. This returns a string representation of the object name.

To get information about the namespace a class object belongs to, use:

class_object.namespace

This returns a string representation of the namespace.

To display detailed class documentation, use the doc() method as follows:

class_object.doc()

Example 22.8. Examining Class Objects

To inspect the cls class object created in Example 22.7, “Accessing Class Objects” and display its name and corresponding namespace, type the following at the interactive prompt:

> cls.classname
'LMI_IPNetworkConnection'
> cls.namespace
'root/cimv2'
>

To access class documentation, type:

> cls.doc()
Class: LMI_IPNetworkConnection
  SuperClass: CIM_IPNetworkConnection
  [qualifier] string UMLPackagePath: 'CIM::Network::IP'

  [qualifier] string Version: '0.1.0'
...
Listing Available Methods

To list all available methods of a particular class object, use the print_methods() method as follows:

class_object.print_methods()

Replace class_object with the name of the class object to inspect. This method prints available methods to standard output.

To get a list of available methods, use the methods() method:

class_object.methods()

This method returns a list of strings.

Example 22.9. Listing Available Methods

To inspect the cls class object created in Example 22.7, “Accessing Class Objects” and list all available methods, type the following at the interactive prompt:

> cls.print_methods()
RequestStateChange
>

To assign a list of these methods to a variable named service_methods, type:

> service_methods = cls.methods()
>
Listing Available Properties

To list all available properties of a particular class object, use the print_properties() method as follows:

class_object.print_properties()

Replace class_object with the name of the class object to inspect. This method prints available properties to standard output.

To get a list of available properties, use the properties() method:

class_object.properties()

This method returns a list of strings.

Example 22.10. Listing Available Properties

To inspect the cls class object created in Example 22.7, “Accessing Class Objects” and list all available properties, type the following at the interactive prompt:

> cls.print_properties()
RequestedState
HealthState
StatusDescriptions
TransitioningToState
Generation
...
>

To assign a list of these classes to a variable named service_properties, type:

> service_properties = cls.properties()
>
Listing and Viewing ValueMap Properties

CIM classes may contain ValueMap properties in their Managed Object Format (MOF) definition. ValueMap properties contain constant values, which may be useful when calling methods or checking returned values.

To list all available ValueMap properties of a particular class object, use the print_valuemap_properties() method as follows:

class_object.print_valuemap_properties()

Replace class_object with the name of the class object to inspect. This method prints available ValueMap properties to standard output:

To get a list of available ValueMap properties, use the valuemap_properties() method:

class_object.valuemap_properties()

This method returns a list of strings.

Example 22.11. Listing ValueMap Properties

To inspect the cls class object created in Example 22.7, “Accessing Class Objects” and list all available ValueMap properties, type the following at the interactive prompt:

> cls.print_valuemap_properties()
RequestedState
HealthState
TransitioningToState
DetailedStatus
OperationalStatus
...
>

To assign a list of these ValueMap properties to a variable named service_valuemap_properties, type:

> service_valuemap_properties = cls.valuemap_properties()
>

To access a particular ValueMap property, use the following syntax:

class_object.valuemap_propertyValues

Replace valuemap_property with the name of the ValueMap property to access.

To list all available constant values, use the print_values() method as follows:

class_object.valuemap_propertyValues.print_values()

This method prints available named constant values to standard output. You can also get a list of available constant values by using the values() method:

class_object.valuemap_propertyValues.values()

This method returns a list of strings.

Example 22.12. Accessing ValueMap Properties

Example 22.11, “Listing ValueMap Properties” mentions a ValueMap property named RequestedState. To inspect this property and list available constant values, type the following at the interactive prompt:

> cls.RequestedStateValues.print_values()
Reset
NoChange
NotApplicable
Quiesce
Unknown
...
>

To assign a list of these constant values to a variable named requested_state_values, type:

> requested_state_values = cls.RequestedStateValues.values()
>

To access a particular constant value, use the following syntax:

class_object.valuemap_propertyValues.constant_value_name

Replace constant_value_name with the name of the constant value. Alternatively, you can use the value() method as follows:

class_object.valuemap_propertyValues.value("constant_value_name")

To determine the name of a particular constant value, use the value_name() method:

class_object.valuemap_propertyValues.value_name("constant_value")

This method returns a string.

Example 22.13. Accessing Constant Values

Example 22.12, “Accessing ValueMap Properties” shows that the RequestedState property provides a constant value named Reset. To access this named constant value, type the following at the interactive prompt:

> cls.RequestedStateValues.Reset
11
> cls.RequestedStateValues.value("Reset")
11
>

To determine the name of this constant value, type:

> cls.RequestedStateValues.value_name(11)
u'Reset'
>
Fetching a CIMClass Object

Many class methods do not require access to a CIMClass object, which is why LMIShell only fetches this object from the CIMOM when a called method actually needs it. To fetch the CIMClass object manually, use the fetch() method as follows:

class_object.fetch()

Replace class_object with the name of the class object. Note that methods that require access to a CIMClass object fetch it automatically.

22.4.5. Working with Instances

LMIShell instances represent instances provided by a CIMOM. You can get and set their properties, list and call their methods, print their documentation strings, get a list of associated or association objects, push modified objects to the CIMOM, and delete individual instances from the CIMOM.

Accessing Instances

To get a list of all available instances of a particular class object, use the instances() method as follows:

class_object.instances()

Replace class_object with the name of the class object to inspect. This method returns a list of LMIInstance objects.

To access the first instance of a class object, use the first_instance() method:

class_object.first_instance()

This method returns an LMIInstance object.

In addition to listing all instances or returning the first one, both instances() and first_instance() support an optional argument to allow you to filter the results:

class_object.instances(criteria)
class_object.first_instance(criteria)

Replace criteria with a dictionary consisting of key-value pairs, where keys represent instance properties and values represent required values of these properties.

Example 22.14. Accessing Instances

To find the first instance of the cls class object created in Example 22.7, “Accessing Class Objects” that has the ElementName property equal to eth0 and assign it to a variable named device, type the following at the interactive prompt:

> device = cls.first_instance({"ElementName": "eth0"})
>
Examining Instances

All instance objects store information about their class name and the namespace they belong to, as well as detailed documentation about their properties and values. In addition, instance objects allow you to retrieve a unique identification object.

To get the class name of a particular instance object, use the following syntax:

instance_object.classname

Replace instance_object with the name of the instance object to inspect. This returns a string representation of the class name.

To get information about the namespace an instance object belongs to, use:

instance_object.namespace

This returns a string representation of the namespace.

To retrieve a unique identification object for an instance object, use:

instance_object.path

This returns an LMIInstanceName object.

Finally, to display detailed documentation, use the doc() method as follows:

instance_object.doc()

Example 22.15. Examining Instances

To inspect the device instance object created in Example 22.14, “Accessing Instances” and display its class name and the corresponding namespace, type the following at the interactive prompt:

> device.classname
u'LMI_IPNetworkConnection'
> device.namespace
'root/cimv2'
>

To access instance object documentation, type:

> device.doc()
Instance of LMI_IPNetworkConnection
  [property] uint16 RequestedState = '12'

  [property] uint16 HealthState

  [property array] string [] StatusDescriptions
...
Creating New Instances

Certain CIM providers allow you to create new instances of specific classes objects. To create a new instance of a class object, use the create_instance() method as follows:

class_object.create_instance(properties)

Replace class_object with the name of the class object and properties with a dictionary that consists of key-value pairs, where keys represent instance properties and values represent property values. This method returns an LMIInstance object.

Example 22.16. Creating New Instances

The LMI_Group class represents system groups and the LMI_Account class represents user accounts on the managed system. To use the ns namespace object created in Example 22.5, “Accessing Namespace Objects”, create instances of these two classes for the system group named pegasus and the user named lmishell-user, and assign them to variables named group and user, type the following at the interactive prompt:

> group = ns.LMI_Group.first_instance({"Name" : "pegasus"})
> user = ns.LMI_Account.first_instance({"Name" : "lmishell-user"})
>

To get an instance of the LMI_Identity class for the lmishell-user user, type:

> identity = user.first_associator(ResultClass="LMI_Identity")
>

The LMI_MemberOfGroup class represents system group membership. To use the LMI_MemberOfGroup class to add the lmishell-user to the pegasus group, create a new instance of this class as follows:

> ns.LMI_MemberOfGroup.create_instance({
...   "Member" : identity.path,
...   "Collection" : group.path})
LMIInstance(classname="LMI_MemberOfGroup", ...)
>
Deleting Individual Instances

To delete a particular instance from the CIMOM, use the delete() method as follows:

instance_object.delete()

Replace instance_object with the name of the instance object to delete. This method returns a boolean. Note that after deleting an instance, its properties and methods become inaccessible.

Example 22.17. Deleting Individual Instances

The LMI_Account class represents user accounts on the managed system. To use the ns namespace object created in Example 22.5, “Accessing Namespace Objects”, create an instance of the LMI_Account class for the user named lmishell-user, and assign it to a variable named user, type the following at the interactive prompt:

> user = ns.LMI_Account.first_instance({"Name" : "lmishell-user"})
>

To delete this instance and remove the lmishell-user from the system, type:

> user.delete()
True
>
Listing and Accessing Available Properties

To list all available properties of a particular instance object, use the print_properties() method as follows:

instance_object.print_properties()

Replace instance_object with the name of the instance object to inspect. This method prints available properties to standard output.

To get a list of available properties, use the properties() method:

instance_object.properties()

This method returns a list of strings.

Example 22.18. Listing Available Properties

To inspect the device instance object created in Example 22.14, “Accessing Instances” and list all available properties, type the following at the interactive prompt:

> device.print_properties()
RequestedState
HealthState
StatusDescriptions
TransitioningToState
Generation
...
>

To assign a list of these properties to a variable named device_properties, type:

> device_properties = device.properties()
>

To get the current value of a particular property, use the following syntax:

instance_object.property_name

Replace property_name with the name of the property to access.

To modify the value of a particular property, assign a value to it as follows:

instance_object.property_name = value

Replace value with the new value of the property. Note that in order to propagate the change to the CIMOM, you must also execute the push() method:

instance_object.push()

This method returns a three-item tuple consisting of a return value, return value parameters, and an error string.

Example 22.19. Accessing Individual Properties

To inspect the device instance object created in Example 22.14, “Accessing Instances” and display the value of the property named SystemName, type the following at the interactive prompt:

> device.SystemName
u'server.example.com'
>
Listing and Using Available Methods

To list all available methods of a particular instance object, use the print_methods() method as follows:

instance_object.print_methods()

Replace instance_object with the name of the instance object to inspect. This method prints available methods to standard output.

To get a list of available methods, use the method() method:

instance_object.methods()

This method returns a list of strings.

Example 22.20. Listing Available Methods

To inspect the device instance object created in Example 22.14, “Accessing Instances” and list all available methods, type the following at the interactive prompt:

> device.print_methods()
RequestStateChange
>

To assign a list of these methods to a variable named network_device_methods, type:

> network_device_methods = device.methods()
>

To call a particular method, use the following syntax:

instance_object.method_name(
  parameter=value,
  ...)

Replace instance_object with the name of the instance object to use, method_name with the name of the method to call, parameter with the name of the parameter to set, and value with the value of this parameter. Methods return a three-item tuple consisting of a return value, return value parameters, and an error string.

Important

LMIInstance objects do not automatically refresh their contents (properties, methods, qualifiers, and so on). To do so, use the refresh() method as described below.

Example 22.21. Using Methods

The PG_ComputerSystem class represents the system. To create an instance of this class by using the ns namespace object created in Example 22.5, “Accessing Namespace Objects” and assign it to a variable named sys, type the following at the interactive prompt:

> sys = ns.PG_ComputerSystem.first_instance()
>

The LMI_AccountManagementService class implements methods that allow you to manage users and groups in the system. To create an instance of this class and assign it to a variable named acc, type:

> acc = ns.LMI_AccountManagementService.first_instance()
>

To create a new user named lmishell-user in the system, use the CreateAccount() method as follows:

> acc.CreateAccount(Name="lmishell-user", System=sys)
LMIReturnValue(rval=0, rparams=NocaseDict({u'Account': LMIInstanceName(classname="LMI_Account"...), u'Identities': [LMIInstanceName(classname="LMI_Identity"...), LMIInstanceName(classname="LMI_Identity"...)]}), errorstr='')

LMIShell support synchronous method calls: when you use a synchronous method, LMIShell waits for the corresponding Job object to change its state to "finished" and then returns the return parameters of this job. LMIShell is able to perform a synchronous method call if the given method returns an object of one of the following classes:

  • LMI_StorageJob
  • LMI_SoftwareInstallationJob
  • LMI_NetworkJob

LMIShell first tries to use indications as the waiting method. If it fails, it uses a polling method instead.

To perform a synchronous method call, use the following syntax:

instance_object.Syncmethod_name(
  parameter=value,
  ...)

Replace instance_object with the name of the instance object to use, method_name with the name of the method to call, parameter with the name of the parameter to set, and value with the value of this parameter. All synchronous methods have the Sync prefix in their name and return a three-item tuple consisting of the job’s return value, job’s return value parameters, and job’s error string.

You can also force LMIShell to use only polling method. To do so, specify the PreferPolling parameter as follows:

instance_object.Syncmethod_name(
  PreferPolling=True
  parameter=value,
  ...)
Listing and Viewing ValueMap Parameters

CIM methods may contain ValueMap parameters in their Managed Object Format (MOF) definition. ValueMap parameters contain constant values.

To list all available ValueMap parameters of a particular method, use the print_valuemap_parameters() method as follows:

instance_object.method_name.print_valuemap_parameters()

Replace instance_object with the name of the instance object and method_name with the name of the method to inspect. This method prints available ValueMap parameters to standard output.

To get a list of available ValueMap parameters, use the valuemap_parameters() method:

instance_object.method_name.valuemap_parameters()

This method returns a list of strings.

Example 22.22. Listing ValueMap Parameters

To inspect the acc instance object created in Example 22.21, “Using Methods” and list all available ValueMap parameters of the CreateAccount() method, type the following at the interactive prompt:

> acc.CreateAccount.print_valuemap_parameters()
CreateAccount
>

To assign a list of these ValueMap parameters to a variable named create_account_parameters, type:

> create_account_parameters = acc.CreateAccount.valuemap_parameters()
>

To access a particular ValueMap parameter, use the following syntax:

instance_object.method_name.valuemap_parameterValues

Replace valuemap_parameter with the name of the ValueMap parameter to access.

To list all available constant values, use the print_values() method as follows:

instance_object.method_name.valuemap_parameterValues.print_values()

This method prints available named constant values to standard output. You can also get a list of available constant values by using the values() method:

instance_object.method_name.valuemap_parameterValues.values()

This method returns a list of strings.

Example 22.23. Accessing ValueMap Parameters

Example 22.22, “Listing ValueMap Parameters” mentions a ValueMap parameter named CreateAccount. To inspect this parameter and list available constant values, type the following at the interactive prompt:

> acc.CreateAccount.CreateAccountValues.print_values()
Operationunsupported
Failed
Unabletosetpasswordusercreated
Unabletocreatehomedirectoryusercreatedandpasswordset
Operationcompletedsuccessfully
>

To assign a list of these constant values to a variable named create_account_values, type:

> create_account_values = acc.CreateAccount.CreateAccountValues.values()
>

To access a particular constant value, use the following syntax:

instance_object.method_name.valuemap_parameterValues.constant_value_name

Replace constant_value_name with the name of the constant value. Alternatively, you can use the value() method as follows:

instance_object.method_name.valuemap_parameterValues.value("constant_value_name")

To determine the name of a particular constant value, use the value_name() method:

instance_object.method_name.valuemap_parameterValues.value_name("constant_value")

This method returns a string.

Example 22.24. Accessing Constant Values

Example 22.23, “Accessing ValueMap Parameters” shows that the CreateAccount ValueMap parameter provides a constant value named Failed. To access this named constant value, type the following at the interactive prompt:

> acc.CreateAccount.CreateAccountValues.Failed
2
> acc.CreateAccount.CreateAccountValues.value("Failed")
2
>

To determine the name of this constant value, type:

> acc.CreateAccount.CreateAccountValues.value_name(2)
u'Failed'
>
Refreshing Instance Objects

Local objects used by LMIShell, which represent CIM objects at CIMOM side, can get outdated, if such objects change while working with LMIShell’s ones. To update the properties and methods of a particular instance object, use the refresh() method as follows:

instance_object.refresh()

Replace instance_object with the name of the object to refresh. This method returns a three-item tuple consisting of a return value, return value parameter, and an error string.

Example 22.25. Refreshing Instance Objects

To update the properties and methods of the device instance object created in Example 22.14, “Accessing Instances”, type the following at the interactive prompt:

> device.refresh()
LMIReturnValue(rval=True, rparams=NocaseDict({}), errorstr='')
>
Displaying MOF Representation

To display the Managed Object Format (MOF) representation of an instance object, use the tomof() method as follows:

instance_object.tomof()

Replace instance_object with the name of the instance object to inspect. This method prints the MOF representation of the object to standard output.

Example 22.26. Displaying MOF Representation

To display the MOF representation of the device instance object created in Example 22.14, “Accessing Instances”, type the following at the interactive prompt:

> device.tomof()
instance of LMI_IPNetworkConnection {
    RequestedState = 12;
    HealthState = NULL;
    StatusDescriptions = NULL;
    TransitioningToState = 12;
...

22.4.6. Working with Instance Names

LMIShell instance names are objects that hold a set of primary keys and their values. This type of an object exactly identifies an instance.

Accessing Instance Names

CIMInstance objects are identified by CIMInstanceName objects. To get a list of all available instance name objects, use the instance_names() method as follows:

class_object.instance_names()

Replace class_object with the name of the class object to inspect. This method returns a list of LMIInstanceName objects.

To access the first instance name object of a class object, use the first_instance_name() method:

class_object.first_instance_name()

This method returns an LMIInstanceName object.

In addition to listing all instance name objects or returning the first one, both instance_names() and first_instance_name() support an optional argument to allow you to filter the results:

class_object.instance_names(criteria)
class_object.first_instance_name(criteria)

Replace criteria with a dictionary consisting of key-value pairs, where keys represent key properties and values represent required values of these key properties.

Example 22.27. Accessing Instance Names

To find the first instance name of the cls class object created in Example 22.7, “Accessing Class Objects” that has the Name key property equal to eth0 and assign it to a variable named device_name, type the following at the interactive prompt:

> device_name = cls.first_instance_name({"Name": "eth0"})
>
Examining Instance Names

All instance name objects store information about their class name and the namespace they belong to.

To get the class name of a particular instance name object, use the following syntax:

instance_name_object.classname

Replace instance_name_object with the name of the instance name object to inspect. This returns a string representation of the class name.

To get information about the namespace an instance name object belongs to, use:

instance_name_object.namespace

This returns a string representation of the namespace.

Example 22.28. Examining Instance Names

To inspect the device_name instance name object created in Example 22.27, “Accessing Instance Names” and display its class name and the corresponding namespace, type the following at the interactive prompt:

> device_name.classname
u'LMI_IPNetworkConnection'
> device_name.namespace
'root/cimv2'
>
Creating New Instance Names

LMIShell allows you to create a new wrapped CIMInstanceName object if you know all primary keys of a remote object. This instance name object can then be used to retrieve the whole instance object.

To create a new instance name of a class object, use the new_instance_name() method as follows:

class_object.new_instance_name(key_properties)

Replace class_object with the name of the class object and key_properties with a dictionary that consists of key-value pairs, where keys represent key properties and values represent key property values. This method returns an LMIInstanceName object.

Example 22.29. Creating New Instance Names

The LMI_Account class represents user accounts on the managed system. To use the ns namespace object created in Example 22.5, “Accessing Namespace Objects” and create a new instance name of the LMI_Account class representing the lmishell-user user on the managed system, type the following at the interactive prompt:

> instance_name = ns.LMI_Account.new_instance_name({
...   "CreationClassName" : "LMI_Account",
...   "Name" : "lmishell-user",
...   "SystemCreationClassName" : "PG_ComputerSystem",
...   "SystemName" : "server"})
>
Listing and Accessing Key Properties

To list all available key properties of a particular instance name object, use the print_key_properties() method as follows:

instance_name_object.print_key_properties()

Replace instance_name_object with the name of the instance name object to inspect. This method prints available key properties to standard output.

To get a list of available key properties, use the key_properties() method:

instance_name_object.key_properties()

This method returns a list of strings.

Example 22.30. Listing Available Key Properties

To inspect the device_name instance name object created in Example 22.27, “Accessing Instance Names” and list all available key properties, type the following at the interactive prompt:

> device_name.print_key_properties()
CreationClassName
SystemName
Name
SystemCreationClassName
>

To assign a list of these key properties to a variable named device_name_properties, type:

> device_name_properties = device_name.key_properties()
>

To get the current value of a particular key property, use the following syntax:

instance_name_object.key_property_name

Replace key_property_name with the name of the key property to access.

Example 22.31. Accessing Individual Key Properties

To inspect the device_name instance name object created in Example 22.27, “Accessing Instance Names” and display the value of the key property named SystemName, type the following at the interactive prompt:

> device_name.SystemName
u'server.example.com'
>
Converting Instance Names to Instances

Each instance name can be converted to an instance. To do so, use the to_instance() method as follows:

instance_name_object.to_instance()

Replace instance_name_object with the name of the instance name object to convert. This method returns an LMIInstance object.

Example 22.32. Converting Instance Names to Instances

To convert the device_name instance name object created in Example 22.27, “Accessing Instance Names” to an instance object and assign it to a variable named device, type the following at the interactive prompt:

> device = device_name.to_instance()
>

22.4.7. Working with Associated Objects

The Common Information Model defines an association relationship between managed objects.

Accessing Associated Instances

To get a list of all objects associated with a particular instance object, use the associators() method as follows:

instance_object.associators(
  AssocClass=class_name,
  ResultClass=class_name,
  ResultRole=role,
  IncludeQualifiers=include_qualifiers,
  IncludeClassOrigin=include_class_origin,
  PropertyList=property_list)

To access the first object associated with a particular instance object, use the first_associator() method:

instance_object.first_associator(
  AssocClass=class_name,
  ResultClass=class_name,
  ResultRole=role,
  IncludeQualifiers=include_qualifiers,
  IncludeClassOrigin=include_class_origin,
  PropertyList=property_list)

Replace instance_object with the name of the instance object to inspect. You can filter the results by specifying the following parameters:

  • AssocClass — Each returned object must be associated with the source object through an instance of this class or one of its subclasses. The default value is None.
  • ResultClass — Each returned object must be either an instance of this class or one of its subclasses, or it must be this class or one of its subclasses. The default value is None.
  • Role — Each returned object must be associated with the source object through an association in which the source object plays the specified role. The name of the property in the association class that refers to the source object must match the value of this parameter. The default value is None.
  • ResultRole — Each returned object must be associated with the source object through an association in which the returned object plays the specified role. The name of the property in the association class that refers to the returned object must match the value of this parameter. The default value is None.

The remaining parameters refer to:

  • IncludeQualifiers — A boolean indicating whether all qualifiers of each object (including qualifiers on the object and on any returned properties) should be included as QUALIFIER elements in the response. The default value is False.
  • IncludeClassOrigin — A boolean indicating whether the CLASSORIGIN attribute should be present on all appropriate elements in each returned object. The default value is False.
  • PropertyList — The members of this list define one or more property names. Returned objects will not include elements for any properties missing from this list. If PropertyList is an empty list, no properties are included in returned objects. If it is None, no additional filtering is defined. The default value is None.

Example 22.33. Accessing Associated Instances

The LMI_StorageExtent class represents block devices available in the system. To use the ns namespace object created in Example 22.5, “Accessing Namespace Objects”, create an instance of the LMI_StorageExtent class for the block device named /dev/vda, and assign it to a variable named vda, type the following at the interactive prompt:

> vda = ns.LMI_StorageExtent.first_instance({
...   "DeviceID" : "/dev/vda"})
>

To get a list of all disk partitions on this block device and assign it to a variable named vda_partitions, use the associators() method as follows:

> vda_partitions = vda.associators(ResultClass="LMI_DiskPartition")
>
Accessing Associated Instance Names

To get a list of all associated instance names of a particular instance object, use the associator_names() method as follows:

instance_object.associator_names(
  AssocClass=class_name,
  ResultClass=class_name,
  Role=role,
  ResultRole=role)

To access the first associated instance name of a particular instance object, use the first_associator_name() method:

instance_object.first_associator_name(
  AssocClass=class_object,
  ResultClass=class_object,
  Role=role,
  ResultRole=role)

Replace instance_object with the name of the instance object to inspect. You can filter the results by specifying the following parameters:

  • AssocClass — Each returned name identifies an object that must be associated with the source object through an instance of this class or one of its subclasses. The default value is None.
  • ResultClass — Each returned name identifies an object that must be either an instance of this class or one of its subclasses, or it must be this class or one of its subclasses. The default value is None.
  • Role — Each returned name identifies an object that must be associated with the source object through an association in which the source object plays the specified role. The name of the property in the association class that refers to the source object must match the value of this parameter. The default value is None.
  • ResultRole — Each returned name identifies an object that must be associated with the source object through an association in which the returned named object plays the specified role. The name of the property in the association class that refers to the returned object must match the value of this parameter. The default value is None.

Example 22.34. Accessing Associated Instance Names

To use the vda instance object created in Example 22.33, “Accessing Associated Instances”, get a list of its associated instance names, and assign it to a variable named vda_partitions, type:

> vda_partitions = vda.associator_names(ResultClass="LMI_DiskPartition")
>

22.4.8. Working with Association Objects

The Common Information Model defines an association relationship between managed objects. Association objects define the relationship between two other objects.

Accessing Association Instances

To get a list of association objects that refer to a particular target object, use the references() method as follows:

instance_object.references(
  ResultClass=class_name,
  Role=role,
  IncludeQualifiers=include_qualifiers,
  IncludeClassOrigin=include_class_origin,
  PropertyList=property_list)

To access the first association object that refers to a particular target object, use the first_reference() method:

instance_object.first_reference(
...   ResultClass=class_name,
...   Role=role,
...   IncludeQualifiers=include_qualifiers,
...   IncludeClassOrigin=include_class_origin,
...   PropertyList=property_list)
>

Replace instance_object with the name of the instance object to inspect. You can filter the results by specifying the following parameters:

  • ResultClass — Each returned object must be either an instance of this class or one of its subclasses, or it must be this class or one of its subclasses. The default value is None.
  • Role — Each returned object must refer to the target object through a property with a name that matches the value of this parameter. The default value is None.

The remaining parameters refer to:

  • IncludeQualifiers — A boolean indicating whether each object (including qualifiers on the object and on any returned properties) should be included as a QUALIFIER element in the response. The default value is False.
  • IncludeClassOrigin — A boolean indicating whether the CLASSORIGIN attribute should be present on all appropriate elements in each returned object. The default value is False.
  • PropertyList — The members of this list define one or more property names. Returned objects will not include elements for any properties missing from this list. If PropertyList is an empty list, no properties are included in returned objects. If it is None, no additional filtering is defined. The default value is None.

Example 22.35. Accessing Association Instances

The LMI_LANEndpoint class represents a communication endpoint associated with a certain network interface device. To use the ns namespace object created in Example 22.5, “Accessing Namespace Objects”, create an instance of the LMI_LANEndpoint class for the network interface device named eth0, and assign it to a variable named lan_endpoint, type the following at the interactive prompt:

> lan_endpoint = ns.LMI_LANEndpoint.first_instance({
...   "Name" : "eth0"})
>

To access the first association object that refers to an LMI_BindsToLANEndpoint object and assign it to a variable named bind, type:

> bind = lan_endpoint.first_reference(
...   ResultClass="LMI_BindsToLANEndpoint")
>

You can now use the Dependent property to access the dependent LMI_IPProtocolEndpoint class that represents the IP address of the corresponding network interface device:

> ip = bind.Dependent.to_instance()
> print ip.IPv4Address
192.168.122.1
>
Accessing Association Instance Names

To get a list of association instance names of a particular instance object, use the reference_names() method as follows:

instance_object.reference_names(
  ResultClass=class_name,
  Role=role)

To access the first association instance name of a particular instance object, use the first_reference_name() method:

instance_object.first_reference_name(
  ResultClass=class_name,
  Role=role)

Replace instance_object with the name of the instance object to inspect. You can filter the results by specifying the following parameters:

  • ResultClass — Each returned object name identifies either an instance of this class or one of its subclasses, or this class or one of its subclasses. The default value is None.
  • Role — Each returned object identifies an object that refers to the target instance through a property with a name that matches the value of this parameter. The default value is None.

Example 22.36. Accessing Association Instance Names

To use the lan_endpoint instance object created in Example 22.35, “Accessing Association Instances”, access the first association instance name that refers to an LMI_BindsToLANEndpoint object, and assign it to a variable named bind, type:

> bind = lan_endpoint.first_reference_name(
...   ResultClass="LMI_BindsToLANEndpoint")

You can now use the Dependent property to access the dependent LMI_IPProtocolEndpoint class that represents the IP address of the corresponding network interface device:

> ip = bind.Dependent.to_instance()
> print ip.IPv4Address
192.168.122.1
>

22.4.9. Working with Indications

Indication is a reaction to a specific event that occurs in response to a particular change in data. LMIShell can subscribe to an indication in order to receive such event responses.

Subscribing to Indications

To subscribe to an indication, use the subscribe_indication() method as follows:

connection_object.subscribe_indication(
  QueryLanguage="WQL",
  Query='SELECT * FROM CIM_InstModification',
  Name="cpu",
  CreationNamespace="root/interop",
  SubscriptionCreationClassName="CIM_IndicationSubscription",
  FilterCreationClassName="CIM_IndicationFilter",
  FilterSystemCreationClassName="CIM_ComputerSystem",
  FilterSourceNamespace="root/cimv2",
  HandlerCreationClassName="CIM_IndicationHandlerCIMXML",
  HandlerSystemCreationClassName="CIM_ComputerSystem",
  Destination="http://host_name:5988")

Alternatively, you can use a shorter version of the method call as follows:

connection_object.subscribe_indication(
  Query='SELECT * FROM CIM_InstModification',
  Name="cpu",
  Destination="http://host_name:5988")

Replace connection_object with a connection object and host_name with the host name of the system you want to deliver the indications to.

By default, all subscriptions created by the LMIShell interpreter are automatically deleted when the interpreter terminates. To change this behavior, pass the Permanent=True keyword parameter to the subscribe_indication() method call. This will prevent LMIShell from deleting the subscription.

Example 22.37. Subscribing to Indications

To use the c connection object created in Example 22.1, “Connecting to a Remote CIMOM” and subscribe to an indication named cpu, type the following at the interactive prompt:

> c.subscribe_indication(
...   QueryLanguage="WQL",
...   Query='SELECT * FROM CIM_InstModification',
...   Name="cpu",
...   CreationNamespace="root/interop",
...   SubscriptionCreationClassName="CIM_IndicationSubscription",
...   FilterCreationClassName="CIM_IndicationFilter",
...   FilterSystemCreationClassName="CIM_ComputerSystem",
...   FilterSourceNamespace="root/cimv2",
...   HandlerCreationClassName="CIM_IndicationHandlerCIMXML",
...   HandlerSystemCreationClassName="CIM_ComputerSystem",
...   Destination="http://server.example.com:5988")
LMIReturnValue(rval=True, rparams=NocaseDict({}), errorstr='')
>
Listing Subscribed Indications

To list all the subscribed indications, use the print_subscribed_indications() method as follows:

connection_object.print_subscribed_indications()

Replace connection_object with the name of the connection object to inspect. This method prints subscribed indications to standard output.

To get a list of subscribed indications, use the subscribed_indications() method:

connection_object.subscribed_indications()

This method returns a list of strings.

Example 22.38. Listing Subscribed Indications

To inspect the c connection object created in Example 22.1, “Connecting to a Remote CIMOM” and list all subscribed indications, type the following at the interactive prompt:

> c.print_subscribed_indications()
>

To assign a list of these indications to a variable named indications, type:

> indications = c.subscribed_indications()
>
Unsubscribing from Indications

By default, all subscriptions created by the LMIShell interpreter are automatically deleted when the interpreter terminates. To delete an individual subscription sooner, use the unsubscribe_indication() method as follows:

connection_object.unsubscribe_indication(indication_name)

Replace connection_object with the name of the connection object and indication_name with the name of the indication to delete.

To delete all subscriptions, use the unsubscribe_all_indications() method:

connection_object.unsubscribe_all_indications()

Example 22.39. Unsubscribing from Indications

To use the c connection object created in Example 22.1, “Connecting to a Remote CIMOM” and unsubscribe from the indication created in Example 22.37, “Subscribing to Indications”, type the following at the interactive prompt:

> c.unsubscribe_indication('cpu')
LMIReturnValue(rval=True, rparams=NocaseDict({}), errorstr='')
>
Implementing an Indication Handler

The subscribe_indication() method allows you to specify the host name of the system you want to deliver the indications to. The following example shows how to implement an indication handler:

> def handler(ind, arg1, arg2, kwargs): ... exported_objects = ind.exported_objects() ... do_something_with(exported_objects) > listener = LmiIndicationListener("0.0.0.0", listening_port) > listener.add_handler("indication-name-XXXXXXXX", handler, arg1, arg2, kwargs)
> listener.start()
>

The first argument of the handler is an LmiIndication object, which contains a list of methods and objects exported by the indication. Other parameters are user specific: those arguments need to be specified when adding a handler to the listener.

In the example above, the add_handler() method call uses a special string with eight "X" characters. These characters are replaced with a random string that is generated by listeners in order to avoid a possible handler name collision. To use the random string, start the indication listener first and then subscribe to an indication so that the Destination property of the handler object contains the following value: schema://host_name/random_string.

Example 22.40. Implementing an Indication Handler

The following script illustrates how to write a handler that monitors a managed system located at 192.168.122.1 and calls the indication_callback() function whenever a new user account is created:

#!/usr/bin/lmishell

import sys
from time import sleep
from lmi.shell.LMIUtil import LMIPassByRef
from lmi.shell.LMIIndicationListener import LMIIndicationListener

# These are passed by reference to indication_callback
var1 = LMIPassByRef("some_value")
var2 = LMIPassByRef("some_other_value")

def indication_callback(ind, var1, var2):
  # Do something with ind, var1 and var2
  print ind.exported_objects()
  print var1.value
  print var2.value

c = connect("hostname", "username", "password")

listener = LMIIndicationListener("0.0.0.0", 65500)
unique_name = listener.add_handler(
  "demo-XXXXXXXX",   # Creates a unique name for me
  indication_callback, # Callback to be called
  var1,        # Variable passed by ref
  var2         # Variable passed by ref
)

listener.start()

print c.subscribe_indication(
  Name=unique_name,
  Query="SELECT * FROM LMI_AccountInstanceCreationIndication WHERE SOURCEINSTANCE ISA LMI_Account",
  Destination="192.168.122.1:65500"
)

try:
  while True:
    sleep(60)
except KeyboardInterrupt:
  sys.exit(0)

22.4.10. Example Usage

This section provides a number of examples for various CIM providers distributed with the OpenLMI packages. All examples in this section use the following two variable definitions:

c = connect("host_name", "user_name", "password")
ns = c.root.cimv2

Replace host_name with the host name of the managed system, user_name with the name of user that is allowed to connect to OpenPegasus CIMOM running on that system, and password with the user’s password.

Using the OpenLMI Service Provider

The openlmi-service package installs a CIM provider for managing system services. The examples below illustrate how to use this CIM provider to list available system services and how to start, stop, enable, and disable them.

Example 22.41. Listing Available Services

To list all available services on the managed machine along with information regarding whether the service has been started (TRUE) or stopped (FALSE) and the status string, use the following code snippet:

for service in ns.LMI_Service.instances():
  print "%s:\t%s" % (service.Name, service.Status)

To list only the services that are enabled by default, use this code snippet:

cls = ns.LMI_Service
for service in cls.instances():
  if service.EnabledDefault == cls.EnabledDefaultValues.Enabled:
    print service.Name

Note that the value of the EnabledDefault property is equal to 2 for enabled services and 3 for disabled services.

To display information about the cups service, use the following:

cups = ns.LMI_Service.first_instance({"Name": "cups.service"})
cups.doc()

Example 22.42. Starting and Stopping Services

To start and stop the cups service and to see its current status, use the following code snippet:

cups = ns.LMI_Service.first_instance({"Name": "cups.service"})
cups.StartService()
print cups.Status
cups.StopService()
print cups.Status

Example 22.43. Enabling and Disabling Services

To enable and disable the cups service and to display its EnabledDefault property, use the following code snippet:

cups = ns.LMI_Service.first_instance({"Name": "cups.service"})
cups.TurnServiceOff()
print cups.EnabledDefault
cups.TurnServiceOn()
print cups.EnabledDefault
Using the OpenLMI Networking Provider

The openlmi-networking package installs a CIM provider for networking. The examples below illustrate how to use this CIM provider to list IP addresses associated with a certain port number, create a new connection, configure a static IP address, and activate a connection.

Example 22.44. Listing IP Addresses Associated with a Given Port Number

To list all IP addresses associated with the eth0 network interface, use the following code snippet:

device = ns.LMI_IPNetworkConnection.first_instance({'ElementName': 'eth0'})
for endpoint in device.associators(AssocClass="LMI_NetworkSAPSAPDependency", ResultClass="LMI_IPProtocolEndpoint"):
  if endpoint.ProtocolIFType == ns.LMI_IPProtocolEndpoint.ProtocolIFTypeValues.IPv4:
    print "IPv4: %s/%s" % (endpoint.IPv4Address, endpoint.SubnetMask)
  elif endpoint.ProtocolIFType == ns.LMI_IPProtocolEndpoint.ProtocolIFTypeValues.IPv6:
    print "IPv6: %s/%d" % (endpoint.IPv6Address, endpoint.IPv6SubnetPrefixLength)

This code snippet uses the LMI_IPProtocolEndpoint class associated with a given LMI_IPNetworkConnection class.

To display the default gateway, use this code snippet:

for rsap in device.associators(AssocClass="LMI_NetworkRemoteAccessAvailableToElement", ResultClass="LMI_NetworkRemoteServiceAccessPoint"):
  if rsap.AccessContext == ns.LMI_NetworkRemoteServiceAccessPoint.AccessContextValues.DefaultGateway:
    print "Default Gateway: %s" % rsap.AccessInfo

The default gateway is represented by an LMI_NetworkRemoteServiceAccessPoint instance with the AccessContext property equal to DefaultGateway.

To get a list of DNS servers, the object model needs to be traversed as follows:

  1. Get the LMI_IPProtocolEndpoint instances associated with a given LMI_IPNetworkConnection using LMI_NetworkSAPSAPDependency.
  2. Use the same association for the LMI_DNSProtocolEndpoint instances.

The LMI_NetworkRemoteServiceAccessPoint instances with the AccessContext property equal to the DNS Server associated through LMI_NetworkRemoteAccessAvailableToElement have the DNS server address in the AccessInfo property.

There can be more possible paths to get to the RemoteServiceAccessPath and entries can be duplicated. The following code snippet uses the set() function to remove duplicate entries from the list of DNS servers:

dnsservers = set()
for ipendpoint in device.associators(AssocClass="LMI_NetworkSAPSAPDependency", ResultClass="LMI_IPProtocolEndpoint"):
  for dnsedpoint in ipendpoint.associators(AssocClass="LMI_NetworkSAPSAPDependency", ResultClass="LMI_DNSProtocolEndpoint"):
    for rsap in dnsedpoint.associators(AssocClass="LMI_NetworkRemoteAccessAvailableToElement", ResultClass="LMI_NetworkRemoteServiceAccessPoint"):
      if rsap.AccessContext == ns.LMI_NetworkRemoteServiceAccessPoint.AccessContextValues.DNSServer:
        dnsservers.add(rsap.AccessInfo)
print "DNS:", ", ".join(dnsservers)

Example 22.45. Creating a New Connection and Configuring a Static IP Address

To create a new setting with a static IPv4 and stateless IPv6 configuration for network interface eth0, use the following code snippet:

capability = ns.LMI_IPNetworkConnectionCapabilities.first_instance({ 'ElementName': 'eth0' })
result = capability.LMI_CreateIPSetting(Caption='eth0 Static',
    IPv4Type=capability.LMI_CreateIPSetting.IPv4TypeValues.Static,
    IPv6Type=capability.LMI_CreateIPSetting.IPv6TypeValues.Stateless)
setting = result.rparams["SettingData"].to_instance()
for settingData in setting.associators(AssocClass="LMI_OrderedIPAssignmentComponent"):
  if setting.ProtocolIFType == ns.LMI_IPAssignmentSettingData.ProtocolIFTypeValues.IPv4:
    # Set static IPv4 address
    settingData.IPAddresses = ["192.168.1.100"]
    settingData.SubnetMasks = ["255.255.0.0"]
    settingData.GatewayAddresses = ["192.168.1.1"]
    settingData.push()

This code snippet creates a new setting by calling the LMI_CreateIPSetting() method on the instance of LMI_IPNetworkConnectionCapabilities, which is associated with LMI_IPNetworkConnection through LMI_IPNetworkConnectionElementCapabilities. It also uses the push() method to modify the setting.

Example 22.46. Activating a Connection

To apply a setting to the network interface, call the ApplySettingToIPNetworkConnection() method of the LMI_IPConfigurationService class. This method is asynchronous and returns a job. The following code snippets illustrates how to call this method synchronously:

setting = ns.LMI_IPAssignmentSettingData.first_instance({ "Caption": "eth0 Static" })
port = ns.LMI_IPNetworkConnection.first_instance({ 'ElementName': 'ens8' })
service = ns.LMI_IPConfigurationService.first_instance()
service.SyncApplySettingToIPNetworkConnection(SettingData=setting, IPNetworkConnection=port, Mode=32768)

The Mode parameter affects how the setting is applied. The most commonly used values of this parameter are as follows:

  • 1 — apply the setting now and make it auto-activated.
  • 2 — make the setting auto-activated and do not apply it now.
  • 4 — disconnect and disable auto-activation.
  • 5 — do not change the setting state, only disable auto-activation.
  • 32768 — apply the setting.
  • 32769 — disconnect.
Using the OpenLMI Storage Provider

The openlmi-storage package installs a CIM provider for storage management. The examples below illustrate how to use this CIM provider to create a volume group, create a logical volume, build a file system, mount a file system, and list block devices known to the system.

In addition to the c and ns variables, these examples use the following variable definitions:

MEGABYTE = 1024*1024
storage_service = ns.LMI_StorageConfigurationService.first_instance()
filesystem_service = ns.LMI_FileSystemConfigurationService.first_instance()

Example 22.47. Creating a Volume Group

To create a new volume group located in /dev/myGroup/ that has three members and the default extent size of 4 MB, use the following code snippet:

# Find the devices to add to the volume group
# (filtering the CIM_StorageExtent.instances()
# call would be faster, but this is easier to read):
sda1 = ns.CIM_StorageExtent.first_instance({"Name": "/dev/sda1"})
sdb1 = ns.CIM_StorageExtent.first_instance({"Name": "/dev/sdb1"})
sdc1 = ns.CIM_StorageExtent.first_instance({"Name": "/dev/sdc1"})

# Create a new volume group:
(ret, outparams, err) = storage_service.SyncCreateOrModifyVG(
    ElementName="myGroup",
    InExtents=[sda1, sdb1, sdc1])
vg = outparams['Pool'].to_instance()
print "VG", vg.PoolID, \
    "with extent size", vg.ExtentSize, \
    "and", vg.RemainingExtents, "free extents created."

Example 22.48. Creating a Logical Volume

To create two logical volumes with the size of 100 MB, use this code snippet:

# Find the volume group:
vg = ns.LMI_VGStoragePool.first_instance({"Name": "/dev/mapper/myGroup"})

# Create the first logical volume:
(ret, outparams, err) = storage_service.SyncCreateOrModifyLV(
    ElementName="Vol1",
    InPool=vg,
    Size=100 * MEGABYTE)
lv = outparams['TheElement'].to_instance()
print "LV", lv.DeviceID, \
    "with", lv.BlockSize * lv.NumberOfBlocks,\
    "bytes created."

# Create the second logical volume:
(ret, outparams, err) = storage_service.SyncCreateOrModifyLV(
    ElementName="Vol2",
    InPool=vg,
    Size=100 * MEGABYTE)
lv = outparams['TheElement'].to_instance()
print "LV", lv.DeviceID, \
    "with", lv.BlockSize * lv.NumberOfBlocks, \
    "bytes created."

Example 22.49. Creating a File System

To create an ext3 file system on logical volume lv from Example 22.48, “Creating a Logical Volume”, use the following code snippet:

(ret, outparams, err) = filesystem_service.SyncLMI_CreateFileSystem(
    FileSystemType=filesystem_service.LMI_CreateFileSystem.FileSystemTypeValues.EXT3,
    InExtents=[lv])

Example 22.50. Mounting a File System

To mount the file system created in Example 22.49, “Creating a File System”, use the following code snippet:

# Find the file system on the logical volume:
fs = lv.first_associator(ResultClass="LMI_LocalFileSystem")

mount_service = ns.LMI_MountConfigurationService.first_instance()
(rc, out, err) = mount_service.SyncCreateMount(
   FileSystemType='ext3',
   Mode=32768, # just mount
   FileSystem=fs,
   MountPoint='/mnt/test',
   FileSystemSpec=lv.Name)

Example 22.51. Listing Block Devices

To list all block devices known to the system, use the following code snippet:

devices = ns.CIM_StorageExtent.instances()
for device in devices:
  if lmi_isinstance(device, ns.CIM_Memory):
    # Memory and CPU caches are StorageExtents too, do not print them
    continue
  print device.classname,
  print device.DeviceID,
  print device.Name,
  print device.BlockSize*device.NumberOfBlocks
Using the OpenLMI Hardware Provider

The openlmi-hardware package installs a CIM provider for monitoring hardware. The examples below illustrate how to use this CIM provider to retrieve information about CPU, memory modules, PCI devices, and the manufacturer and model of the machine.

Example 22.52. Viewing CPU Information

To display basic CPU information such as the CPU name, the number of processor cores, and the number of hardware threads, use the following code snippet:

cpu = ns.LMI_Processor.first_instance()
cpu_cap = cpu.associators(ResultClass="LMI_ProcessorCapabilities")[0]
print cpu.Name
print cpu_cap.NumberOfProcessorCores
print cpu_cap.NumberOfHardwareThreads

Example 22.53. Viewing Memory Information

To display basic information about memory modules such as their individual sizes, use the following code snippet:

mem = ns.LMI_Memory.first_instance()
for i in mem.associators(ResultClass="LMI_PhysicalMemory"):
  print i.Name

Example 22.54. Viewing Chassis Information

To display basic information about the machine such as its manufacturer or its model, use the following code snippet:

chassis = ns.LMI_Chassis.first_instance()
print chassis.Manufacturer
print chassis.Model

Example 22.55. Listing PCI Devices

To list all PCI devices known to the system, use the following code snippet:

for pci in ns.LMI_PCIDevice.instances():
  print pci.Name

22.5. Using OpenLMI Scripts

The LMIShell interpreter is built on top of Python modules that can be used to develop custom management tools. The OpenLMI Scripts project provides a number of Python libraries for interfacing with OpenLMI providers. In addition, it is distributed with lmi, an extensible utility that can be used to interact with these libraries from the command line.

To install OpenLMI Scripts on your system, type the following at a shell prompt:

easy_install --user openlmi-scripts

This command installs the Python modules and the lmi utility in the ~/.local/ directory. To extend the functionality of the lmi utility, install additional OpenLMI modules by using the following command:

easy_install --user package_name

For a complete list of available modules, see the Python website. For more information about OpenLMI Scripts, see the official OpenLMI Scripts documentation.

22.6. Additional Resources

For more information about OpenLMI and system management in general, see the resources listed below.

Installed Documentation

  • lmishell(1) — The manual page for the lmishell client and interpreter provides detailed information about its execution and usage.

Online Documentation

  • Red Hat Enterprise Linux 7 Networking Guide — The Networking Guide for Red Hat Enterprise Linux 7 documents relevant information regarding the configuration and administration of network interfaces and network services on the system.
  • Red Hat Enterprise Linux 7 Storage Administration Guide — The Storage Administration Guide for Red Hat Enterprise Linux 7 provides instructions on how to manage storage devices and file systems on the system.
  • Red Hat Enterprise Linux 7 Power Management Guide — The Power Management Guide for Red Hat Enterprise Linux 7 explains how to manage power consumption of the system effectively. It discusses different techniques that lower power consumption for both servers and laptops, and explains how each technique affects the overall performance of the system.
  • Red Hat Enterprise Linux 7 Linux Domain Identity, Authentication, and Policy Guide — The Linux Domain Identity, Authentication, and Policy Guide for Red Hat Enterprise Linux 7 covers all aspects of installing, configuring, and managing IPA domains, including both servers and clients. The guide is intended for IT and systems administrators.
  • FreeIPA Documentation — The FreeIPA Documentation serves as the primary user documentation for using the FreeIPA Identity Management project.
  • OpenSSL Home Page — The OpenSSL home page provides an overview of the OpenSSL project.
  • Mozilla NSS Documentation — The Mozilla NSS Documentation serves as the primary user documentation for using the Mozilla NSS project.

See Also

  • Chapter 4, Managing Users and Groups documents how to manage system users and groups in the graphical user interface and on the command line.
  • Chapter 9, Yum describes how to use the Yum package manager to search, install, update, and uninstall packages on the command line.
  • Chapter 10, Managing Services with systemd provides an introduction to systemd and documents how to use the systemctl command to manage system services, configure systemd targets, and execute power management commands.
  • Chapter 12, OpenSSH describes how to configure an SSH server and how to use the ssh, scp, and sftp client utilities to access it.