Skip to content

Commit

Permalink
This pr implements all of the DMTF defined pull operations except for
Browse files Browse the repository at this point in the history
EnumerationCount which will NOT be implemented because it has been
deprecated.

These operations are implemented consistent with the DMTF specifications
and with the APSs approximately the same as DSP0200.  The major
difference is that we carry the namespace from operation internally
within the context that must be passed between operations since it
is a constant once the open has been executed. All of the
pull operations defined in DSP0200 are implemented except for
EnumerationContext.  We will not implement that request because it
is being deprecated by DMTF as of no value.

The api documentation for all of these operations is up-to-date and
has passed multiple reviews.

Implements the result of all of the pull operations as a named tuple
with three parts, instances/paths, end_of_sequence, enumeration_context.
The OpenQueryInstances has 4 parts to account for the ResultClass parameter.

Adds INSTANCEPATH as IRETURNVALUE child in tupleparse.py as they
are used by the pull operations xml.

The live test (run_cim_operations.py) has been extended to run tests
on all of the pull operations. Today this tests largely the main
paths and the core parameters on all of the operations.

We are missing tests for a lot of edge cases and for the extra paramters
on associators, references, etc.

These tests have been successfully run against openpegasus with
run_cimoperations.py.

API documentation is complete.  Tests exist for all pull functions as part
of run_cimoperations.py and they have been tested against
OpenPegasus.

This pr does NOT include changes to wbemcli for these new operations.

test_client.py was extended to process the results of the pull operations
since there is a key difference between the operation and the others in
that these return a tuple of results (objects, paramvalues) rather than
just objecs. We added a new response type that processes the tuple results.

There is one mock testcase for openEnumerateInstances.

Note added to changes.rst about this pr and the new methods.

Adds a single example of a pull enumerate instances session. This example
uses the pull to enumerate instances, display information on each operation
and display the resulting list of instances

Last version of pr fixes pull operations per comments including:

1. Modified pull result to globals for namedtuples.
2. Remove commented code.
3. Simplify pull result code so it is now a single statement
4. Modified run_cimoperations.py to clean up tests and fix some errors in
tests. There is still one test that takes a long time because it
runs against a whole namespace.
  • Loading branch information
