Linux configuration with OpenLMI
Cosmopolitan
Quickly changing the network configuration on a system should not really be a problem. But how did that work on a Debian system? If you mainly deal with other distributions, you often need to invest a few minutes more for what are actually simple tasks. Seasoned admins will of course have established their own toolboxes over time with useful scripts and tools. Thanks to these toolboxes, most of the routine tasks can be done in next to no time. However, maintaining and improving the toolbox also takes time.
Multiple Distributions
What happens if your employer wants to introduce a new Linux distribution? Will the scripts work the new distribution? Maybe not. You thus need to maintain different versions of a script. Alternatively, the script can be adjusted so that it performs the desired work on different systems. But this costs the admin more time, and because time is a scarce commodity, you might want to look for other solutions.
Furthermore, this approach does not scale very well. Why would anyone want to reinvent the wheel, if we could simply agree on a standard for performing the same work on different systems? In the area of system management, the Open Linux Management Infrastructure (OpenLMI) [1] is trying to define such a standard.
OpenLMI is based on the Common Information Model (CIM) standards. CIM in turn is a Web-Based Enterprise Management (WBEM) component [2], another standard of the Distributed Management Task Force (DMTF) that is made up of various components (such as CIM) and defines various technologies and methods for unified management of computer systems.
The CIM component describes the typical object classes to be used on a system to be managed (hardware, software, users, and a variety of subsystems) in a kind of schema. CIM determines what an instance of a particular class looks like and how it relates to other objects of the class. In the everyday use of WBEM, the term CIM is used, most of the time, not only for the schema description itself, but for the technology and associated tools. However, CIM is only a portion of the larger WBEM specification.
Architecture
Each system for which the OpenLMI framework is responsible must have a CIM Object Manager (CIMOM), which is a broker that communicates with a management system (in the article, this system always represented as a client). The broker receives the requests and forwards them to providers, which then do the actual work. This work takes place on the system's various object classes. Providers exist for different types of objects, which in turn individually describe a system.
Communication with the client systems (i.e., the systems from which the brokers receive their requests) takes place via a protocol standardized by the DMTF. The protocol, known as CIM Operations over HTTP, was most recently revised in December 2013 [3]. Basically, this is an XML document that is transmitted between the broker and the client in both directions using HTTP. Client authentication against the broker is required before you can exchange data between systems. After this, the client can then query, and also change, certain objects' properties by means of predefined methods.
The provider responsible for a particular object decides which methods are used. One example is the CIM network provider, which has a Network Port class. Multiple instances of this class can exist that then reflect the individual network cards in the system. A property of the class could be, for example, MaxSpeed. If you query this, the maximum speed of the card will be displayed. This is possible for all instances of the Network Port class.
Installation
The following section looks at the setup and configuration of a CIMOM and a client system. A recent version of Fedora, which is used on both systems, provides the required packages via the distribution's standard repositories. As the broker, Fedora uses the OpenPegasus WBEM service; a number of providers are available for various subsystems. A WBEM client and interpreter are used on the client system; they can address the desired CIM objects on the broker. Client authentication is necessary when accessing the broker. This is based on user names and passwords, which are defined previously on the broker. Because communication is via the insecure HTTP protocol, the use of X.509 certificates is recommended for production use. This supports data encryption using the secure HTTPS protocol. In my example, both systems belong to a FreeIPA domain so that the broker can easily retrieve a certificate from the identity management framework. The use of self-signed certificates is also possible for test purposes.
On systems running the CIM broker, the OpenPegasus WBEM services and the most important CIM providers then can be easily installed using the distribution's dnf
package manager:
# dnf install tog-pegasus # dnf install openlmi-{storage,networking,service,account,hardware,powermanagement}
More providers can be installed, if required. For testing purposes, however, the newly installed packages are all you need. As an alternative to this procedure, the source code is available on the OpenLMI project website. Although the OpenPegasus CIMOM is now the de facto standard in the open source environment, there are a few other brokers – for example, the Small Footprint CIM Broker (SFCB), which is often used in the embedded Linux industry.
In the file /etc/Pegasus/access.conf
, you define which users have access to the broker. You need to set a password for the broker on the system. Since HTTP Basic authentication is used to log in the users, and thus all data are transferred in the clear, a corresponding X.509 certificate should be used on the CIMOM systems to support client system access via HTTPS.
In this article, I assume that all systems are part of a FreeIPA domain – this is not a requirement. Another Kerberos principal can be easily created on the broker for the CIMOM service to then request an X.509 certificate for this service (Listing 1). This also has the advantage that the certificates can be managed by the FreeIPA client service, certmonger
. This ensures, for example, that the certificates are renewed when their expiration dates mature and they become be invalid.
Listing 1: Request a Certificate
# ipa service-add CIMOM/`hostname` ------------------------------------------------------------------------------- Added service "CIMOM/broker.example.com@EXAMPLE.COM" ------------------------------------------------------------------------------- Principal: CIMOM/broker.example.com@EXAMPLE.COM Managed by: broker.example.com # ipa-getcert request -f /etc/Pegasus/server.pem -k /etc/Pegasus/file.pem -N CN=`hostname` -K CIMOM/`hostname`
Also note that there is currently a problem in connection with SELinux, if you want certmonger
to store the certificate in the default path below /etc/Pegasus
, since access to these folders is prevented by an enabled SELinux policy. Unfortunately, the path cannot be changed by means of a configuration statement, so the only available approach is to write your own SELinux policy module that permits access to the folder or to run the certmonger
service in SELinux's permissive mode. Since the first option would go beyond the scope of this article [4], I am simply assuming that the service is in permissive mode. This can be easily implemented using the following command:
# semanage permissive -a certmonger_t
Dropping the certificate in the /etc/Pegasus
folder will then work, although the audited service still displays SELinux error messages. Of course, you can also obtain a certificate from a different certificate authority (CA). In any case, you need to ensure that the CA certificate is also available, in addition to the certificate and the corresponding key for the broker. Save this in /etc/Pegasus/client.pem
. The CA certificate naturally also needs to be available in the X. 509 trust store on the client systems so that the connection to the broker is validated. Finally, you need to launch and permanently enable the CIMOM service:
# systemctl start tog-pegasus.service # systemctl enable tog-pegasus.service
On the client systems, the openlmi-tools package must be in place. It contains the lmi
meta-tool, which can send the generic high-level commands to a broker. There is also lmishell
, which is based on a Python interpreter.
It can be used both interactively and non-interactively. To be able to work with the tools, you also need to install the OpenLMI scripts. These are Python libraries that provide access to the various CIMOM objects. The installation again relies on the dnf
package manager:
# dnf install openlmi-tools "openlmi-scripts-*"
First Steps
The lmi
tool is useful for testing whether communication between the broker and a client system is working. Listing 2 shows how to access the client information via the broker system.
Listing 2: Access Client Information
# lmi --user pegasus -h ibm-x3455-2.example.comm lmi> system password: ========================================================== Host: ibm-x3455-2.example.com ========================================================== Hardware: IBM IBM eServer x3455-[xxxxxxx] Serial Number: -[UUID:C8040008000011037D001276EE0201AB]- Asset Tag: -[UUID:C8040008000011037D001276EE0201AB]- CPU: AMD, x86_64 arch CPU Topology: 4 cpu(s), 8 core(s), 8 thread(s) Memory: 2.0 GB Disk Space: N/A GB total, N/A GB free OS: Fedora release 23 (Twenty Three) Kernel: 4.3.5-300.fc23.x86_64 Firewall: off Logging: on (journald)
Within the lmi
tool, you can use the built-in help to discover the features provided by the previously installed OpenLMI scripts. help script name
calls the help for an installed script. For example, calling help service
shows that this provider gives you an easy approach to managing the remote services.
A simple httpd service show
indicates the status of the web server on the remote system. The statement for starting service httpd start
would then be:
lmi> service show httpd Name=httpd Caption=The Apache HTTP Server Enabled=No Status=Running
It is worthwhile experimenting a little with the scripts. For many standard tasks, they are capable of simply and easily managing a wide variety of systems. See the scripts tutorial [5] for help developing your own scripts for the lmi
tool.
LMIShell
Things become really interesting when you start using the LMIShell. It is fully programmable and can even be used interactively, like the Python interpreter itself. Each CIM object is converted by the LMIShell to a Python object so that you can develop very comprehensive scripts given some basic knowledge of Python. The following section introduces some basic functions that should make it easier to get started with writing your own scripts.
To access a broker system, you first need to define a connection object. It contains the name of the system you want to communicate with and defines how to handle authentication against this system:
# lmishell > c = connect("ibm-x3455-2.example.com", "pegasus", "redhat")
The following method can be used to verify the successful creation of the connection object:
> isinstance(c, LMIConnection) True
The broker breaks down the available classes into namespaces that you can view by typing c.root.print_namespaces()
. If you want to access a particular namespace, this is achieved as follows:
> ns = c.root.cimv2
You can display the classes contained within this namespace by typing ns.print_classes()
. To access a particular class, simply create a new instance of the class (e.g., srv=ns.LMI_Service
for the service class). By the way, the shell also supports tab completion. After creating a namespace object, you can type ns.
and press Tab to show all the classes. srv.doc()
tells more about the existing methods of the services object you just created.
The following simple script should now return all of a system's services. Save it in the services.lmi
file:
#!/usr/bin/lmishell c = connect("ibm-x3455-2.example.com", "pegasus", "redhat") ns = c.root.cimv2 srv = c.root.cimv2.LMI_Service for service in srv.instances(): print "Name:\t %s" % (service.Name)
Of course, you can choose a shorter notation instead:
for service in c.root.cimv2.LMI_Service.instances(): print "Name:\t %s" % (service.Name)
After calling the script with lmishell services.lmi
, you see an overview of the existing services on the system ibm-x3455-2.example.com
. If you are interested in the enabled services instead, simply change the statement:
for service in srv.instances(): if service.EnabledDefault == srv.EnabledDefaultValues.Enabled: print "Name:\t %s" % (service.Name)
For similar examples and additional information, see the excellent and detailed OpenLMI documentation [6].
Joining a Domain
Finally, let's just point out the Realmd CIM provider; this subject is discussed in detail in the article on the FreeIPA identity management framework in this issue. The Realmd provider is a practical example of how you can easily add a variety of Linux systems to an existing FreeIPA domain with the help of OpenLMI. This is usually done by calling ipa-client install
. With just three lines of OpenLMI code, the Realmd provider handles this task:
c = connect("ibm-x3455-2.example.com", "pegasus", "redhat") realm = c.root.cimv2.LMI_RealmdService.first_instance() realm.JoinDomain( Domain="example.com", User="admin", Password="password")
The charm of this approach is that you can include this snippet of code in a larger script, with the help of which you could define, for example, the complete provisioning action for the system, ranging from the installation to the configuration of individual services.
Conclusion
OpenLMI provides an interface for performing a variety of standard tasks on Linux systems. The syntax of the individual command-line tools does not need to be known for this because it is abstracted by the OpenLMI scripts. This simplifies the system administration especially for newcomers.
The LMIShell is a powerful tool that supports programming for complex tasks to suit your own requirements. Ready-made scripts already exist for many tasks, and these can be easily used as a jumping-off point for developing your own scripts.