OpenLMI
=======

The OpenLMI project provides a common infrastructure for the management
of Linux systems.  Capabilities include configuration, management
and monitoring of hardware, operating systems, and system services.
OpenLMI includes a set of services that can be accessed both locally
and remotely, multiple language bindings, standard APIs, and standard
scripting interfaces.


openlmi-providers
-----------------

openlmi-providers is set of (usually) small providers (agents) that will
provide given functionality on host system.  Following providers are part
of this sub-project:

 *  **Account** provider manages POSIX accounts. It allows to list,
    create, delete and modify users and groups.

 *  **Fan** provider implements interface for hardware monitoring of fans
    in the system. It uses lm_sensors library so it's linux specific.
    There are three interfaces provided according to CIM model:

     *  *Linux_Fan* - Provides instance for every fan founded by
        lm_sensors with basic information.

     *  *Linux_FanSensor* - Associated sensor for each instance of
         Linux_Fan.  Value of fan speed can be obtained from property
         `CurrentReading`.

     *  *Linux_FanAssociatedSensor* - Provides association of instances
         of above 2 providers.

 *  **Hardware** provider allows to list various HW components on the
    managed system such as PCI devices, CPUs and memory.

 *  **Journald** provider exposes data stored in SystemD Journal
    service. See [systemd project][1] for more information.  For the
    moment, global journal is used, all journal files are mixed together.
    This may change in the future.

 *  **LogicalFile** provider is for logical file management.  Supports
    ordinary files, directories, links, device files and fifo files.
    The provider allows to read files, create new directories and remove
    directories.

 *  **Power** provider allows to monitor and change power state of
    the computer system.  Supports commands *halt*, *reboot*, *suspend*
    and *hibernate*.

 *  **Service** provider allows manipulation with system services.
    Supports commands: *status*, *start*, *stop*, *restart*, *enable* and
    *disable*.

    This provider comes in two distinct implementations, one using
    systemd (service-dbus) and one using init scripts in /etc/rc.d/init.d
    (service).

 *  **Software** provider allows to install, remove, list and update
    packages.  Requires python 2.6+ and yum.

    This provider comes in two distinct implementations, one using
    yum python API (software) and second using PackageKit (software-dbus).

 *  **RealmD** provider interfaces with the RealmD daemon which allows
    for the Kerberos and Active Directory realms enrollment

 *  **PCP** provider interfaces with the PCP (Performance Co-Pilot)
    daemon.  Allows reading of PCP metrics on the local host.

 *  **Locale** provider interfaces wiith *systemd-localed*.  Allows to
    control system locale variables (LANG, LC_PAPER, ...) and keyboard
    mapping for virtual console and X11.

 *  **SSSD** provider interfaces with the [SSSD][2] daemon.

 *  **SELinux** provider interfaces with SELinux.

 [1]: http://www.freedesktop.org/wiki/Software/systemd/ 
 [2]: https://fedorahosted.org/sssd/


Support libraries
-----------------

This package contains also several C libraries, which make provider development
a bit more comfortable.

 *  **Indication Manager** (libindmanager) - simplifies indication sending by
    semi-automatic watching list of CIM instances and reporting its changes.

 *  **Indication Sender** (libindsender) - simplifies management of indications,
    which are based on static filters.

 *  **Job Manager** (libjobmanager) - simplifies CIM_ConcreteJob processing.

 *  **OpenLMI library** (libopenlmi) - various utility functions used by more
    than one OpenLMI provider.

Build Dependencies
------------------

For all providers:

 -  cmake
 -  gcc
 -  konkretcmpi-devel
 -  sblim-cmpi-devel
 -  cim-schema
 -  glib2-devel 2.26+

For documentation:

 -  python-sphinx
 -  konkretcmpi-python
 -  (optionally) plantuml

Provider specific dependencies:

 *  *Account*

    - libuser-devel

 *  *Fan*

    - lm_sensors - installed and configured
    - lm_sensors-libs
    - lm_sensors-devel

 *  *Hardware*

    - pciutils-devel
    - dmidecode

 *  *Journald*

    - systemd-devel

 *  *LogicalFile*

    - libudev-devel (systemd-devel)
    - libselinux-devel

 *  *Power*

    - logind (part of systemd) or pm-utils
    - shutdown and reboot commands in $PATH (usually provided by systemd,
      upstart or SysVinit)

 * *SELinux*

    - libxml2-devel
    - libsemanage-devel
    - libjobmanager (from this package)
    - libindsender (from this package)

 *  *Service*

    - systemd

 *  *RealmD*

    - dbus-devel

 *  *PCP*

    - python-pcp

 *  *Locale*

    - systemd 30+ (systemd-localed)

 *  *SSSD*

    - dbus-devel
    - libsss_simpleifp-devel

 *  *Software* (the DBus-specific variant)

    - libjobmanager (from this package)
    - libindsender (from this package)


