• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pywbem / pywbemtools / test-2757

11 Jan 2026 09:04AM UTC coverage: 29.475% (-58.6%) from 88.026%
test-2757

Pull #1501

github

web-flow
Merge 4229b955d into f9b5e1682
Pull Request #1501: Fixed start program timeouts and other issues in listener tests; Enabled tests again

59 of 116 new or added lines in 3 files covered. (50.86%)

3924 existing lines in 32 files now uncovered.

1953 of 6626 relevant lines covered (29.47%)

0.59 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

35.52
/pywbemtools/pywbemcli/_cmd_instance.py
1
# (C) Copyright 2017 IBM Corp.
2
# (C) Copyright 2017 Inova Development Inc.
3
# All Rights Reserved
4
#
5
# Licensed under the Apache License, Version 2.0 (the "License");
6
# you may not use this file except in compliance with the License.
7
# You may obtain a copy of the License at
8
#
9
#    http://www.apache.org/licenses/LICENSE-2.0
10
#
11
# Unless required by applicable law or agreed to in writing, software
12
# distributed under the License is distributed on an "AS IS" BASIS,
13
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
# See the License for the specific language governing permissions and
15
# limitations under the License.
16
"""
2✔
17
Click Command definition for the instance command group which includes
18
cmds for get, enumerate, list of instance.
19

20
NOTE: Commands are ordered in help display by their order in this file.
21
"""
22

23

24
import click
2✔
25

26
from pywbem import CIMInstanceName, CIMClassName, Error, CIMError, \
2✔
27
    CIM_ERR_NOT_FOUND
28

29
from .pywbemcli import cli
2✔
30
from ._common import pick_instance, resolve_propertylist, create_ciminstance, \
2✔
31
    filter_namelist, verify_operation, process_invokemethod, \
32
    pywbem_error_exception, parse_kv_pair
33

34
from ._display_cimobjects import display_cim_objects
2✔
35

36
from ._common_options import propertylist_option, names_only_option, \
2✔
37
    include_classorigin_instance_option, namespace_option, summary_option, \
38
    verify_option, multiple_namespaces_option_dflt_all, \
39
    multiple_namespaces_option_dflt_conn, class_filter_options, \
40
    object_order_option
41

42
from ._cimvalueformatter import mof_escaped
2✔
43

44
from ._association_shrub import AssociationShrub
2✔
45

46
from .config import DEFAULT_QUERY_LANGUAGE
2✔
47
from ._common_cmd_functions import get_namespaces, enumerate_classes_filtered, \
2✔
48
    ResultsHandler
49
from .._click_extensions import PywbemtoolsGroup, PywbemtoolsCommand, \
2✔
50
    CMD_OPTS_TXT, GENERAL_OPTS_TXT, SUBCMD_HELP_TXT
51
from .._options import add_options, help_option, validate_required_arg
2✔
52
from .._output_formatting import validate_output_format, format_table, \
2✔
53
    warning_msg
54

55
#
56
#   Common option definitions for instance group
57
#
58

59
# NOTE: A number of the options use double-dash as the short form.  In those
60
# cases, a third definition of the options without the double-dash defines
61
# the corresponding option name, ex. 'include_qualifiers'. It should be
62
# defined with underscore and not dash
63

64
# This is instance-only because the default is False for include-qualifiers
65
# on instances but True on classes
66
include_qualifiers_get_option = [              # pylint: disable=invalid-name
2✔
67
    click.option('--iq', '--include-qualifiers', 'include_qualifiers',
68
                 is_flag=True, required=False,
69
                 help='Include qualifiers in the returned instance. '
70
                      'Not all servers return qualifiers on instances. '
71
                      'Default: Do not include qualifiers.')]
72

73
include_qualifiers_list_option = [              # pylint: disable=invalid-name
2✔
74
    click.option('--iq', '--include-qualifiers', 'include_qualifiers',
75
                 is_flag=True, required=False,
76
                 help='When traditional operations are used, include '
77
                      'qualifiers in the returned instances. '
78
                      'Some servers may ignore this option. '
79
                      'By default, and when pull operations are used, '
80
                      'qualifiers will never be included.')]
81

82
# specific to instance because DeepInheritance differs between class and
83
# instance operations.
84
deep_inheritance_enum_option = [              # pylint: disable=invalid-name
2✔
85
    click.option('--di', '--deep-inheritance', 'deep_inheritance',
86
                 is_flag=True, required=False,
87
                 help='Include subclass properties in the returned '
88
                      'instances. '
89
                      'Default: Do not include subclass properties.')]
90

91
local_only_get_option = [              # pylint: disable=invalid-name
2✔
92
    click.option('--lo', '--local-only', 'local_only', is_flag=True,
93
                 required=False,
94
                 help='Do not include superclass properties in the returned '
95
                      'instance. '
96
                      'Some servers may ignore this option. '
97
                      'Default: Include superclass properties.')]
98

99
local_only_list_option = [              # pylint: disable=invalid-name
2✔
100
    click.option('--lo', '--local-only', 'local_only', is_flag=True,
101
                 required=False,
102
                 help='When traditional operations are used, do not include '
103
                      'superclass properties in the returned instances. '
104
                      'Some servers may ignore this option. '
105
                      'By default, and when pull operations are used, '
106
                      'superclass properties will always be included.')]
107

108
property_create_option = [              # pylint: disable=invalid-name
2✔
109
    click.option('-p', '--property', type=str, metavar='PROPERTYNAME=VALUE',
110
                 required=False, multiple=True,
111
                 help='Initial property value for the new instance. '
112
                      'May be specified multiple times. '
113
                      'Array property values are specified as a '
114
                      'comma-separated list; embedded instances are not '
115
                      'supported. '
116
                      'Default: No initial properties provided.')]
117

118
property_modify_option = [              # pylint: disable=invalid-name
2✔
119
    click.option('-p', '--property', type=str, metavar='PROPERTYNAME=VALUE',
120
                 required=False, multiple=True,
121
                 help='Property to be modified, with its new value. '
122
                      'May be specified once for each property to be '
123
                      'modified. '
124
                      'Array property values are specified as a '
125
                      'comma-separated list; embedded instances are not '
126
                      'supported. '
127
                      'Default: No properties modified.')]
128

129
keybinding_key_option = [              # pylint: disable=invalid-name
2✔
130
    click.option('-k', '--key', type=str, metavar='KEYNAME=VALUE',
131
                 required=False, multiple=True,
132
                 help='Value for a key in keybinding of CIM instance name. '
133
                      'May be specified multiple times. '
134
                      'Allows defining keys without the issues of quotes. '
135
                      'Default: No keybindings provided.')]
136

137
filter_query_language_option = [              # pylint: disable=invalid-name
2✔
138
    click.option('--fql', '--filter-query-language', 'filter_query_language',
139
                 type=str, metavar='QUERY-LANGUAGE', default=None,
140
                 help='The filter query language to be used with '
141
                      '--filter-query. '
142
                      'Default: DMTF:FQL.')]
143

144
filter_query_option = [              # pylint: disable=invalid-name
2✔
145
    click.option('--fq', '--filter-query', 'filter_query', type=str,
146
                 metavar='QUERY-STRING', default=None,
147
                 help='When pull operations are used, filter the instances in '
148
                      'the result via a filter query. '
149
                      'By default, and when traditional operations are used, '
150
                      'no such filtering takes place.')]
151

152
help_instancename_option = [              # pylint: disable=invalid-name
2✔
153
    click.option('--hi', '--help-instancename', 'help_instancename',
154
                 is_flag=True, required=False, is_eager=True,
155
                 help='Show help message for specifying INSTANCENAME '
156
                      'including use of the --key and --namespace options.')]
157

158
show_null_option = [              # pylint: disable=invalid-name
2✔
159
    click.option('--show-null', 'show_null', is_flag=True, required=False,
160
                 help='In the TABLE output formats, show properties with no '
161
                      'value (i.e. Null) in all of the instances to be '
162
                      'displayed. Otherwise only properties at least '
163
                      'one instance has a non-Null property are displayed')]
164

165

166
##########################################################################
167
#
168
#   Click command group and command definitions
169
#   These decorated functions implement the commands, arguments, and
170
#
171
###########################################################################
172

173

174
@cli.group('instance', cls=PywbemtoolsGroup, options_metavar=GENERAL_OPTS_TXT,
2✔
175
           subcommand_metavar=SUBCMD_HELP_TXT)
176
@add_options(help_option)
2✔
177
def instance_group():
2✔
178
    """
179
    Command group for CIM instances.
180

181
    This command group defines commands to inspect instances, to invoke
182
    methods on instances, and to create and delete instances.
183

184
    Modification of instances is not currently supported.
185

186
    In addition to the command-specific options shown in this help text, the
187
    general options (see 'pywbemcli --help') can also be specified before the
188
    'instance' keyword.
189
    """
UNCOV
190
    pass  # pylint: disable=unnecessary-pass
×
191

192

193
@instance_group.command('enumerate', cls=PywbemtoolsCommand,
2✔
194
                        options_metavar=CMD_OPTS_TXT)