KSchopmeyer committed Jun 8, 2016
1 parent fc4e67a commit c35d540
Show file tree
Hide file tree
Showing 8 changed files with 3,312 additions and 178 deletions.
18 changes: 18 additions & 0 deletions docs/changes.rst
Expand Up @@ -155,6 +155,24 @@ Enhancements
Documentation indicated that iterable was allowed but was limited
to list. (issue #347)

* Implemented pull operations per DMTF specification DSP0200 and DSP0201.
This includes the following new client operations to execute enumeration
sequences:
- OpenEnumerateInstances
- OpenEnumerateInstancePaths
- OpenAssociatorInstances
- OpenAssociatorInstancePaths
- OpenReferenceInstances
- OpenReferenceInstancePaths
- OpenQueryInstances
- PullInstances
- PullInstancesWithPath
- PullInstancePaths
- CloseEnumeration
PyWBEM does NOT implement the EnumerationCount operation as it
is both deprecated and unusable. (Issue #9)


Bug fixes
^^^^^^^^^

Expand Down
3 changes: 3 additions & 0 deletions docs/intro.rst
Expand Up @@ -224,6 +224,9 @@ References
DSP0207
`DMTF DSP0207, WBEM URI Mapping, Version 1.0 <http://www.dmtf.org/standards/published_documents/DSP0207_1.0.pdf>`_

DSP0212
`DMTF DSP0212, Filter Query Language, Version 1.0.1 <http://www.dmtf.org/standards/published_documents/DSP0212_1.0.1.pdf>`_

DSP1033
`DMTF DSP1033, Profile Registration Profile, Version 1.1 <http://www.dmtf.org/standards/published_documents/DSP1033_1.1.pdf>`_

Expand Down
176 changes: 176 additions & 0 deletions examples/pullenuminstances.py
@@ -0,0 +1,176 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Example of using Pull Operations to retrieve instances from a
WBEM Server. This example allows either simplistic command line
input with a fixed number of parameters or defaults to internal
definitions if incorrect number of cmd line arguments are supplied.
It:
Creates a connection
Opens an enumeration session with OpenEnumerateInstances
Executes a pull loop until the result.eos =True
Displays overall statistics on the returns
It also displays the results of the open and each pull in detail
"""

from __future__ import print_function

import sys
import datetime
from pywbem import WBEMConnection, CIMError, Error

# Dfault connection attributes. Used if not all arguments are
# supplied on the command line.
USERNAME = 'blah'
PASSWORD = 'blah'
TEST_CLASS = 'CIM_ComputerSystem'
TEST_NAMESPACE = 'root/cimv2'
SERVER_URL = 'http://localhost'

class ElapsedTimer(object):
"""
Set up elapsed time timer. Calculates time between initiation
and access.
"""
def __init__(self):
""" Initiate the object with current time"""
self.start_time = datetime.datetime.now()

def reset(self):
""" Reset the start time for the timer"""
self.start_time = datetime.datetime.now()

def elapsed_ms(self):
""" Get the elapsed time in milliseconds. returns floating
point representation of elapsed time in seconds.
"""
dt = datetime.datetime.now() - self.start_time
return ((dt.days * 24 * 3600) + dt.seconds) * 1000 \
+ dt.microseconds / 1000.0

def elapsed_sec(self):
""" get the elapsed time in seconds. Returns floating
point representation of time in seconds
"""
return self.elapsed_ms() / 1000

def connect_server(server_url, creds, namespace):
"""
Connect to the server return the connection object.
This call should not generate any exceptions
"""
return WBEMConnection(server_url, creds,
default_namespace=namespace,
no_verification=True)

def execute_request(conn, classname, max_open, max_pull):
"""
Enumerate instances defined by the function's
classname argument using the OpenEnumerateInstances and
PullInstancesWithPath.
* classname - Classname for the enumeration.
* max_open - defines the maximum number of instances
for the server to return for the open
*max_pull defines the maximum number of instances for the
WBEM server to return for each pull operation.
Displays results of each open or pull operation including
size, return parameters, and time to execute.
Any exception exits the function.
"""
start = ElapsedTimer()
result = conn.OpenEnumerateInstances(classname,
MaxObjectCount=max_open)

print('open rtn eos=%s context=%s, count=%s time=%s ms' %
(result.eos, result.context, len(result.instances),
start.elapsed_ms()))

# save instances since we reuse result
insts = result.instances

# loop to make pull requests until end_of_sequence received.
pull_count = 0
while not result.eos:
pull_count += 1
op_start = ElapsedTimer()
result = conn.PullInstancesWithPath(result.context,
MaxObjectCount=max_pull)

insts.extend(result.instances)

print('pull rtn eos=%s context=%s, insts=%s time=%s ms' %
(result.eos, result.context, len(result.instances),
op_start.elapsed_ms()))


print('Result instance count=%s pull count=%s time=%.2f sec' % \
(len(insts), pull_count, start.elapsed_sec()))
return insts

def main():
"""
Get arguments and call the execution function
"""

# if less than required arguments, use the defaults
if len(sys.argv) < 8:
print("Usage: %s server_url username password namespace classname "
"max_open, max_pull" % sys.argv[0])
server_url = SERVER_URL
username = USERNAME
password = PASSWORD
namespace = TEST_NAMESPACE
classname = TEST_CLASS
max_open = 0
max_pull = 100
else:
server_url = sys.argv[1]
username = sys.argv[2]
password = sys.argv[3]
namespace = sys.argv[4]
classname = sys.argv[5]
max_open = sys.argv[6]
max_pull = sys.argv[7]

# create the credentials tuple for WBEMConnection
creds = (username, password)

print('Parameters: server_url=%s\n username=%s\n namespace=%s\n' \
' classname=%s\n max_open=%s,\n max_pull=%s' % \
(server_url, username, namespace, classname, max_open, max_pull))

# call method to connect to the server
conn = connect_server(server_url, creds, namespace)

#Call method to execute the enumeration sequence and return instances
try:
instances = execute_request(conn, classname, max_open, max_pull)

# print the resulting instances
for instance in instances:
print('\npath=%s\n%s' % (instance.path, instance.tomof()))

# handle any exception
except Error as err:
# If CIMError, display CIMError attributes
if isinstance(err, CIMError):
print('Operation Failed: CIMError: code=%s, Description=%s' % \
(err.status_code_name, err.status_description))
else:
print ("Operation failed: %s" % err)
sys.exit(1)

return 0

if __name__ == '__main__':
sys.exit(main())



0 comments on commit c35d540

Please sign in to comment.