Library dependencies:

 *  *libjobmanager*

    - json-glib-devel 1.0+


Compilation and installation
----------------------------

    $ mkdir build && cd build
    $ cmake .. -DCMAKE_INSTALL_PREFIX=/usr
    $ make
    $ make doc
    # make install
    # make register-Fan
    # make register-PowerManagement
    # make register-Service

You can disable specific provider by adding `-DWITH-<PROVIDER>=0` to
cmake line.



Development Tips
----------------


### Understanding konkret code generation issues ###

konkret is a tool that reads in a mof file and generates C code.
For every XXX class it will generate a XXX.h and XXXProvider.c file.
The code generation occurs due to CMake macros provided by the
openlmi-providers-devel package. konkret needs to run any time you modify
the mof file.  It *always* generates a new XXX.h file because that's
where definitions based on the contents of the mof file are located.
If there is no XXXProvider.c file it will also generate it.  This is
a "stub" file in which you will fill in with your implementation.
If XXXProvider.c exits it will not overwrite it, however it always
overwrites the XXX.h file.

Do not put anything into the XXX.h file you'll need to retain.

After editing the mof file the make targets will cause konkret to run
again.  You'll get brand new XXX.h files.  But your old XXXProvider.c
files may no longer have the correct definitions (e.g. prototypes) found
in the XXX.h file so you may need to hand edit by copying the function
prototype from the XXX.h file into your XXXProvider.c file.

If you've written definitions that logically belong in XXX.h but don't
want them nuked the next time konkret runs my solution was to put them
in someother .h file that's included by the XXXProvider.c file.


### Initializing class instances ###

The way konkret works is to emit specialized inline functions to
initialize each member of a class.  If the class is subclassed
you get different initializers depending on whether the property
is in the parent class or the subclass.  You cannot call a parent
class property initializer in a subclass (yuck), you have to use the
subclass initializer for the property inherited from the parent class.
This creates a maintenance problem if the parent class changes, you have
find every place parent class properties are inialized and make changes.
To solve this problem I defined macros that initialize class properties.
The macro takes a "klass" parameter and token pastes it to generate the
class specific property manipulation function call.  Using these macros
means anytime a class changes due to a change in the mof file there is
only one place where you need to change the code.  These macros are a good
example of what logically belongs in the XXX.h file but are separated
out into a different .h file because konkret will nuke anything you've
added to a XXX.h file.


### Modifications to the provider ###

During development if the mof file changes you have to make Pegasus reload
the mof.  It's not sufficient to retart cimserver, you have to unregister
the provider and register it again for Pegasus to see the mof changes.
Thus you would use the openlmi-mof-register command above except pass
the unregister option, followed by the above command, e.g.

    % openlmi-mof-register unregister \
        /usr/share/openlmi-providers/LMI_Realmd.mof \
        /usr/share/openlmi-providers/LMI_Realmd.reg
    % openlmi-mof-register register \
        /usr/share/openlmi-providers/LMI_Realmd.mof \
        /usr/share/openlmi-providers/LMI_Realmd.reg

If all you've done during devopment is modify the provider (not it's
mof definition) then all you need to do is:

    % sudo cimserver -s
    % sudo make install
    % sudo cimserver


### How do I run the Pegasus CIMOM so I can see debug statements? ###

    % sudo cimserver daemon=false forceProviderProcesses=false


### How do I use GDB to debug my provider ###

Create the following .gdbinit file where `XXX` is where you want to break.

    set breakpoint pending on
    b XXX
    r daemon=false forceProviderProcesses=false

then run gdb like this:

    % sudo gdb cimserver


### How do I trace what Pegasus is doing? ###

    % cimserver daemon=false forceProviderProcesses=false \
        logLevel=TRACE traceLevel=5 traceFacility=File \
        traceComponents=All

The trace is written to file

    /var/lib/Pegasus/cache/trace/cimserver.trc

More information about cimserver tracing can be found in the "OpenPegasus
Tracing User Guide" PDF.  Google the title to get a current URL.


Provider-specific Instructions
------------------------------

### PCP ###

Please note the PCP provider needs a different registration procedure
since the PCP metrics classes are being generated automatically
according to the PCP namespace.  There is a helper script provided in
the openlmi-pcp package that generates the MOF and REG files according
to the installed PCP components and registers the appropriate classes
within the CIMOM.  The script requires the pcmd daemon to be running.

    % openlmi-pcp-generate

The openlmi-pcp package also installs a daily cronjob that runs the
script automatically to ensure any changes made to the PCP namespace
would be reflected in the system's CIM model.