195
@click.argument('classname', type=str, metavar='CLASSNAME', required=True)
2✔
196
@add_options(local_only_list_option)
2✔
197
@add_options(deep_inheritance_enum_option)
2✔
198
@add_options(include_qualifiers_list_option)
2✔
199
@add_options(include_classorigin_instance_option)
2✔
200
@add_options(propertylist_option)
2✔
201
@add_options(multiple_namespaces_option_dflt_conn)
2✔
202
@add_options(names_only_option)
2✔
203
@add_options(summary_option)
2✔
204
@add_options(filter_query_option)
2✔
205
@add_options(filter_query_language_option)
2✔
206
@add_options(show_null_option)
2✔
207
@add_options(object_order_option)
2✔
208
@add_options(help_option)
2✔
209
@click.pass_obj
2✔
210
def instance_enumerate(context, classname, **options):
2✔
211
    """
212
    List the instances of a class.
213

214
    Enumerate the CIM instances of the specified class (CLASSNAME argument),
215
    including instances of subclasses in the specified CIM namespace(s)
216
    (--namespace option), and display the returned instances, or instance paths
217
    if --names-only was specified. If no namespace was specified, the default
218
    namespace of the connection is used.
219

220
    The instances to be retrieved can be filtered by the --filter-query option.
221

222
    The --local-only, --deep-inheritance, --include-qualifiers,
223
    --include-classorigin, and --propertylist options determine which parts
224
    are included in each retrieved instance.
225

226
    The --names-only option can be used to show only the instance paths.
227

228
    In the output, the instances and instance paths will be formatted as
229
    defined by the --output-format general option. Table formats on instances
230
    will be replaced with MOF format.
231
    """
UNCOV
232
    context.execute_cmd(
×
233
        lambda: cmd_instance_enumerate(context, classname, options))
234

235

236
@instance_group.command('get', cls=PywbemtoolsCommand,
2✔
237
                        options_metavar=CMD_OPTS_TXT)
238
@click.argument('instancename', type=str, metavar='INSTANCENAME',
2✔
239
                required=False)
240
@add_options(local_only_get_option)
2✔
241
@add_options(include_qualifiers_get_option)
2✔
242
@add_options(include_classorigin_instance_option)
2✔
243
@add_options(propertylist_option)
2✔
244
@add_options(keybinding_key_option)
2✔
245
@add_options(multiple_namespaces_option_dflt_conn)
2✔
246
@add_options(object_order_option)
2✔
247
@add_options(help_instancename_option)
2✔
248
@add_options(show_null_option)
2✔
249
@add_options(help_option)
2✔
250
@click.pass_obj
2✔
251
def instance_get(context, instancename, **options):
2✔
252
    """
253
    Get an instance of a class.
254

255
    For information on how to specify the instance using INSTANCENAME and the
256
    --key and --namespace options, invoke with --help-instancename.
257

258
    The --local-only, --include-qualifiers, --include-classorigin, and
259
    --propertylist options determine which parts are included in the retrieved
260
    instance.
261

262
    In the output, the instance will formatted as defined by the
263
    --output-format general option.
264
    """
UNCOV
265
    if options['help_instancename']:
×
UNCOV
266
        show_help_instancename()
×
UNCOV
267
        return
×
UNCOV
268
    validate_required_arg(instancename, 'INSTANCENAME')
×
UNCOV
269
    context.execute_cmd(
×
270
        lambda: cmd_instance_get(context, instancename, options))
271

272

273
@instance_group.command('delete', cls=PywbemtoolsCommand,
2✔
274
                        options_metavar=CMD_OPTS_TXT)
275
@click.argument('instancename', type=str, metavar='INSTANCENAME',
2✔
276
                required=False)
277
@add_options(keybinding_key_option)
2✔
278
@add_options(namespace_option)
2✔
279
@add_options(help_instancename_option)
2✔
280
@add_options(help_option)
2✔
281
@click.pass_obj
2✔
282
def instance_delete(context, instancename, **options):
2✔
283
    """
284
    Delete an instance of a class.
285

286
    WARNING: Deletion of instances will cause the removal of corresponding
287
    resources in the managed environment (i.e. in the real world). Some
288
    instances may not be deletable.
289

290
    For information on how to specify the instance using INSTANCENAME and the
291
    --key and --namespace options, invoke with --help-instancename.
292
    """
UNCOV
293
    if options['help_instancename']:
×
UNCOV
294
        show_help_instancename()
×
UNCOV
295
        return
×
UNCOV
296
    validate_required_arg(instancename, 'INSTANCENAME')
×
UNCOV
297
    context.execute_cmd(
×
298
        lambda: cmd_instance_delete(context, instancename, options))
299

300

301
@instance_group.command('create', cls=PywbemtoolsCommand,
2✔
302
                        options_metavar=CMD_OPTS_TXT)
303
@click.argument('classname', type=str, metavar='CLASSNAME', required=True)
2✔
304
@add_options(property_create_option)
2✔
305
@add_options(verify_option)
2✔
306
@add_options(namespace_option)
2✔
307
@add_options(help_option)
2✔
308
@click.pass_obj
2✔
309
def instance_create(context, classname, **options):
2✔
310
    """
311
    Create an instance of a class in a namespace.
312

313
    Create a CIM instance of the specified creation class (CLASSNAME
314
    argument) in the specified CIM namespace (--namespace option), with
315
    the specified properties (--property options) and display the CIM instance
316
    path of the created instance. If no namespace was specified, the default
317
    namespace of the connection is used.
318

319
    The properties to be initialized and their new values are specified using
320
    the --property option, which may be specified multiple times.
321

322
    Pywbemcli retrieves the class definition from the server in order to
323
    verify that the specified properties are consistent with the property
324
    characteristics in the class definition.
325

326
    Example:
327

328
      pywbemcli instance create CIM_blah -P id=3 -P arr="bla bla",foo
329
    """
UNCOV
330
    context.execute_cmd(
×
331
        lambda: cmd_instance_create(context, classname, options))
332

333

334
@instance_group.command('modify', cls=PywbemtoolsCommand,
2✔
335
                        options_metavar=CMD_OPTS_TXT)
336
@click.argument('instancename', type=str, metavar='INSTANCENAME',
2✔
337
                required=False)
338
@add_options(property_modify_option)
2✔
339
@click.option('--pl', '--propertylist', 'propertylist', multiple=True, type=str,
2✔
340
              default=None, required=False, metavar='PROPERTYLIST',
341
              help='Reduce the properties to be modified (as per '
342
              '--property) to a specific property list. '
343
              'Multiple properties may be specified with either a '
344
              'comma-separated list or by using the option multiple '
345
              'times. The empty string will cause no properties to '
346
              'be modified. '
347
              'Default: Do not reduce the properties to be modified.')
348
@add_options(verify_option)
2✔
349
@add_options(keybinding_key_option)
2✔
350
@add_options(namespace_option)
2✔
351
@add_options(help_instancename_option)
2✔
352
@add_options(help_option)
2✔
353
@click.pass_obj
2✔
354
def instance_modify(context, instancename, **options):
2✔
355
    """
356
    Modify properties of an instance.
357

358
    For information on how to specify the instance using INSTANCENAME and the
359
    --key and --namespace options, invoke with --help-instancename.
360

361
    The properties to be modified and their new values are specified using the
362
    --property option, which may be specified multiple times.
363

364
    The --propertylist option allows restricting the set of properties to be
365
    modified. Given that the set of properties to be modified is already
366
    determined by the specified --property options, it does not need to be
367
    specified.
368

369
    Example:
370

371
      pywbemcli instance modify CIM_blah.fred=3 -P id=3 -P arr="bla bla",foo
372
    """
UNCOV
373
    if options['help_instancename']:
×
UNCOV
374
        show_help_instancename()
×
UNCOV
375
        return
×
UNCOV
376
    validate_required_arg(instancename, 'INSTANCENAME')
×
UNCOV
377
    context.execute_cmd(
×
378
        lambda: cmd_instance_modify(context, instancename, options))
379

380

381
@instance_group.command('associators', cls=PywbemtoolsCommand,
2✔
382
                        options_metavar=CMD_OPTS_TXT)
383
@click.argument('instancename', type=str, metavar='INSTANCENAME',
2✔
384
                required=False)
385
@click.option('--ac', '--assoc-class', 'assoc_class', type=str, required=False,
2✔
386
              metavar='CLASSNAME',
387
              help='Filter the result set by association class name. '
388
                   'Subclasses of the specified class also match.')
389
@click.option('--rc', '--result-class', 'result_class', type=str,
2✔
390
              required=False, metavar='CLASSNAME',
391
              help='Filter the result set by result class name. '
392
                   'Subclasses of the specified class also match.')
393
@click.option('-r', '--role', type=str, required=False,
2✔
394
              metavar='PROPERTYNAME',
395
              help='Filter the result set by source end role name.')
396
@click.option('--rr', '--result-role', 'result_role', type=str, required=False,
2✔
397
              metavar='PROPERTYNAME',
398
              help='Filter the result set by far end role name.')
