7. Mock WBEM server support¶
7.1. Mock support overview¶
Pywbemcli has support for mocking a WBEM server with the general option
--mock-server/-m
. This allows executing pywbemcli against a mock
WBEM server that is automatically created in pywbemcli, rather than a real
WBEM server.
The --mock-server
option is mutually exclusive with the --server
and
--name
options, since each defines a WBEM server.
The automatically created mock WBEM server has a in-memory repository for CIM objects (qualifier declarations, classes, and instances) and supports CIM namespaces. The operations performed against the mock WBEM server cause that mock repository to be inspected or manipulated accordingly.
The mock repository can be loaded with CIM objects from files specified as
an argument to the --mock-server
option. Each use of the option specifies
one file path of such a file. The option may be used multiple times and each
specified file is processed sequentially, in the sequence of the options
on the command line.
The following types of files are supported for the --mock-server
option:
MOF files: If the file extension is
.mof
, the file is considered a MOF file. Pywbemcli compiles the MOF in the file and adds the resulting CIM objects into the mock repository.The MOF file may define CIM qualifier declarations, CIM classes and CIM instances.
At this point, these CIM objects can be added to only one CIM namespace in the repository of the mock WBEM server, namely the default namespace of the connection (see
--default-namespace
global option).If a CIM object already exists in the repository, it is updated accordingly.
Python files: If the file extension is
.py
, the file is considered a Python file. The file is executed using Python’sexec()
(i.e. with module namespace__builtin__
), and with the following Python global variables made available:CONN
(pywbem_mock.FakedWBEMConnection
): This object provides a connection to the mock WBEM server. The methods of this object can be used to create and modify CIM objects in the mock repository.SERVER
(pywbem.WBEMServer
): This object is layered on top of theCONN
object and provides access to higher level features of the mock WBEM server, such as getting the Interop namespace, adding namespaces, or building more complex objects for the mock repository.VERBOSE
(bool): A flag that contains the value of the boolean--verbose
general option of pywbemcli.
The Python script can for example create Python objects of type
CIMQualifierDeclaration
,CIMClass
andCIMInstance
for representing CIM objects, and add them to the mock repository via calls topywbem_mock.FakedWBEMConnection.add_cimobjects()
.The Python script can also extend the capabilities of the mock WBEM server by implementing callbacks via
pywbem_mock.method_callback_interface()
, for handling CIM method invocations against the mock WBEM server.
Pywbemcli logging (-l
or --log
general option) can be used together
with the mock support. Since the mock support does not use HTTP(S), only the
“api” component in the log configuration string will generate any log output.
7.2. Creating files for the mock repository¶
The following is an example MOF file (named tst_file.mof
) that defines some
CIM qualifier declarations, a single CIM class, and a single CIM instance of
that class:
# Define some qualifiers
Qualifier Description : string = null,
Scope(any),
Flavor(EnableOverride, ToSubclass, Translatable);
Qualifier In : boolean = true,
Scope(parameter),
Flavor(DisableOverride, ToSubclass);
Qualifier Key : boolean = false,
Scope(property, reference),
Flavor(DisableOverride, ToSubclass);
Qualifier Out : boolean = false,
Scope(parameter),
Flavor(DisableOverride, ToSubclass);
# Define a class
[Description ("Simple CIM Class")]
class CIM_Foo {
[Key, Description("This is a key property")]
string InstanceID;
[Description("This is a uint32 property")]
uint32 IntegerProp;
[Description("Method with one output parameter")]
uint32 TestMethod(
[In (false), Out, Description("Output parameter")]
string OutputParam;
);
};
# Define an instance of the class
instance of CIM_Foo as $foo1 {
InstanceID = "CIM_Foo1";
IntegerProp = 1;
};
The pywbemcli command to use this MOF file for loading into a mock WBEM server, and then to enumerate its CIM class names is:
$ pywbemcli --mock-server tst_file.mof class enumerate --names-only
CIM_Foo
The following is Python code (in a file tst_file.py
) that will add the same
CIM objects as in the MOF file to the mock repository using
add_cim_objects()
. If the --verbose
general option is set on the pywbemcli command line, the mock repository will
be displayed:
#!/usr/bin/env python
from pywbem import CIMQualifierDeclaration, CIMQualifier, CIMClass, \
CIMProperty, CIMMethod, CIMParameter, CIMInstance, CIMInstanceName, Uint32
def main():
# Global variables made available by pywbemcli
global CONN, VERBOSE
# Define some qualifier declarations
description_qd = CIMQualifierDeclaration(
'Description', type='string', value=None,
scopes=dict(ANY=True),
overridable=True, tosubclass=True, translatable=True)
in_qd = CIMQualifierDeclaration(
'In', type='boolean', value=True,
scopes=dict(PARAMETER=True),
overridable=False, tosubclass=True)
key_qd = CIMQualifierDeclaration(
'Key', type='boolean', value=False,
scopes=dict(PROPERTY=True, REFERENCE=True),
overridable=False, tosubclass=True)
out_qd = CIMQualifierDeclaration(
'Out', type='boolean', value=False,
scopes=dict(PARAMETER=True),
overridable=False, tosubclass=True)
# Define a class
foo_cl = CIMClass(
'CIM_Foo',
qualifiers=[
CIMQualifier('Description', 'Simple CIM Class'),
],
properties=[
CIMProperty(
'InstanceID', type='string', value=None,
qualifiers=[
CIMQualifier('Key', True),
CIMQualifier('Description', 'This is a key property'),
],
class_origin='CIM_Foo', propagated=False),
CIMProperty(
'IntegerProp', type='uint32', value=None,
qualifiers=[
CIMQualifier('Key', True),
CIMQualifier('Description', 'This is a uint32 property'),
],
class_origin='CIM_Foo', propagated=False),
],
methods=[
CIMMethod(
'TestMethod', return_type='uint32',
qualifiers=[
CIMQualifier('Description',
'Method with one output parameter'),
],
parameters=[
CIMParameter(
'OutputParam', type='string',
qualifiers=[
CIMQualifier('In', False),
CIMQualifier('Out', True),
CIMQualifier('Description', 'Output parameter'),
]),
],
class_origin='CIM_Foo', propagated=False),
]
)
# Define an instance of the class.
# Note: The mock repository does not add an instance path, so it must be
# prepared upfront.
foo1 = CIMInstance(
'CIM_Foo',
path=CIMInstanceName(
'CIM_Foo', keybindings=dict(InstanceID="CIM_Foo1")),
properties=[
CIMProperty('InstanceID', value="CIM_Foo1"),
CIMProperty('IntegerProp', value=Uint32(1)),
])
# Add the CIM objects to the mock repository
CONN.add_cimobjects([
description_qd, in_qd, key_qd, out_qd,
foo_cl,
foo1,
])
if VERBOSE:
CONN.display_repository()
if __name__ == '__builtin__':
main()
As you can see, adding CIM objects with a MOF file is more compact, but of course the Python script can contain logic, and it provides for implementing CIM method calls via callbacks.
It is possible to mix MOF files and Python scripts by specifying the
--mock-server
option multiple times.
The pywbemcli command to use this Python file for loading into a mock WBEM server, and then to enumerate its CIM class names is:
$ pywbemcli --mock-server tst_file.py class enumerate --names-only
CIM_Foo