Indications
===========
Indication is a reaction to some specific event that occurs in response to a
particular change in data. LMIShell can perform an indication subscription, by
which we can receive such event responses.



Indication handler
------------------
The first step is to set up an indication handler. This is a routine that will
be triggered when the OpenLMI sends us an indication for which we have
registered (see below). It is important to set up the handler first so that we
can generate a unique registration name and avoid conflicts with other clients
that may wish to register for the same indication. The indication handler may
be part of the same process that will initiate the provider registration or it
may be an independent script, but the unique registration name must be
acquired first in either case.

The following example describes creating a handler and a listener for an
indication:

.. code-block:: python

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

The first argument of the handler is an :py:class:`LMIIndication` object,
which contains the list of methods and objects exported by the indication.
The other arguments are handler-specific; Any number of arguments may be
specified as necessary; those arguments must then be provided to the
:py:meth:`.LMIIndicationListener.add_handler` method of the listener. In the
above example, the string used in the
:py:meth:`.LMIIndicationListener.add_handler` call is specified with eight
**"X"** characters. Those characters will be replaced by unique string, which
is generated by the listeners to avoid a handler name clash. Use of this
uniqueness capability is not mandatory but is highly recommended. The
substituted name is returned as the result of the
:py:meth:`.LMIIndicationListener.add_handler` method so it can be used later.

The :py:class:`LMIIndicationListener` constructor takes up to four
arguments, two mandatory (hostname and port) and two optional when using SSL
(certfile and keyfile). It returns an :py:class:`LMIIndicationListener`
object.

The :py:meth:`.LMIIndicationListener.start` method creates a new thread and
runs an HTTP service in that thread, awaiting indications from the CIMOM. This
method will continue to run until :py:meth:`.LMIIndicationListener.stop` is
called or the current application exits.



Subscribing to an indication
----------------------------
The LMIShell is capable of creating an indication subscription with the filter and
handler objects in one single step. This example is based upon `sblim-cmpi-base`
provider.

How to subscribe to an indication, please, follow the next example:

.. code-block:: python

    > c = connect("host", "privileged_user", "password")
    > c.subscribe_indication(
    ...    QueryLanguage="WQL",
    ...    Query='SELECT * FROM CIM_InstModification',
    ...    Name=unique_name,
    ...    CreationNamespace="root/interop",
    ...    SubscriptionCreationClassName="CIM_IndicationSubscription",
    ...    FilterCreationClassName="CIM_IndicationFilter",
    ...    FilterSystemCreationClassName="CIM_ComputerSystem",
    ...    FilterSourceNamespace="root/cimv2",
    ...    HandlerCreationClassName="CIM_IndicationHandlerCIMXML",
    ...    HandlerSystemCreationClassName="CIM_ComputerSystem",
    ...    # destination computer, where the indications will be delivered
    ...    Destination="http://192.168.122.1:%d" % listening_port
    ...  )
    LMIReturnValue(rval=True, rparams={}, errorstr="")
    >

The previous code can be simplified by omitting some optional parameters:

* *QueryLanguage*: *DMTF:CQL*
* *CreationNamespace*: *root/interop*
* *SubscriptionCreationClassName*: *CIM_IndicationSubscription*
* *FilterCreationClassName*: *CIM_IndicationFilter*
* *FilterSystemCreationClassName*: *CIM_ComputerSystem*
* *FilterSourceNamespace*: *root/cimv2*
* *HandlerCreationClassName*: *CIM_IndicationHandlerCIMXML*
* *HandlerSystemCreationClassName*: *CIM_ComputerSystem*

Simplified subscription:

.. code-block:: python

   > c = connect("host", "privileged_user", "password")
   > c.subscribe_indication(
   ...    Name=unique_name,
   ...    Query='SELECT * FROM CIM_InstModification',
   ...    Destination="http://192.168.122.1:5988"
   ...  )
   LMIReturnValue(rval=True, rparams={}, errorstr="")
   >

**NOTE:** Make sure, that you are logged-in with an account, which has write
privileges in the *root/interop* namespace.

In this state, we have a indication subscription created.

Auto-delete subscriptions
^^^^^^^^^^^^^^^^^^^^^^^^^
By default all subscriptions created by LMIShell will be **auto-deleted**, when
the shell quits. To change this behavior, you can pass :samp:`Permanent=True`
keyword parameter to :py:meth:`.LMIConnection.subscribe_indication` call, which
will prevent LMIShell from deleting the subscription.

Listing subscribed indications
------------------------------
To list all the subscribed indications, run following code:

.. code-block:: python

    > c.print_subscribed_indications()
    ...
    > subscribed_ind_lst = c.subscribed_indications()
    >

Unsubscribing from an indication
---------------------------------
By default, the subscriptions created by the shell are auto-deleted, when the
shell quits.

If you want to delete the subscriptions sooner, you can use the following methods:

To unsubscribe from a specific indication:

.. code-block:: python

    > c.unsubscribe_indication(unique_name)
    LMIReturnValue(rval=True, rparams={}, errorstr="")

Or to unsubscribe from all indications:

.. code-block:: python

    > c.unsubscribe_all_indications()
    >