399
@add_options(include_qualifiers_list_option)
2✔
400
@add_options(include_classorigin_instance_option)
2✔
401
@add_options(propertylist_option)
2✔
402
@add_options(names_only_option)
2✔
403
@add_options(keybinding_key_option)
2✔
404
@add_options(multiple_namespaces_option_dflt_conn)
2✔
405
@add_options(summary_option)
2✔
406
@add_options(filter_query_option)
2✔
407
@add_options(filter_query_language_option)
2✔
408
@add_options(show_null_option)
2✔
409
@add_options(help_instancename_option)
2✔
410
@add_options(object_order_option)
2✔
411
@add_options(help_option)
2✔
412
@click.pass_obj
2✔
413
def instance_associators(context, instancename, **options):
2✔
414
    """
415
    List the instances associated with an instance.
416

417
    List the CIM instances that are associated with the specified CIM instance,
418
    and display the returned instances, or instance paths if --names-only was
419
    specified.
420

421
    For information on how to specify the instance using INSTANCENAME and the
422
    --key and --namespace options, invoke with --help-instancename.
423

424
    The instances to be retrieved can be filtered by the --filter-query,
425
    --role, --result-role, --assoc-class, and --result-class options.
426

427
    The --include-qualifiers, --include-classorigin, and --propertylist options
428
    determine which parts are included in each retrieved instance.
429

430
    The --names-only option can be used to show only the instance paths.
431

432
    In the output, the instances and instance paths will be formatted as
433
    defined by the --output-format general option. Table formats on instances
434
    will be replaced with MOF format.
435
    """
UNCOV
436
    if options['help_instancename']:
×
UNCOV
437
        show_help_instancename()
×
UNCOV
438
        return
×
UNCOV
439
    validate_required_arg(instancename, 'INSTANCENAME')
×
UNCOV
440
    context.execute_cmd(
×
441
        lambda: cmd_instance_associators(context, instancename, options))
442

443

444
@instance_group.command('references', cls=PywbemtoolsCommand,
2✔
445
                        options_metavar=CMD_OPTS_TXT)
446
@click.argument('instancename', type=str, metavar='INSTANCENAME',
2✔
447
                required=False)
448
@click.option('--rc', '--result-class', 'result_class', type=str,
2✔
449
              required=False, metavar='CLASSNAME',
450
              help='Filter the result set by result class name. '
451
                   'Subclasses of the specified class also match.')
452
@click.option('-r', '--role', type=str, required=False, metavar='PROPERTYNAME',
2✔
453
              help='Filter the result set by source end role name.')
454
@add_options(include_qualifiers_list_option)
2✔
455
@add_options(include_classorigin_instance_option)
2✔
456
@add_options(propertylist_option)
2✔
457
@add_options(names_only_option)
2✔
458
@add_options(keybinding_key_option)
2✔
459
@add_options(multiple_namespaces_option_dflt_conn)
2✔
460
@add_options(summary_option)
2✔
461
@add_options(filter_query_option)
2✔
462
@add_options(show_null_option)
2✔
463
@add_options(filter_query_language_option)
2✔
464
@add_options(help_instancename_option)
2✔
465
@add_options(object_order_option)
2✔
466
@add_options(help_option)
2✔
467
@click.pass_obj
2✔
468
def instance_references(context, instancename, **options):
2✔
469
    """
470
    List the instances referencing an instance.
471

472
    List the CIM (association) instances that reference the specified CIM
473
    instance, and display the returned instances, or instance paths if
474
    --names-only was specified.
475

476
    For information on how to specify the instance using INSTANCENAME and the
477
    --key and --namespace options, invoke with --help-instancename.
478

479
    The instances to be retrieved can be filtered by the --filter-query, --role
480
    and --result-class options.
481

482
    The --include-qualifiers, --include-classorigin, and --propertylist options
483
    determine which parts are included in each retrieved instance.
484

485
    The --names-only option can be used to show only the instance paths.
486

487
    In the output, the instances and instance paths will be formatted as
488
    defined by the --output-format general option. Table formats on instances
489
    will be replaced with MOF format.
490
    """
UNCOV
491
    if options['help_instancename']:
×
UNCOV
492
        show_help_instancename()
×
UNCOV
493
        return
×
UNCOV
494
    validate_required_arg(instancename, 'INSTANCENAME')
×
495
    # pylint: disable=line-too-long
UNCOV
496
    context.execute_cmd(lambda: cmd_instance_references(context, instancename, options))  # noqa: E501
×
497

498

499
@instance_group.command('invokemethod', cls=PywbemtoolsCommand,
2✔
500
                        options_metavar=CMD_OPTS_TXT)
501
@click.argument('instancename', type=str, metavar='INSTANCENAME',
2✔
502
                required=False)
503
@click.argument('methodname', type=str, metavar='METHODNAME', required=False)
2✔
504
@click.option('-p', '--parameter', type=str, metavar='PARAMETERNAME=VALUE',
2✔
505
              required=False, multiple=True,
506
              help='Specify a method input parameter with its value. '
507
                   'May be specified multiple times. '
508
                   'Array property values are specified as a comma-separated '
509
                   'list; embedded instances are not supported. '
510
                   'Default: No input parameters.')
511
@add_options(keybinding_key_option)
2✔
512
@add_options(namespace_option)
2✔
513
@add_options(help_instancename_option)
2✔
514
@add_options(help_option)
2✔
515
@click.pass_obj
2✔
516
def instance_invokemethod(context, instancename, methodname, **options):
2✔
517
    """
518
    Invoke a method on an instance.
519

520
    Invoke a CIM method (METHODNAME argument) on a CIM instance with the
521
    specified input parameters (--parameter options), and display the method
522
    return value and output parameters.
523

524
    For information on how to specify the instance using INSTANCENAME and the
525
    --key and --namespace options, invoke with --help-instancename.
526

527
    The method input parameters are specified using the --parameter option,
528
    which may be specified multiple times.
529

530
    Pywbemcli retrieves the class definition of the creation class of the
531
    instance from the server in order to verify that the specified input
532
    parameters are consistent with the parameter characteristics in the method
533
    definition.
534

535
    Use the 'class invokemethod' command to invoke CIM methods on CIM classes.
536

537
    Example:
538

539
      pywbemcli -n myconn instance invokemethod CIM_x.id='hi" methodx -p id=3
540
    """
UNCOV
541
    if options['help_instancename']:
×
UNCOV
542
        show_help_instancename()
×
UNCOV
543
        return
×
UNCOV
544
    validate_required_arg(instancename, 'INSTANCENAME')
×
UNCOV
545
    validate_required_arg(methodname, 'METHODNAME')
×
546
    # pylint: disable=line-too-long
UNCOV
547
    context.execute_cmd(lambda: cmd_instance_invokemethod(context, instancename, methodname, options))  # noqa: E501
×
548

549

550
@instance_group.command('query', cls=PywbemtoolsCommand,
2✔
551
                        options_metavar=CMD_OPTS_TXT)
552
@click.argument('query', type=str, required=True, metavar='QUERY-STRING')
2✔
553
@click.option('--ql', '--query-language', 'query_language', type=str,
2✔
554
              metavar='QUERY-LANGUAGE', default=DEFAULT_QUERY_LANGUAGE,
555
              help='The query language to be used with --query. '
556
              f'Default: {DEFAULT_QUERY_LANGUAGE}.')
557
@add_options(namespace_option)
2✔
558
@add_options(summary_option)
2✔
559
@add_options(help_option)
2✔
560
@click.pass_obj
2✔
561
def instance_query(context, query, **options):
2✔
562
    """
563
    Execute a query on instances in a namespace.
564

565
    Execute the specified query (QUERY_STRING argument) in the specified CIM
566
    namespace (--namespace option), and display the returned instances. If no
567
    namespace was specified, the default namespace of the connection is used.
568

569
    In the output, the instances will formatted as defined by the
570
    --output-format general option.
571
    """
UNCOV
572
    context.execute_cmd(lambda: cmd_instance_query(context, query, options))
×
573

574

575
@instance_group.command('count', cls=PywbemtoolsCommand,
2✔
576
                        options_metavar=CMD_OPTS_TXT)
577
@click.argument('classname', type=str, metavar='CLASSNAME-GLOB',
2✔
578
                required=False)
579
@add_options(multiple_namespaces_option_dflt_all)
2✔
580
@click.option('-s', '--sort', is_flag=True, required=False,
2✔
581
              help='Sort by instance count. Otherwise sorted by class name.')
582
@click.option('--ignore-class', type=str,
2✔
583
              multiple=True,
584
              metavar='CLASSNAME',
585
              help="Class names of classes to be ignored (not counted). "
586
                   "Allows counting instances in servers where instance "
587
                   "retrieval may cause a CIMError or Error exception "
588
                   "on some classes. CIM errors on particular "
589
                   "classes are ignored. Error exceptions cause scan to stop "
590
                   "and remaining classes status shown as 'not scanned'. "
591
                   "Multiple class names are allowed (one per option or "
592
                   "comma-separated).")
