Skip to content

Commit

Permalink
Merge branch 'master' into andy/issue587-check-url-target
Browse files Browse the repository at this point in the history
  • Loading branch information
andy-maier committed Dec 11, 2016
2 parents db3246e + 92ac80e commit 80fcde3
Show file tree
Hide file tree
Showing 11 changed files with 3,201 additions and 2,783 deletions.
18 changes: 18 additions & 0 deletions docs/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ pywbem v0.10.0.dev0

Released: Not yet

Incompatible changes
^^^^^^^^^^^^^^^^^^^^

* All methods of the WBEMSubscriptionManager class that returned instance
paths (or lists thereof) in pywbem v0.9 now return the complete instances
(or lists thereof).

Deprecations
^^^^^^^^^^^^

Expand Down Expand Up @@ -58,12 +65,23 @@ Enhancements
as a context manager, whose exit method automatically cleans up by calling
`remove_all_servers()`.

* Added the global functions to the RTD documentation that are available in
the wbemcli interactive shell.

* Added CIM Schema archive to the repository, in order to avoid repeated
downloads during testing in the CI systems.

* Added methods to the operation recorder (class `BaseOperationRecorder`) for
disabling and enabling it. (issue #493).

* The Name property of indication filters created via the
WBEMSubscriptionManager class can now be controlled by the user.

* Indication filter, listener destination and indication subscription
instances created via the WBEMSubscriptionManager class, that are "owned",
are now conditionally created, dependent on the owned instances that have
been discovered upon restart of the WBEMSubscriptionManager.

Bug fixes
^^^^^^^^^

Expand Down
223 changes: 223 additions & 0 deletions docs/notebooks/subscriptionmanager.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Subscription Manager"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<a href=\"#\" onclick=\"history.back()\">&lt;--- Back</a>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The [`WBEMSubscriptionManager`](https://pywbem.readthedocs.io/en/latest/indication.html#pywbem.WBEMSubscriptionManager) class is a subscription manager that provides for creating and removing indication subscriptions, indication filters and listener destinations for multiple WBEM servers and multiple WBEM listeners and for getting information about existing indication subscriptions.\n",
"\n",
"A WBEM listener that is used with this subscription manager is identified through its URL, so it may be the WBEM listener provided by pywbem (see class [`WBEMListener`](https://pywbem.readthedocs.io/en/latest/indication.html#pywbem.WBEMListener)) or any external WBEM listener.\n",
"\n",
"This tutorial presents a full blown example on how to set up and shut down a subscription manager and some filters, listener destinations and subscription, including error handling. The code sections shown below are meant to be concatenated into one script."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The following code fragment creates a [`WBEMConnection`](https://pywbem.readthedocs.io/en/latest/client.html#pywbem.WBEMConnection) object for connecting to the WBEM server that is the target for the subscriptions, i.e. the server that lateron will emit the indications. It also creates a [`WBEMServer`](https://pywbem.readthedocs.io/en/latest/server.html#pywbem.WBEMServer) object based on that connection, that will be added to the subscription manager lateron.\n",
"\n",
"The code also defines the URL of a WBEM listener that will be the receiver of the indications. The WBEM listener is not subject of this tutorial, so we assume it just exists, for the purpose of this tutorial:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from __future__ import print_function\n",
"import pywbem\n",
"\n",
"# The WBEM server that should emit the indications\n",
"server = 'http://myserver'\n",
"username = 'user'\n",
"password = 'password'\n",
"\n",
"# The URL of the WBEM listener\n",
"listener_url = 'http://mylistener'\n",
"\n",
"conn = pywbem.WBEMConnection(server, (username, password),\n",
" no_verification=True)\n",
"server = pywbem.WBEMServer(conn)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next, we create the subscription manager, and add the WBEM server to it.\n",
"\n",
"This causes interaction to happen with the WBEM server: The [`add_server()`](https://pywbem.readthedocs.io/en/latest/indication.html#pywbem.WBEMSubscriptionManager.add_server) method determines whether the WBEM server has any listener destinations, indication filters, or subscriptions that are owned by this subscription manager. This is determined based upon the subscription manager ID ('fred' in this example). Such instances could exist for example if this script was used before and has been aborted or failed. Because of the interaction with the WBEM server, exceptions could be raised.\n",
"\n",
"In this tutorial, we use a try-block to show where exceptions can happen, but we just re-raise them without doing any recovery."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"sub_mgr = pywbem.WBEMSubscriptionManager(subscription_manager_id='fred')\n",
"\n",
"try:\n",
" server_id = sub_mgr.add_server(server)\n",
"except pywbem.Error as exc:\n",
" raise"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, we want to create a listener destination for our WBEM listener. We use \"owned\" listener destinations in order to benefit from the automatic recovery, conditional creation, and cleanup of owned instances (see [section WBEMSubscriptionManager](https://pywbem.readthedocs.io/en/latest/indication.html#wbemsubscriptionmanager) for details about owned instances).\n",
"\n",
"Because the subscription manager has discovered instances owned by it already, the [`add_listener_destinations()`](https://pywbem.readthedocs.io/en/latest/indication.html#pywbem.WBEMSubscriptionManager.add_listener_destinations) method creates a listener destination instance only if it does not exist yet. That makes our code easy, because we don't have to care about that. However, because the method possibly needs to create an instance in the WBEM server, we again need to be prepared for exceptions:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"try:\n",
" dest_inst = sub_mgr.add_listener_destinations(server_id, listener_url, owned=True)\n",
"except pywbem.Error as exc:\n",
" raise"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In this tutorial, we create a dynamic filter. We could have used a static (pre-existing) filter as well, of course.\n",
"\n",
"Suppose, the management profile we implement requires us to use a specific filter name, so we need to create a \"permanent\" filter (an \"owned\" filter requires that the subscription manager has control over the filter name).\n",
"\n",
"We further assume for the sake of simplicity of this tutorial, that the subscription is active only as long as the script runs, and that we tear everything down at the end of the script. Because the filter is permanent, we don't get the benefit of the automatic cleanup for owned filters, so we need to clean up the filter explicitly. Again, in order not to overload this tutorial, we do this in a straight forward flow without protecting ourselves againt exceptions. In a more real life example, you could for example protect the flow with a try-block and clean up in its `finally` clause.\n",
"\n",
"The next piece of code creates a permanent filter:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"filter_source_ns = \"root/cimv2\"\n",
"filter_query = \"SELECT * FROM CIM_AlertIndication \" \\\n",
" \"WHERE OwningEntity = 'DMTF' \" \\\n",
" \"AND MessageID LIKE 'SVPC0123|SVPC0124|SVPC0125'\"\n",
"filter_language = \"DMTF:CQL\"\n",
"filter_name = \"DMTF:System Virtualization:Alerts\"\n",
"\n",
"try:\n",
" filter_inst = sub_mgr.add_filter(server_id, filter_source_ns, filter_query,\n",
" filter_language, owned=False, name=filter_name)\n",
"except pywbem.Error as exc:\n",
" raise"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We now have a filter and a listener destination at hand. We can now activate the emission of indications defined by the filter to the WBEM listener defined by the listener destination, by creating an indication subscription.\n",
"\n",
"The subscription is between an owned destination and a permanent filter, so it will automatically become owned. This allows the subscription manager to deal with its lifecycle automatically when attempting to clean up the underlying owned filter."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"try:\n",
" sub_inst = sub_mgr.add_subscriptions(server_id, filter_inst.path, dest_inst.path)\n",
"except pywbem.Error as exc:\n",
" raise"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Once we want to stop the indication sending, we need to remove any permanent instances explicitly, and can leave the cleanup of owned instances to the subscription manager.\n",
"\n",
"However, because subscriptions must be removed before their underlying filters or destinations, we need to remove the owned subscription explicitly as well, then the filter, then we can leave the rest (the destination) to the subscription manager cleanup that happens when we remove the server:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"try:\n",
" sub_mgr.remove_subscriptions(server_id, sub_inst.path)\n",
" sub_mgr.remove_filter(server_id, filter_inst.path)\n",
" sub_mgr.remove_server(server_id) # will automatically remove the owned destination\n",
"except pywbem.Error as exc:\n",
" raise"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<a href=\"#\" onclick=\"history.back()\">&lt;--- Back</a>"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.5"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
3 changes: 2 additions & 1 deletion docs/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This section contains a few short tutorials about using pywbem. It is intended
to be enough to get people up and going who already know a bit about WBEM and
CIM.

The tutorials in this section are
The tutorials in this section are
`Jupyter Notebooks <http://jupyter-notebook-beginner-guide.readthedocs.io/>`_,
and are shown using the online
`Jupyter Notebook Viewer <http://nbviewer.jupyter.org/>`_.
Expand All @@ -28,6 +28,7 @@ Tutorial Short description
:nbview:`createdeleteinst.ipynb` CreateInstance + DeleteInstance
:nbview:`modifyinstance.ipynb` ModifyInstance
:nbview:`invokemethod.ipynb` InvokeMethod
:nbview:`subscriptionmanager.ipynb` Subscription Manager
================================== ===========================================

For the following topics, tutorials are not yet available:
Expand Down
11 changes: 11 additions & 0 deletions docs/utilities.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ The MOF compiler has a pluggable interface for the CIM repository. The default
implementation of that interface uses a WBEM server as its repository.
The plug interface is also described in the :ref:`MOF compiler API`.

Usage
^^^^^

Here is the help text of the command:

.. include:: mof_compiler.help.txt
Expand All @@ -53,8 +56,16 @@ implemented as an interactive shell.
The WBEM client CLI does not have an external API on its own; it is for the
most part a consumer of the :ref:`WBEM client library API`.

Usage
^^^^^

Here is the help text of the command:

.. include:: wbemcli.help.txt
:literal:

Global functions
^^^^^^^^^^^^^^^^

.. automodule:: wbemcli
:members:
14 changes: 8 additions & 6 deletions examples/pegasusindicationtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,10 @@ def run_test(svr_url, listener_host, user, password, http_listener_port, \
old_subs = sub_mgr.get_all_subscriptions(server_id)
# TODO filter for our sub mgr
if len(old_subs) != 0 or len(old_filters) != 0:
sub_mgr.remove_subscriptions(server_id, old_subs)
sub_mgr.remove_subscriptions(server_id,
[inst.path for inst in old_subs])
for filter_ in old_filters:
sub_mgr.remove_filter(server_id, filter_)
sub_mgr.remove_filter(server_id, filter_.path)

except ConnectionError as ce:
print('Connection Error %s with %s' % (ce, svr_url))
Expand Down Expand Up @@ -227,11 +228,11 @@ def run_test(svr_url, listener_host, user, password, http_listener_port, \
sub_mgr.add_listener_destinations(server_id, listener_url)

# Create a dynamic alert indication filter and subscribe for it
filter_path = sub_mgr.add_filter(
filter_ = sub_mgr.add_filter(
server_id, TEST_CLASS_NAMESPACE,
TEST_QUERY,
query_language="DMTF:CQL")
subscription_paths = sub_mgr.add_subscriptions(server_id, filter_path)
subscriptions = sub_mgr.add_subscriptions(server_id, filter_.path)

# Request server to create indications by invoking method
# This is pegasus specific
Expand Down Expand Up @@ -259,8 +260,9 @@ def run_test(svr_url, listener_host, user, password, http_listener_port, \
time.sleep(requested_indications/150)


sub_mgr.remove_subscriptions(server_id, subscription_paths)
sub_mgr.remove_filter(server_id, filter_path)
sub_mgr.remove_subscriptions(server_id,
[inst.path for inst in subscriptions])
sub_mgr.remove_filter(server_id, filter_.path)
sub_mgr.remove_server(server_id)
LISTENER.stop()

Expand Down
2 changes: 2 additions & 0 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ doc_dependent_files := \
$(package_name)/_recorder.py \
$(package_name)/_server.py \
$(package_name)/config.py \
wbemcli.py \

# PyLint config file
pylint_rc_file := pylintrc
Expand All @@ -105,6 +106,7 @@ py_src_files := \
$(filter-out $(moftab_files), $(wildcard $(package_name)/*.py)) \
$(wildcard testsuite/*.py) \
wbemcli \
wbemcli.py \
mof_compiler \

# Test log
Expand Down
Loading

0 comments on commit 80fcde3

Please sign in to comment.