593
@add_options(class_filter_options)
2✔
594
@add_options(help_option)
2✔
595
@click.pass_obj
2✔
596
def instance_count(context, classname, **options):
2✔
597
    """
598
    Count the instances of each class with matching class name.
599

600
    Display the count of instances of each CIM class whose class name
601
    matches the specified wildcard expression (CLASSNAME-GLOB) in all CIM
602
    namespaces of the WBEM server, or in the specified namespaces
603
    (--namespace option).  This differs from instance enumerate, etc. in that
604
    it counts the instances specifically for the classname of each instance
605
    returned, not including subclasses.
606

607
    The CLASSNAME-GLOB argument is a wildcard expression that is matched on
608
    class names case insensitively.
609
    The special characters from Unix file name wildcarding are supported
610
    ('*' to match zero or more characters, '?' to match a single character,
611
    and '[]' to match character ranges). To avoid shell expansion of wildcard
612
    characters, the CLASSNAME-GLOB argument should be put in quotes.
613

614
    If CLASSNAME-GLOB is not specified, then all classes in the specified
615
    namespaces are counted (same as when specifying CLASSNAME-GLOB as "*").
616

617
    For example, "pywbem_*" returns classes whose name begins with "PyWBEM_",
618
    "pywbem_", etc. "*system*" returns classes whose names include the case
619
    insensitive string "system".
620

621
    If a CIMError occurs on any enumerate, it is flagged with a warning message
622
    and the search for instances continues.  If an Error exception occurs
623
    (ex. Connection error) the scan is terminated under the assumption
624
    that the server may have failed and the remaining items are shown as
625
    "Not scanned".
626

627
    This command can take a long time to execute since it potentially
628
    enumerates all instance names for all classes in all namespaces.
629
    """
UNCOV
630
    context.execute_cmd(lambda: cmd_instance_count(context, classname, options))
×
631

632

633
@instance_group.command('shrub', cls=PywbemtoolsCommand,
2✔
634
                        options_metavar=CMD_OPTS_TXT)
635
@click.argument('instancename', type=str, metavar='INSTANCENAME',
2✔
636
                required=False)
637
@click.option('--ac', '--assoc-class', 'assoc_class', type=str, required=False,
2✔
638
              metavar='CLASSNAME',
639
              help='Filter the result set by association class name. '
640
                   'Subclasses of the specified class also match.')
641
@click.option('--rc', '--result-class', 'result_class', type=str,
2✔
642
              required=False, metavar='CLASSNAME',
643
              help='Filter the result set by result class name. '
644
                   'Subclasses of the specified class also match.')
645
@click.option('-r', '--role', type=str, required=False,
2✔
646
              metavar='PROPERTYNAME',
647
              help='Filter the result set by source end role name.')
648
@click.option('--rr', '--result-role', 'result_role', type=str, required=False,
2✔
649
              metavar='PROPERTYNAME',
650
              help='Filter the result set by far end role name.')
651
@add_options(keybinding_key_option)
2✔
652
@add_options(namespace_option)
2✔
653
@add_options(summary_option)
2✔
654
@click.option('-f', '--fullpath', default=False, is_flag=True,
2✔
655
              help='Normally the instance paths in the tree views are '
656
                   'by hiding some keys with ~ to make the tree simpler '
657
                   'to read. This includes keys that have the same value '
658
                   'for all instances and the "CreationClassName" key.  When'
659
                   'this option is used the full instance paths are displayed.')
660
@add_options(help_instancename_option)
2✔
661
@add_options(help_option)
2✔
662
@click.pass_obj
2✔
663
def instance_shrub(context, instancename, **options):
2✔
664
    """
665
    Show the association shrub for INSTANCENAME.
666

667
    The shrub is a view of all of the instance association relationships for
668
    a defined INSTANCENAME showing the various components that are part of
669
    the association including Role, AssocClasse,ResultRole, And ResultClas
670

671
    The default view is a tree view from the INSTANCENAME to associated
672
    instances.
673

674
    Displays the shrub of association components for the association source
675
    instance defined by INSTANCENAME.
676

677
    For information on how to specify the instance using INSTANCENAME and the
678
    --key and --namespace options, invoke with --help-instancename.
679

680
    Normally the association information is displayed as a tree but it
681
    may also be displayed as a table or as one of the object formats (ex. MOF)
682
    of all instances that are part of the shrub if one of the cim object
683
    formats is selected with the global output_format parameter.
684

685
    Results are formatted as defined by the output format global option.
686
    """
UNCOV
687
    if options['help_instancename']:
×
UNCOV
688
        show_help_instancename()
×
UNCOV
689
        return
×
UNCOV
690
    validate_required_arg(instancename, 'INSTANCENAME')
×
691
    # pylint: disable=line-too-long
UNCOV
692
    context.execute_cmd(lambda: cmd_instance_shrub(context, instancename, options))  # noqa: E501
×
693

694

695
####################################################################
696
#
697
#  Common functions for cmd_instance processing
698
#
699
####################################################################
700

701
# Subject help used both in instance cmd group and in the help cmd
702

703
HELP_INSTANCENAME_MSG = """
2✔
704
An instance path is specified using the INSTANCENAME argument and optionally the
705
--key and --namespace options. It can be specified in three ways:
706

707
1. By specifying the instance path as an untyped WBEM URI in the INSTANCENAME
708
   argument. In this case, the keybindings of the instance are specified in the
709
   WBEM URI, and the --key option must not be used.
710

711
   String typed keybindings in WBEM URIs are using double quotes, so the
712
   processing of special characters by the shell (such as backslashes and
713
   quotes) needs to be considered.
714

715
   The CIM namespace of the instance can be specified in the WBEM URI, or using
716
   the --namespace option, or otherwise the default namespace of the connection
717
   will be used.
718

719
   If present, the scheme and host components in the WBEM URI will be ignored.
720

721
   Examples (for a shell such as 'bash'):
722

723
     cimv2/test:TST_Person.FirstName=\\"Albert\\",LastName=\\"Einstein\\"
724
     TST_Foo.ID=42 --namespace cimv2/test
725
     TST_Foo.ID=42                     # default namespace of connection is used
726
     TST_Foo.IntegerKey=42
727
     TST_Foo.BooleanKey=true
728
     TST_Foo.StringKey=\\"text\\"        # shell processes escapes
729
     'TST_Foo.StringKey="text"'        # shell processes outer squotes
730
     'TST_Foo.StringKey="42"'          # shell processes outer squotes
731
     'TST_Foo.StringKey="true"'        # shell processes outer squotes
732
     "TST_Foo.StringKey=\\"it's\\""      # shell proc. outer dquotes and escapes
733
     'TST_Foo.StringKey="1.75\\""'      # shell processes outer squotes
734
     'TST_Foo.StringKey="a b"'         # shell processes outer squotes
735
     'CIM_SubProfile.Main="CIM_RegisteredProfile.InstanceID=\\"acme.1\\"",
736
       Sub="CIM_RegisteredProfile.InstanceID=\\"acme.2\\""'
737

738
2. By specifying the class path of the creation class of the instance as an
739
   untyped WBEM URI in the INSTANCENAME argument and by using the --key option
740
   to specify the keybindings of the instance.
741

742
   This approach reduces the use of double quotes compared to the first
743
   approach and eliminates it for the most common cases, but the processing of
744
   special characters by the shell still needs to be considered.
745

746
   The --key option can be specified multiple times, once for each key of the
747
   instance name. The argument of the --key option has a NAME=VALUE format,
748
   where NAME is the name of the key property and VALUE is its value. The
749
   string/numeric/boolean type needed for creating a keybinding is determined
750
   automatically from VALUE. Valid integer numbers are interpreted as a numeric
751
   type, the strings "true" and "false" in any lexical case are interpreted as
752
   a boolean type, and anything else is interpreted as a string type. Starting
753
   and ending VALUE with double quotes forces interpretation as a string type;
754
   in that case double quotes and backslashes inside of the double quotes need
755
   to be backslash-escaped. This is useful for strings that have a numeric
756
   value, or the string values "true" or "false".
757

758
   The CIM namespace of the instance can be specified in the WBEM URI, or using
759
   the --namespace option, or otherwise the default namespace of the connection
760
   will be used.
761

762
   If present, the scheme and host components in the WBEM URI will be ignored.
763

764
   Examples (for a shell such as 'bash'):
765

766
     cimv2/test:TST_Person --key FirstName=Albert --key LastName=Einstein
767
     TST_Foo --namespace cimv2/test --key ID=42
768
     TST_Foo --key ID=42               # default namespace of connection is used
769
     TST_Foo --key IntegerKey=42
770
     TST_Foo --key BooleanKey=true
771
     TST_Foo --key StringKey=text
772
     TST_Foo --key StringKey=\\"42\\"    # shell processes escapes
773
     TST_Foo --key StringKey=\\"true\\"  # shell processes escapes
774
     TST_Foo --key "StringKey=it's"    # shell processes outer dquotes
775
     TST_Foo --key 'StringKey=1.75"'   # shell processes outer squotes
776
     TST_Foo --key "StringKey=a b"     # shell processes outer dquotes
777
     TST_Foo --key StringKey="a b"     # shell processes outer dquotes
778
     TST_Foo --key StringKey=a\\ b      # shell processes escapes
779
     CIM_SubProfile --key Main='CIM_RegisteredProfile.InstanceID="acme.1"'
780
       --key Sub='CIM_RegisteredProfile.InstanceID="acme.2"'
781

782
3. By specifying the class path of the creation class of the instance as an
783
   untyped WBEM URI in the INSTANCENAME argument, followed by a wildcard
784
   indicator ".?". In this case, the --key option must not be used. The
785
   instances of the specified class are displayed and the user is prompted for
786
   an index number to select an instance.
787

788
   The CIM namespace of the instance can be specified in the WBEM URI, or using
789
   the --namespace option, or otherwise the default namespace of the connection
790
   will be used.
791

792
   If present, the scheme and host components in the WBEM URI will be ignored.
793

794
   Example command:
795

796
     $ pywbemcli instance get cimv2/test:TST_Person.?
797
     Pick Instance name to process
798
     0: cimv2/test:TST_Person.FirstName="Albert",LastName="Einstein"
799
     1: cimv2/test:TST_Person.FirstName="Marie",LastName="Curie"
800
     Input integer between 0 and 1 or Ctrl-C to exit selection: _
801
"""
802

803

804
def show_help_instancename():
2✔
805
    """
806
    Show the help message on how to specify an instance using INSTANCENAME
807
    and the --key and --namespace options.
808
    """
809
    # Note: This help text has a fixed width since it is too complex to
810
    # dynamically render it to a given width.
811

UNCOV
812
    click.echo(HELP_INSTANCENAME_MSG)
×
813

814

815
def get_instancename(context, instancename, options, default_all_ns=False):
2✔
816
    """
817
    Common function to construct a CIMInstanceName object from the
818
    INSTANCENAME argument and the --key and --namespace options specified
819
    in the command line.
820

821
    The keybindings of the returned CIM instance path(s) must be specified in
822
    exactly one of these ways:
823

824
    * If the keybindings component in the instance name string is "?"
825
      (e.g. "CIM_Foo.?"), the instances of that class are listed and the user
826
      is prompted to pick instance name. If multiple namespaces are specified
827
      in the "--namespaces" option the instances in all requested namespaces
828
      are listed for the user to pick one.
829

830
    * If the "key" option is non-empty, the so specified key values are used as
831
      keybindings for the returned instance path, and the instancename string
832
      is interpreted as a class WBEM URI.
833

834
    * If the instance name string specifies keybindings, these keybindings
835
      are used to define the instance name to return.
836

837
    The namespace of the returned CIM instance path must be specified in
838
    exactly one of these ways:
839

840
    * If the instance name string specifies a namespace, it is used.
841

842
    * If the "--namespace" option is non-empty, it is used. If the "--namespace"
843
      option is a list, the request is to return instance names in any of the
844
      namespaces.
845

846
    * Otherwise, the default namespace of the connection in the context is used.
847

848
    Parameters:
849

850
      context (:class:`'~pywbemtools._context_obj.ContextObj`):
851
        The Click context object.
852

853
      instancename (:term:`string`):
854
        The INSTANCENAME argument from the command line.
855

856
      options (dict):
857
        Command-specific options from the command line (including "-key" and
858
        "--namespace" if specified).
859

860
      default_all_ns (:class:`py:bool`)
861
        If True, the default is to return all namespaces.  Otherwise the
862
        default is to return None.
863

864
    Returns:
865

866
      :class:`~pywbem.CIMInstanceName`: CIM instance path. It is never None.
867
      Namespace included in instance name ONLY if it is in the parameter
868
      instance name or multiple namespaces were specified with "--namespace".
869

870
    Raises:
871

872
      ClickException: Various reasons.
873
    """
UNCOV
874
    conn = context.pywbem_server.conn
×
875

UNCOV
876
    def validate_namespace_option(class_path):
×
877
        """Validate either namespace in instance or --namespace but not both"""
UNCOV
878
        if class_path.namespace:
×
UNCOV
879
            if options['namespace']:
×
UNCOV
880
                raise click.ClickException(
×
881
                    f"Using --namespace option: {options['namespace']} "
882
                    "conflicts with specifying namespace in "
883
                    f"INSTANCENAME: {instancename}")
884

885
    # If option is a tuple, expand option to get list of all namespaces
886
    # defined. Option may be multiple uses of the option and/or comma-separated
887
    # string for any option value
UNCOV
888
    if isinstance(options['namespace'], tuple):
×
UNCOV
889
        ns_names = get_namespaces(context, options['namespace'],
×
890
                                  default_all_ns=default_all_ns)
891
    else:
UNCOV
892
        ns_names = options['namespace']
×
893

894
    # Process the 3 exclusive cmd option (".?", --key option, instance name )
UNCOV
895
    if instancename.endswith(".?"):
×
UNCOV
896
        if options['key']:
×
UNCOV
897
            raise click.ClickException(
×
898
                "Using the --key option conflicts with specifying a "
899
                f"wildcard keybinding in INSTANCENAME: {instancename}")
900

UNCOV
901
        class_uri = instancename[:-2]
×
UNCOV
902
        try:
×
UNCOV
903
            class_path = CIMClassName.from_wbem_uri(class_uri)
×
UNCOV
904
        except ValueError as exc:
×
UNCOV
905
            raise click.ClickException(str(exc))
×
906

UNCOV
907
        validate_namespace_option(class_path)
×
908

UNCOV
909
        try:
×
910
            # User picks one instance.  returned instance path includes
911
            # namespace.
UNCOV
912
            instance_path = pick_instance(
×
913
                context, class_path.classname, ns_names)
914
            # Reset the namespace in instance name if multiple namespaces
UNCOV
915
            if instance_path:
×
UNCOV
916
                if ns_names:
×
UNCOV
917
                    instance_path.namespace = None
×
UNCOV
918
        except ValueError as exc:
×
919
            raise click.ClickException(str(exc))
×
920

921
    # if --key option exists.
UNCOV
922
    elif options['key']:
×
923
        # Transform the --key option values into WBEM URI keybinding strings
UNCOV
924
        kb_strs = []
×
UNCOV
925
        for kv in options['key']:
×
UNCOV
926
            key, value = parse_kv_pair(kv)
×
UNCOV
927
            if value is None:
×
UNCOV
928
                raise click.ClickException(
×
929
                    f"VALUE in --key option argument is missing: {kv}")
UNCOV
930
            try:
×
UNCOV
931
                int(value)
×
UNCOV
932
                is_int = True
×
UNCOV
933
            except (ValueError, TypeError):
×
UNCOV
934
                is_int = False
×
UNCOV
935
            if value is None:
×
936
                # There is no official NULL representation in WBEM URI
937
                kb_value = ''
×
UNCOV
938
            elif is_int:
×
939
                # integer - use without quotes
UNCOV
940
                kb_value = value
×
UNCOV
941
            elif value.upper() in ('TRUE', 'FALSE'):
×
942
                # boolean - use the upper cased string without quotes
UNCOV
943
                kb_value = value.upper()
×
UNCOV
944
            elif value.startswith('"') and value.endswith('"'):
×
945
                # string - the value between the double quotes is assumed to
946
                # already be backslash-escaped, at the minimum for double
947
                # quotes and backslashes.
UNCOV
948
                kb_value = value
×
949
            else:
950
                # string - double quotes and escaping is added
951
                # Note that a keybinding value in a WBEM URI only requires
952
                # the minimal escaping for MOF string literals, i.e. double
953
                # quotes and backslashes. However, we escape all control chars,
954
                # double quotes, and single quotes, to ensure that there are no
955
                # unprintable characters, and no quotes that might interfere
956
                # with the shell.
UNCOV
957
                kb_value = f'"{mof_escaped(value)}"'
×
958

UNCOV
959
            kb_strs.append(f"{key}={kb_value}")
×
960

961
        # We perform an extra verification that instance name was a class
962
        # path to get a more understandable error message if it is not,
963
        # compared to leaving that to CIMInstanceName.from_wbem_uri().
UNCOV
964
        try:
×
UNCOV
965
            CIMClassName.from_wbem_uri(instancename)
×
UNCOV
966
        except ValueError as exc:
×
UNCOV
967
            raise click.ClickException(str(exc))
×
968

UNCOV
969
        instancename_kb = f"{instancename}.{','.join(kb_strs)}"
×
970

UNCOV
971
        try:
×
UNCOV
972
            instance_path = CIMInstanceName.from_wbem_uri(instancename_kb)
×
UNCOV
973
            validate_namespace_option(instance_path)
×
UNCOV
974
        except ValueError as exc:
×
UNCOV
975
            raise click.ClickException(str(exc))
×
976

977
    else:  # else for not options['key']] or ".?", i.e. full key in inst path
UNCOV
978
        try:
×
UNCOV
979
            instance_path = CIMInstanceName.from_wbem_uri(instancename)
×
UNCOV
980
            validate_namespace_option(instance_path)
×
UNCOV
981
        except ValueError as exc:
×
UNCOV
982
            raise click.ClickException(str(exc))
×
983

UNCOV
984
    if instance_path is None:
×
UNCOV
985
        raise click.ClickException(
×
986
            f"No instance paths found for instancename {instancename}")
987

988
    # Set namespace into path if ns_names not set
UNCOV
989
    if not instance_path.namespace:
×
UNCOV
990
        if not ns_names:
×
UNCOV
991
            instance_path.namespace = options.get('namespace') or \
×
992
                conn.default_namespace
UNCOV
993
        if isinstance(ns_names, str):
×
UNCOV
994
            instance_path.namespace = ns_names
×
995

UNCOV
996
    return instance_path
×
997

998

999
####################################################################
1000
#
1001
#  cmd_instance_<action> processors
1002
#
1003
####################################################################
1004

1005

1006
def cmd_instance_get(context, instancename, options):
2✔
1007
    """
1008
    Get and display an instance of a CIM Class.
1009

1010
    Gets the instance defined by instancename argument in the namespaces defined
1011
    and displays in output format defined.  If multiple namespaces are defined
1012
    this method may get multiple instances.
1013

1014
    If the wildcard key is used (CLASSNAME.?), pywbemcli presents a list of
1015
    instances to the console from which one can be picked to get from the
1016
    server and display.
1017
    """
UNCOV
1018
    conn = context.pywbem_server.conn
×
UNCOV
1019
    output_fmt = validate_output_format(context.output_format, ['CIM', 'TABLE'])
×
1020

1021
    # Returns list of namespaces from namespace option
UNCOV
1022
    instancepath = get_instancename(context, instancename, options)
×
1023

UNCOV
1024
    property_list = resolve_propertylist(options['propertylist'])
×
1025

UNCOV
1026
    results = ResultsHandler(context, options, output_fmt, "instance",
×
1027
                             instancepath, instpath=instancepath,
1028
                             property_list=property_list)
1029

UNCOV
1030
    for ns in results:
×
UNCOV
1031
        try:
×
UNCOV
1032
            instancepath.namespace = ns
×
UNCOV
1033
            results.add(conn.GetInstance(
×
1034
                instancepath,
1035
                LocalOnly=options['local_only'],
1036
                IncludeQualifiers=options['include_qualifiers'],
1037
                IncludeClassOrigin=options['include_classorigin'],
1038
                PropertyList=property_list))
1039

UNCOV
1040
        except CIMError as ce:
×
1041
            # Process error and continue or generate exception
UNCOV
1042
            results.handle_exception(ns, ce)
×
UNCOV
1043
            continue
×
1044

UNCOV
1045
        except Error as er:
×
UNCOV
1046
            raise pywbem_error_exception(er)
×
1047

UNCOV
1048
    results.display()
×
1049

1050

1051
def cmd_instance_delete(context, instancename, options):
2✔
1052
    """
1053
        If option interactive is set, get instances of the class defined
1054
        by instance name and allow the user to select the instance to
1055
        delete. This method allows only a single namespace.
1056

1057
        Otherwise attempt to delete the instance defined by instancename
1058
    """
UNCOV
1059
    conn = context.pywbem_server.conn
×
1060

UNCOV
1061
    instancepath = get_instancename(context, instancename, options)
×
1062

UNCOV
1063
    try:
×
UNCOV
1064
        conn.DeleteInstance(instancepath)
×
1065

UNCOV
1066
        if context.verbose:
×
UNCOV
1067
            context.spinner_stop()
×
UNCOV
1068
            click.echo(f'Deleted instance {instancepath}')
×
1069

UNCOV
1070
    except Error as er:
×
UNCOV
1071
        raise pywbem_error_exception(er)
×
1072

1073

1074
def cmd_instance_create(context, classname, options):
2✔
1075
    """
1076
       Create an instance and submit to wbemserver.
1077
       If successful, this operation returns the new instance name. Otherwise
1078
       it raises an exception
1079
    """
UNCOV
1080
    conn = context.pywbem_server.conn
×
UNCOV
1081
    ns = options['namespace'] or conn.default_namespace
×
UNCOV
1082
    try:
×
UNCOV
1083
        class_ = conn.GetClass(
×
1084
            classname, namespace=ns, LocalOnly=False)
UNCOV
1085
    except CIMError as ce:
×
UNCOV
1086
        if ce.status_code == CIM_ERR_NOT_FOUND:
×
UNCOV
1087
            raise click.ClickException(
×
1088
                f'CIMClass: "{classname}" does not exist in '
1089
                f'namespace "{ns}" in WEB server: {conn}.')
UNCOV
1090
        raise pywbem_error_exception(ce)
×
1091

UNCOV
1092
    except Error as er:
×
UNCOV
1093
        raise pywbem_error_exception(er)
×
1094

UNCOV
1095
    properties = options['property']
×
1096

1097
    # properties is a tuple of name,value pairs
UNCOV
1098
    new_inst = create_ciminstance(class_, properties)
×
1099

UNCOV
1100
    if options['verify']:
×
UNCOV
1101
        context.spinner_stop()
×
UNCOV
1102
        click.echo(new_inst.tomof())
×
UNCOV
1103
        if not verify_operation("Execute CreateInstance", msg=True):
×
UNCOV
1104
            return
×
UNCOV
1105
    try:
×
UNCOV
1106
        name = conn.CreateInstance(new_inst, namespace=ns)
×
1107

UNCOV
1108
        context.spinner_stop()
×
UNCOV
1109
        click.echo(f'{name}')
×
1110
    except Error as er:
×
1111
        raise click.ClickException(
×
1112
            f'Server Error creating instance in namespace {ns}. Exception: '
1113
            f'{er.__class__.__name__}: {er}')
1114

1115

1116
def cmd_instance_modify(context, instancename, options):
2✔
1117
    """
1118
    Build an instance defined by the options and submit to wbemserver
1119
    as a ModifyInstance method.
1120

1121
    This method allows only a single namespace.
1122

1123
    In order to make a correct instance, this method first gets the
1124
    corresponding class and uses that as the template for creating the intance.
1125
    The class provides property names, types, array flags, etc. to assure
1126
    that the instance is correctly built.
1127

1128
    If successful, this operation returns nothing.
1129
    """
UNCOV
1130
    conn = context.pywbem_server.conn
×
UNCOV
1131
    instancepath = get_instancename(context, instancename, options)
×
1132

UNCOV
1133
    ns = options['namespace'] or conn.default_namespace
×
1134

UNCOV
1135
    try:
×
UNCOV
1136
        class_ = conn.GetClass(
×
1137
            instancepath.classname, namespace=ns, LocalOnly=False)
UNCOV
1138
    except CIMError as ce:
×
UNCOV
1139
        if ce.status_code == CIM_ERR_NOT_FOUND:
×
UNCOV
1140
            raise click.ClickException(
×
1141
                f'CIMClass: {instancepath.classname!r} does not exist in '
1142
                f'WEB server: {conn.url}')
1143

UNCOV
1144
        raise pywbem_error_exception(ce)
×
UNCOV
1145
    except Error as er:
×
UNCOV
1146
        raise pywbem_error_exception(er)
×
1147

UNCOV
1148
    property_list = resolve_propertylist(options['propertylist'])
×
1149

1150
    # properties is a tuple of name,value pairs
UNCOV
1151
    modified_inst = create_ciminstance(class_, options['property'])
×
1152

UNCOV
1153
    modified_inst.path = instancepath
×
1154

UNCOV
1155
    if options['verify']:
×
UNCOV
1156
        context.spinner_stop()
×
UNCOV
1157
        click.echo(modified_inst.tomof())
×
UNCOV
1158
        if not verify_operation("Execute ModifyInstance", msg=True):
×
UNCOV
1159
            return
×
1160

UNCOV
1161
    try:
×
UNCOV
1162
        conn.ModifyInstance(modified_inst, PropertyList=property_list)
×
UNCOV
1163
        if context.verbose:
×
UNCOV
1164
            context.spinner_stop()
×
UNCOV
1165
            click.echo(f'Modified instance {instancepath}')
×
UNCOV
1166
    except Error as er:
×
UNCOV
1167
        raise click.ClickException('Server Error modifying instance {} '
×
1168
                                   'in namespace {}. Exception: {}: {}'.format
1169
                                   (instancepath, ns, er.__class__.__name__,
1170
                                    er))
1171

1172

1173
def cmd_instance_invokemethod(context, instancename, methodname,
2✔
1174
                              options):
1175
    """
1176
    Create an instance and submit to wbemserver
1177
    """
UNCOV
1178
    instancepath = get_instancename(context, instancename, options)
×
1179

UNCOV
1180
    try:
×
UNCOV
1181
        process_invokemethod(context, instancepath, methodname,
×
1182
                             options['namespace'], options['parameter'])
UNCOV
1183
    except Error as er:
×
UNCOV
1184
        raise pywbem_error_exception(er)
×
1185

1186

1187
def get_filterquerylanguage(options):
2✔
1188
    """
1189
    Get the filterquery language based on what is in the filterquery option
1190
    and the filterquerylanguage options.
1191
    If filterquery exists but filterquerylanguage does not, use DMTF as
1192
    the filter query language.
1193
    if filterquery does not exist but filterquerylanguage does, just return it
1194
    """
UNCOV
1195
    if options['filter_query']:
×
UNCOV
1196
        fql = options['filter_query_language'] or 'DMTF:FQL'
×
1197
    else:
UNCOV
1198
        fql = options['filter_query_language']
×
UNCOV
1199
    return fql
×
1200

1201

1202
def enumerate_instances(conn, context, options, namespace, classname,
2✔
1203
                        property_list, return_original_err=False):
1204
    """
1205
    Internal method.
1206

1207
    Issue the command to enumerate either the paths or instances for the
1208
    namespace defined by the namespace parameter.
1209

1210
    If the return_original_err is True, reraise any  Error or CIMError
1211
    exception.
1212
    """
UNCOV
1213
    try:
×
UNCOV
1214
        if options['names_only']:
×
UNCOV
1215
            return conn.PyWbemcliEnumerateInstancePaths(
×
1216
                ClassName=classname,
1217
                namespace=namespace,
1218
                FilterQuery=options['filter_query'],
1219
                FilterQueryLanguage=get_filterquerylanguage(options),
1220
                MaxObjectCount=context.pywbem_server.pull_max_cnt)
1221

UNCOV
1222
        return conn.PyWbemcliEnumerateInstances(
×
1223
            ClassName=classname,
1224
            namespace=namespace,
1225
            LocalOnly=options['local_only'],
1226
            IncludeQualifiers=options['include_qualifiers'],
1227
            DeepInheritance=options['deep_inheritance'],
1228
            IncludeClassOrigin=options['include_classorigin'],
1229
            FilterQuery=options['filter_query'],
1230
            FilterQueryLanguage=get_filterquerylanguage(options),
1231
            MaxObjectCount=context.pywbem_server.pull_max_cnt,
1232
            PropertyList=property_list)
1233

UNCOV
1234
    except Error as er:
×
1235
        # Return either the original exception or the ClickException.
UNCOV
1236
        if return_original_err:
×
UNCOV
1237
            raise er
×
UNCOV
1238
        raise pywbem_error_exception(er)
×
1239

1240
    # Exception from Enumerate and the FilterQuery.  This exception would
1241
    # apply  to all namespaces so just terminate.
UNCOV
1242
    except ValueError as ve:
×
UNCOV
1243
        raise click.ClickException(
×
1244
            'Instance enumerate failed because FilterQuery not allowed with '
1245
            'traditional EnumerateInstance. '
1246
            f'--use-pull: {context.pywbem_server.use_pull}. '
1247
            f'Exception: {ve.__class__.__name__}: {ve}')
1248

1249

1250
def cmd_instance_enumerate(context, classname, options):
2✔
1251
    """
1252
    Enumerate CIM instances or CIM instance names
1253

1254
    Returns:
1255
        list of objects retrieved.
1256

1257
    """
UNCOV
1258
    conn = context.pywbem_server.conn
×
UNCOV
1259
    output_fmt = validate_output_format(context.output_format, ['CIM', 'TABLE'])
×
1260

UNCOV
1261
    property_list = resolve_propertylist(options['propertylist'])
×
1262

UNCOV
1263
    results = ResultsHandler(context, options, output_fmt, "class", classname,
×
1264
                             property_list=property_list)
1265

UNCOV
1266
    for ns in results:
×
UNCOV
1267
        try:
×
UNCOV
1268
            results.add(enumerate_instances(conn, context, options, ns,
×
1269
                                            classname, property_list,
1270
                                            return_original_err=True))
1271

UNCOV
1272
        except CIMError as ce:
×
1273
            # Process error and continue or generate exception
UNCOV
1274
            results.handle_exception(ns, ce)
×
UNCOV
1275
            continue
×
1276

UNCOV
1277
        except Error as er:
×
UNCOV
1278
            raise pywbem_error_exception(er)
×
1279

UNCOV
1280
    results.display()
×
1281

1282

1283
def cmd_instance_references(context, instancename, options):
2✔
1284
    """Execute the references request operation to get references for
1285
       the classname defined. This may be either interactive or if the
1286
       interactive option is set or use the instancename directly.
1287

1288
       This method allows multiple namespaces
1289

1290
       If the interactive option is selected, the instancename MUST BE
1291
       a classname.
1292
    """
UNCOV
1293
    conn = context.pywbem_server.conn
×
UNCOV
1294
    output_fmt = validate_output_format(context.output_format, ['CIM', 'TABLE'])
×
1295

UNCOV
1296
    instancepath = get_instancename(context, instancename, options)
×
1297

UNCOV
1298
    property_list = resolve_propertylist(options['propertylist'])
×
1299

UNCOV
1300
    results = ResultsHandler(context, options, output_fmt, "instance",
×
1301
                             instancepath, instpath=instancepath,
1302
                             property_list=property_list)
1303

UNCOV
1304
    for ns in results:
×
UNCOV
1305
        try:
×
UNCOV
1306
            instancepath.namespace = ns
×
UNCOV
1307
            if options['names_only']:
×
UNCOV
1308
                results.add(conn.PyWbemcliReferenceInstancePaths(
×
1309
                    instancepath,
1310
                    ResultClass=options['result_class'],
1311
                    Role=options['role'],
1312
                    FilterQuery=options['filter_query'],
1313
                    FilterQueryLanguage=get_filterquerylanguage(options),
1314
                    MaxObjectCount=context.pywbem_server.pull_max_cnt))
1315
            else:
UNCOV
1316
                results.add(conn.PyWbemcliReferenceInstances(
×
1317
                    instancepath,
1318
                    ResultClass=options['result_class'],
1319
                    Role=options['role'],
1320
                    IncludeQualifiers=options['include_qualifiers'],
1321
                    IncludeClassOrigin=options['include_classorigin'],
1322
                    FilterQuery=options['filter_query'],
1323
                    FilterQueryLanguage=get_filterquerylanguage(options),
1324
                    MaxObjectCount=context.pywbem_server.pull_max_cnt,
1325
                    PropertyList=property_list))
1326

UNCOV
1327
        except CIMError as ce:
×
1328
            # Process error and continue or generate exception
UNCOV
1329
            results.handle_exception(ns, ce)
×
UNCOV
1330
            continue
×
1331

UNCOV
1332
        except Error as er:
×
UNCOV
1333
            raise pywbem_error_exception(er)
×
1334

UNCOV
1335
        except ValueError as ve:
×
UNCOV
1336
            raise click.ClickException(
×
1337
                'Instance references failed because FilterQuery not allowed '
1338
                'with traditional References. '
1339
                f'--use-pull {context.pywbem_server.use_pull}. '
1340
                f'Exception: {ve.__class__.__name__}: {ve}')
UNCOV
1341
    results.display()
×
1342

1343

1344
def cmd_instance_associators(context, instancename, options):
2✔
1345
    """
1346
    Execute the references request operation to get references for
1347
    the classname defined.
1348

1349
    This method allows multiple namespaces.
1350
    """
UNCOV
1351
    conn = context.pywbem_server.conn
×
UNCOV
1352
    output_fmt = validate_output_format(context.output_format, ['CIM', 'TABLE'])
×
1353

UNCOV
1354
    instancepath = get_instancename(context, instancename, options)
×
1355

UNCOV
1356
    property_list = resolve_propertylist(options['propertylist'])
×
1357

UNCOV
1358
    results = ResultsHandler(context, options, output_fmt, "class",
×
1359
                             instancepath, instpath=instancepath,
1360
                             property_list=property_list)
1361

UNCOV
1362
    for ns in results:
×
UNCOV
1363
        try:
×
UNCOV
1364
            instancepath.namespace = ns
×
UNCOV
1365
            if options['names_only']:
×
UNCOV
1366
                results.add(conn.PyWbemcliAssociatorInstancePaths(
×
1367
                    instancepath,
1368
                    AssocClass=options['assoc_class'],
1369
                    Role=options['role'],
1370
                    ResultClass=options['result_class'],
1371
                    ResultRole=options['result_role'],
1372
                    FilterQuery=options['filter_query'],
1373
                    FilterQueryLanguage=get_filterquerylanguage(options),
1374
                    MaxObjectCount=context.pywbem_server.pull_max_cnt))
1375
            else:
UNCOV
1376
                results.add(conn.PyWbemcliAssociatorInstances(
×
1377
                    instancepath,
1378
                    AssocClass=options['assoc_class'],
1379
                    Role=options['role'],
1380
                    ResultClass=options['result_class'],
1381
                    ResultRole=options['result_role'],
1382
                    IncludeQualifiers=options['include_qualifiers'],
1383
                    IncludeClassOrigin=options['include_classorigin'],
1384
                    FilterQuery=options['filter_query'],
1385
                    FilterQueryLanguage=get_filterquerylanguage(options),
1386
                    MaxObjectCount=context.pywbem_server.pull_max_cnt,
1387
                    PropertyList=property_list))
1388

UNCOV
1389
        except CIMError as ce:
×
1390
            # Process error and continue or generate exception
UNCOV
1391
            results.handle_exception(ns, ce)
×
UNCOV
1392
            continue
×
1393

UNCOV
1394
        except Error as er:
×
UNCOV
1395
            raise pywbem_error_exception(er)
×
1396

UNCOV
1397
        except ValueError as ve:
×
UNCOV
1398
            raise click.ClickException(
×
1399
                'Instance associators failed because FilterQuery not allowed '
1400
                'with traditional Associators. '
1401
                f'--use-pull: {context.pywbem_server.use_pull}. '
1402
                f'Exception: {ve.__class__.__name__}: {ve}')
1403

UNCOV
1404
    results.display()
×
1405

1406

1407
def cmd_instance_count(context, classname, options):
2✔
1408
    """
1409
    Get the number of instances of each class in the namespace
1410
    """
UNCOV
1411
    conn = context.pywbem_server.conn
×
UNCOV
1412
    output_fmt = validate_output_format(context.output_format, 'TABLE')
×
1413

UNCOV
1414
    class_ignore_list = []
×
UNCOV
1415
    for cls in options['ignore_class']:
×
UNCOV
1416
        if ',' in cls:
×
UNCOV
1417
            class_ignore_list.extend(cls.split(','))
×
1418
        else:
UNCOV
1419
            class_ignore_list.append(cls)
×
1420

1421
    # Differs from class find because the classname is optional.
1422
    # If None, select all
UNCOV
1423
    if classname is None:
×
UNCOV
1424
        classname = '*'
×
1425

1426
    # Create list of namespaces from the option or from all namespaces
1427
    # default_rtn forces
UNCOV
1428
    ns_names = get_namespaces(context, options['namespace'],
×
1429
                              default_all_ns=True)
1430

UNCOV
1431
    ns_cln_tuples = []  # a list of tuples of namespace, classname
×
UNCOV
1432
    for namespace in ns_names:
×
1433
        # Get all classes in Namespace
UNCOV
1434
        try:
×
1435
            # Set cmd options that are required for this command.
1436
            # 1. Always use deep_inheritance
1437
            # 2. Set namespace to each namespace in loop
UNCOV
1438
            options['deep_inheritance'] = True
×
UNCOV
1439
            options['names_only'] = True
×
1440

UNCOV
1441
            classnames = enumerate_classes_filtered(context, namespace, None,
×
1442
                                                    options)
UNCOV
1443
        except Error as er:
×
UNCOV
1444
            raise pywbem_error_exception(er)
×
1445

UNCOV
1446
        if classnames:
×
UNCOV
1447
            classlist = filter_namelist(classname, classnames, ignore_case=True)
×
UNCOV
1448
            cl_tup = [(namespace, cln) for cln in classlist]
×
UNCOV
1449
            ns_cln_tuples.extend(cl_tup)
×
1450

1451
    # Sort since normal output for this command is  namespace, classname
1452
    # alphabetic order.
UNCOV
1453
    ns_cln_tuples.sort(key=lambda tup: (tup[0], tup[1]))
×
1454

UNCOV
1455
    display_data = []
×
UNCOV
1456
    error = 0
×
1457
    # Scan all of the class/namespace tuples to get count of instances
1458
    # of each class.
UNCOV
1459
    for tup in ns_cln_tuples:
×
UNCOV
1460
        ns = tup[0]
×
UNCOV
1461
        cln = tup[1]
×
UNCOV
1462
        if cln in class_ignore_list:
×
UNCOV
1463
            display_tuple = (ns, cln, "ignored")
×
UNCOV
1464
            display_data.append(display_tuple)
×
UNCOV
1465
            continue
×
1466
        # If an error has occurred, just display the remaining items with
1467
        # Not scanned msg.
UNCOV
1468
        if error:
×
1469
            display_tuple = (ns, cln, "Not scanned")
×
1470
            display_data.append(display_tuple)
×
1471
            continue
×
1472
        # Try block allows issues where enumerate does not properly execute
1473
        # The totals may be wrong but at least it gets what it can.
1474
        # This accounts for issues with some servers where there
1475
        # are providers that return errors from the enumerate.
UNCOV
1476
        inst_names = None
×
UNCOV
1477
        try:
×
UNCOV
1478
            inst_names = conn.EnumerateInstanceNames(cln, namespace=ns)
×
1479
        except CIMError as ce:
×
1480
            warning_msg(f"Server CIMError {ce.status_code_name} with "
×
1481
                        f"namepace={ns}, class={cln}. Continuing scan.")
1482
            display_tuple = (ns, cln, f"CIMError {ce.status_code_name}")
×
1483
            display_data.append(display_tuple)
×
1484
            continue
×
1485
        # Error exception caused termination of the connection. Add this
1486
        # item to the display with Server Fail message instead of count
1487
        except Error as er:
×
1488
            error = er
×
1489
            warning_msg(f"Server Error {er} with namepace={ns}, class={cln}. "
×
1490
                        "Terminating scan.")
1491
            display_tuple = (ns, cln, "Server Fail")
×
1492
            display_data.append(display_tuple)
×
1493
            continue
×
1494

1495
        # Sum the number of instances with the defined classname.
1496
        # this counts only classes with that specific classname and not
1497
        # subclasses
UNCOV
1498
        if inst_names:
×
UNCOV
1499
            count = sum(1 for inst_name in inst_names
×
1500
                        if (inst_name.classname.lower() == cln.lower()))
1501
            # Display only non-zero elements
UNCOV
1502
            if count:
×
UNCOV
1503
                display_tuple = (ns, cln, count)
×
UNCOV
1504
                display_data.append(display_tuple)
×
1505

1506
    # Post scan processing
1507
    # If sort set, re-sort by count size
UNCOV
1508
    if options['sort']:
×
UNCOV
1509
        display_data.sort(key=lambda x: x[2])
×
1510

UNCOV
1511
    headers = ['Namespace', 'Class', 'count']
×
UNCOV
1512
    rows = []
×
UNCOV
1513
    if display_data:
×
UNCOV
1514
        for item in display_data:
×
UNCOV
1515
            rows.append([item[0], item[1], item[2]])
×
1516

UNCOV
1517
    context.spinner_stop()
×
UNCOV
1518
    click.echo(format_table(rows, headers,
×
1519
                            title='Count of instances per class',
1520
                            table_format=output_fmt))
UNCOV
1521
    if error:
×
1522
        raise click.ClickException(
×
1523
            f"Server Error {error} at namespace={ns}, class:{cln}. "
1524
            "Scan incomplete.")
1525

1526

1527
def cmd_instance_query(context, query, options):
2✔
1528
    """
1529
    Execute the query defined by the inputs.
1530

1531
    This commands creates a Query request based on the command input variables
1532
    and options and outputs the result in either CIM or TABLE format.
1533
    """
UNCOV
1534
    conn = context.pywbem_server.conn
×
UNCOV
1535
    output_fmt = validate_output_format(context.output_format, ['CIM', 'TABLE'])
×
1536

UNCOV
1537
    try:
×
UNCOV
1538
        results = conn.PyWbemcliQueryInstances(
×
1539
            options['query_language'],
1540
            query,
1541
            namespace=options['namespace'],
1542
            MaxObjectCount=context.pywbem_server.pull_max_cnt)
1543

1544
        display_cim_objects(
×
1545
            context, results, output_fmt, summary=options['summary'])
1546

UNCOV
1547
    except Error as er:
×
UNCOV
1548
        raise pywbem_error_exception(er)
×
1549

1550

1551
def cmd_instance_shrub(context, instancename, options):
2✔
1552
    """
1553
    Display the association information defined by instancename as a tree
1554
    showing the various steps to get through the roles, references, etc. to
1555
    return the names of associated instances.
1556
    """
UNCOV
1557
    conn = context.pywbem_server.conn
×
1558

1559
    # ns_names = get_namespaces(context, options['namespace'], default_rtn=None)
UNCOV
1560
    instancepath = get_instancename(context, instancename, options)
×
1561

UNCOV
1562
    try:
×
1563

1564
        # Collect the data for the shrub
UNCOV
1565
        shrub = AssociationShrub(conn, instancepath,
×
1566
                                 Role=options['role'],
1567
                                 AssocClass=options['assoc_class'],
1568
                                 ResultRole=options['result_role'],
1569
                                 ResultClass=options['result_class'],
1570
                                 verbose=context.verbose,
1571
                                 fullpath=options['fullpath'])
1572

1573
        # display the shrub
UNCOV
1574
        context.spinner_stop()
×
UNCOV
1575
        shrub.display_shrub(context.output_format, options['summary'])
×
1576
    except Error as er:
×
1577
        raise pywbem_error_exception(er)
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc