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

pywbem / pywbemtools / test-2530

30 Mar 2025 06:49AM UTC coverage: 92.868% (-0.06%) from 92.929%
test-2530

push

github

andy-maier
Dev: Simplified the release of a version and the start of a new version

Details:

* Added new make targets:
  - release_branch
  - release_publish
  - start_branch
  - start_tag

* Updated the instructions in development.rst accordingly.

* Fixed typos and formatting issues in development.rst

Signed-off-by: Andreas Maier <andreas.r.maier@gmx.de>

6068 of 6534 relevant lines covered (92.87%)

10.05 hits per line

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

95.37
/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
"""
11✔
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
11✔
25

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

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

34
from ._display_cimobjects import display_cim_objects
11✔
35

36
from ._common_options import propertylist_option, names_only_option, \
11✔
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
11✔
43

44
from ._association_shrub import AssociationShrub
11✔
45

46
from .config import DEFAULT_QUERY_LANGUAGE
11✔
47
from ._common_cmd_functions import get_namespaces, enumerate_classes_filtered, \
11✔
48
    ResultsHandler
49
from .._click_extensions import PywbemtoolsGroup, PywbemtoolsCommand, \
11✔
50
    CMD_OPTS_TXT, GENERAL_OPTS_TXT, SUBCMD_HELP_TXT
51
from .._options import add_options, help_option, validate_required_arg
11✔
52
from .._output_formatting import validate_output_format, format_table, \
11✔
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
11✔
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
11✔
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
11✔
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
11✔
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
11✔
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
11✔
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
11✔
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
11✔
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
11✔
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
11✔
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
11✔
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
11✔
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,
11✔
175
           subcommand_metavar=SUBCMD_HELP_TXT)
176
@add_options(help_option)
11✔
177
def instance_group():
11✔
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
    """
190
    pass  # pylint: disable=unnecessary-pass
11✔
191

192

193
@instance_group.command('enumerate', cls=PywbemtoolsCommand,
11✔
194
                        options_metavar=CMD_OPTS_TXT)
195
@click.argument('classname', type=str, metavar='CLASSNAME', required=True)
11✔
196
@add_options(local_only_list_option)
11✔
197
@add_options(deep_inheritance_enum_option)
11✔
198
@add_options(include_qualifiers_list_option)
11✔
199
@add_options(include_classorigin_instance_option)
11✔
200
@add_options(propertylist_option)
11✔
201
@add_options(multiple_namespaces_option_dflt_conn)
11✔
202
@add_options(names_only_option)
11✔
203
@add_options(summary_option)
11✔
204
@add_options(filter_query_option)
11✔
205
@add_options(filter_query_language_option)
11✔
206
@add_options(show_null_option)
11✔
207
@add_options(object_order_option)
11✔
208
@add_options(help_option)
11✔
209
@click.pass_obj
11✔
210
def instance_enumerate(context, classname, **options):
11✔
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
    """
232
    context.execute_cmd(
11✔
233
        lambda: cmd_instance_enumerate(context, classname, options))
234

235

236
@instance_group.command('get', cls=PywbemtoolsCommand,
11✔
237
                        options_metavar=CMD_OPTS_TXT)
238
@click.argument('instancename', type=str, metavar='INSTANCENAME',
11✔
239
                required=False)
240
@add_options(local_only_get_option)
11✔
241
@add_options(include_qualifiers_get_option)
11✔
242
@add_options(include_classorigin_instance_option)
11✔
243
@add_options(propertylist_option)
11✔
244
@add_options(keybinding_key_option)
11✔
245
@add_options(multiple_namespaces_option_dflt_conn)
11✔
246
@add_options(object_order_option)
11✔
247
@add_options(help_instancename_option)
11✔
248
@add_options(show_null_option)
11✔
249
@add_options(help_option)
11✔
250
@click.pass_obj
11✔
251
def instance_get(context, instancename, **options):
11✔
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
    """
265
    if options['help_instancename']:
11✔
266
        show_help_instancename()
11✔
267
        return
11✔
268
    validate_required_arg(instancename, 'INSTANCENAME')
11✔
269
    context.execute_cmd(
11✔
270
        lambda: cmd_instance_get(context, instancename, options))
271

272

273
@instance_group.command('delete', cls=PywbemtoolsCommand,
11✔
274
                        options_metavar=CMD_OPTS_TXT)
275
@click.argument('instancename', type=str, metavar='INSTANCENAME',
11✔
276
                required=False)
277
@add_options(keybinding_key_option)
11✔
278
@add_options(namespace_option)
11✔
279
@add_options(help_instancename_option)
11✔
280
@add_options(help_option)
11✔
281
@click.pass_obj
11✔
282
def instance_delete(context, instancename, **options):
11✔
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
    """
293
    if options['help_instancename']:
11✔
294
        show_help_instancename()
11✔
295
        return
11✔
296
    validate_required_arg(instancename, 'INSTANCENAME')
11✔
297
    context.execute_cmd(
11✔
298
        lambda: cmd_instance_delete(context, instancename, options))
299

300

301
@instance_group.command('create', cls=PywbemtoolsCommand,
11✔
302
                        options_metavar=CMD_OPTS_TXT)
303
@click.argument('classname', type=str, metavar='CLASSNAME', required=True)
11✔
304
@add_options(property_create_option)
11✔
305
@add_options(verify_option)
11✔
306
@add_options(namespace_option)
11✔
307
@add_options(help_option)
11✔
308
@click.pass_obj
11✔
309
def instance_create(context, classname, **options):
11✔
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
    """
330
    context.execute_cmd(
11✔
331
        lambda: cmd_instance_create(context, classname, options))
332

333

334
@instance_group.command('modify', cls=PywbemtoolsCommand,
11✔
335
                        options_metavar=CMD_OPTS_TXT)
336
@click.argument('instancename', type=str, metavar='INSTANCENAME',
11✔
337
                required=False)
338
@add_options(property_modify_option)
11✔
339
@click.option('--pl', '--propertylist', 'propertylist', multiple=True, type=str,
11✔
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)
11✔
349
@add_options(keybinding_key_option)
11✔
350
@add_options(namespace_option)
11✔
351
@add_options(help_instancename_option)
11✔
352
@add_options(help_option)
11✔
353
@click.pass_obj
11✔
354
def instance_modify(context, instancename, **options):
11✔
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
    """
373
    if options['help_instancename']:
11✔
374
        show_help_instancename()
11✔
375
        return
11✔
376
    validate_required_arg(instancename, 'INSTANCENAME')
11✔
377
    context.execute_cmd(
11✔
378
        lambda: cmd_instance_modify(context, instancename, options))
379

380

381
@instance_group.command('associators', cls=PywbemtoolsCommand,
11✔
382
                        options_metavar=CMD_OPTS_TXT)
383
@click.argument('instancename', type=str, metavar='INSTANCENAME',
11✔
384
                required=False)
385
@click.option('--ac', '--assoc-class', 'assoc_class', type=str, required=False,
11✔
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,
11✔
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,
11✔
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,
11✔
397
              metavar='PROPERTYNAME',
398
              help='Filter the result set by far end role name.')
399
@add_options(include_qualifiers_list_option)
11✔
400
@add_options(include_classorigin_instance_option)
11✔
401
@add_options(propertylist_option)
11✔
402
@add_options(names_only_option)
11✔
403
@add_options(keybinding_key_option)
11✔
404
@add_options(multiple_namespaces_option_dflt_conn)
11✔
405
@add_options(summary_option)
11✔
406
@add_options(filter_query_option)
11✔
407
@add_options(filter_query_language_option)
11✔
408
@add_options(show_null_option)
11✔
409
@add_options(help_instancename_option)
11✔
410
@add_options(object_order_option)
11✔
411
@add_options(help_option)
11✔
412
@click.pass_obj
11✔
413
def instance_associators(context, instancename, **options):
11✔
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
    """
436
    if options['help_instancename']:
11✔
437
        show_help_instancename()
11✔
438
        return
11✔
439
    validate_required_arg(instancename, 'INSTANCENAME')
11✔
440
    context.execute_cmd(
11✔
441
        lambda: cmd_instance_associators(context, instancename, options))
442

443

444
@instance_group.command('references', cls=PywbemtoolsCommand,
11✔
445
                        options_metavar=CMD_OPTS_TXT)
446
@click.argument('instancename', type=str, metavar='INSTANCENAME',
11✔
447
                required=False)
448
@click.option('--rc', '--result-class', 'result_class', type=str,
11✔
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',
11✔
453
              help='Filter the result set by source end role name.')
454
@add_options(include_qualifiers_list_option)
11✔
455
@add_options(include_classorigin_instance_option)
11✔
456
@add_options(propertylist_option)
11✔
457
@add_options(names_only_option)
11✔
458
@add_options(keybinding_key_option)
11✔
459
@add_options(multiple_namespaces_option_dflt_conn)
11✔
460
@add_options(summary_option)
11✔
461
@add_options(filter_query_option)
11✔
462
@add_options(show_null_option)
11✔
463
@add_options(filter_query_language_option)
11✔
464
@add_options(help_instancename_option)
11✔
465
@add_options(object_order_option)
11✔
466
@add_options(help_option)
11✔
467
@click.pass_obj
11✔
468
def instance_references(context, instancename, **options):
11✔
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
    """
491
    if options['help_instancename']:
11✔
492
        show_help_instancename()
11✔
493
        return
11✔
494
    validate_required_arg(instancename, 'INSTANCENAME')
11✔
495
    # pylint: disable=line-too-long
496
    context.execute_cmd(lambda: cmd_instance_references(context, instancename, options))  # noqa: E501
11✔
497

498

499
@instance_group.command('invokemethod', cls=PywbemtoolsCommand,
11✔
500
                        options_metavar=CMD_OPTS_TXT)
501
@click.argument('instancename', type=str, metavar='INSTANCENAME',
11✔
502
                required=False)
503
@click.argument('methodname', type=str, metavar='METHODNAME', required=False)
11✔
504
@click.option('-p', '--parameter', type=str, metavar='PARAMETERNAME=VALUE',
11✔
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)
11✔
512
@add_options(namespace_option)
11✔
513
@add_options(help_instancename_option)
11✔
514
@add_options(help_option)
11✔
515
@click.pass_obj
11✔
516
def instance_invokemethod(context, instancename, methodname, **options):
11✔
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
    """
541
    if options['help_instancename']:
11✔
542
        show_help_instancename()
11✔
543
        return
11✔
544
    validate_required_arg(instancename, 'INSTANCENAME')
11✔
545
    validate_required_arg(methodname, 'METHODNAME')
11✔
546
    # pylint: disable=line-too-long
547
    context.execute_cmd(lambda: cmd_instance_invokemethod(context, instancename, methodname, options))  # noqa: E501
11✔
548

549

550
@instance_group.command('query', cls=PywbemtoolsCommand,
11✔
551
                        options_metavar=CMD_OPTS_TXT)
552
@click.argument('query', type=str, required=True, metavar='QUERY-STRING')
11✔
553
@click.option('--ql', '--query-language', 'query_language', type=str,
11✔
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)
11✔
558
@add_options(summary_option)
11✔
559
@add_options(help_option)
11✔
560
@click.pass_obj
11✔
561
def instance_query(context, query, **options):
11✔
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
    """
572
    context.execute_cmd(lambda: cmd_instance_query(context, query, options))
11✔
573

574

575
@instance_group.command('count', cls=PywbemtoolsCommand,
11✔
576
                        options_metavar=CMD_OPTS_TXT)
577
@click.argument('classname', type=str, metavar='CLASSNAME-GLOB',
11✔
578
                required=False)
579
@add_options(multiple_namespaces_option_dflt_all)
11✔
580
@click.option('-s', '--sort', is_flag=True, required=False,
11✔
581
              help='Sort by instance count. Otherwise sorted by class name.')
582
@click.option('--ignore-class', type=str,
11✔
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)
11✔
594
@add_options(help_option)
11✔
595
@click.pass_obj
11✔
596
def instance_count(context, classname, **options):
11✔
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
    """
630
    context.execute_cmd(lambda: cmd_instance_count(context, classname, options))
11✔
631

632

633
@instance_group.command('shrub', cls=PywbemtoolsCommand,
11✔
634
                        options_metavar=CMD_OPTS_TXT)
635
@click.argument('instancename', type=str, metavar='INSTANCENAME',
11✔
636
                required=False)
637
@click.option('--ac', '--assoc-class', 'assoc_class', type=str, required=False,
11✔
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,
11✔
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,
11✔
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,
11✔
649
              metavar='PROPERTYNAME',
650
              help='Filter the result set by far end role name.')
651
@add_options(keybinding_key_option)
11✔
652
@add_options(namespace_option)
11✔
653
@add_options(summary_option)
11✔
654
@click.option('-f', '--fullpath', default=False, is_flag=True,
11✔
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)
11✔
661
@add_options(help_option)
11✔
662
@click.pass_obj
11✔
663
def instance_shrub(context, instancename, **options):
11✔
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
    """
687
    if options['help_instancename']:
11✔
688
        show_help_instancename()
11✔
689
        return
11✔
690
    validate_required_arg(instancename, 'INSTANCENAME')
11✔
691
    # pylint: disable=line-too-long
692
    context.execute_cmd(lambda: cmd_instance_shrub(context, instancename, options))  # noqa: E501
11✔
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 = """
11✔
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():
11✔
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

812
    click.echo(HELP_INSTANCENAME_MSG)
11✔
813

814

815
def get_instancename(context, instancename, options, default_all_ns=False):
11✔
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
    """
874
    conn = context.pywbem_server.conn
11✔
875

876
    def validate_namespace_option(class_path):
11✔
877
        """Validate either namespace in instance or --namespace but not both"""
878
        if class_path.namespace:
11✔
879
            if options['namespace']:
11✔
880
                raise click.ClickException(
11✔
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
888
    if isinstance(options['namespace'], tuple):
11✔
889
        ns_names = get_namespaces(context, options['namespace'],
11✔
890
                                  default_all_ns=default_all_ns)
891
    else:
892
        ns_names = options['namespace']
11✔
893

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

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

907
        validate_namespace_option(class_path)
11✔
908

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

921
    # if --key option exists.
922
    elif options['key']:
11✔
923
        # Transform the --key option values into WBEM URI keybinding strings
924
        kb_strs = []
11✔
925
        for kv in options['key']:
11✔
926
            key, value = parse_kv_pair(kv)
11✔
927
            if value is None:
11✔
928
                raise click.ClickException(
11✔
929
                    f"VALUE in --key option argument is missing: {kv}")
930
            try:
11✔
931
                int(value)
11✔
932
                is_int = True
11✔
933
            except (ValueError, TypeError):
11✔
934
                is_int = False
11✔
935
            if value is None:
11✔
936
                # There is no official NULL representation in WBEM URI
937
                kb_value = ''
×
938
            elif is_int:
11✔
939
                # integer - use without quotes
940
                kb_value = value
11✔
941
            elif value.upper() in ('TRUE', 'FALSE'):
11✔
942
                # boolean - use the upper cased string without quotes
943
                kb_value = value.upper()
11✔
944
            elif value.startswith('"') and value.endswith('"'):
11✔
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.
948
                kb_value = value
11✔
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.
957
                kb_value = f'"{mof_escaped(value)}"'
11✔
958

959
            kb_strs.append(f"{key}={kb_value}")
11✔
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().
964
        try:
11✔
965
            CIMClassName.from_wbem_uri(instancename)
11✔
966
        except ValueError as exc:
11✔
967
            raise click.ClickException(str(exc))
11✔
968

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

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

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

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

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

996
    return instance_path
11✔
997

998

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

1005

1006
def cmd_instance_get(context, instancename, options):
11✔
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
    """
1018
    conn = context.pywbem_server.conn
11✔
1019
    output_fmt = validate_output_format(context.output_format, ['CIM', 'TABLE'])
11✔
1020

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

1024
    property_list = resolve_propertylist(options['propertylist'])
11✔
1025

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

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

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

1045
        except Error as er:
11✔
1046
            raise pywbem_error_exception(er)
11✔
1047

1048
    results.display()
11✔
1049

1050

1051
def cmd_instance_delete(context, instancename, options):
11✔
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
    """
1059
    conn = context.pywbem_server.conn
11✔
1060

1061
    instancepath = get_instancename(context, instancename, options)
11✔
1062

1063
    try:
11✔
1064
        conn.DeleteInstance(instancepath)
11✔
1065

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

1070
    except Error as er:
11✔
1071
        raise pywbem_error_exception(er)
11✔
1072

1073

1074
def cmd_instance_create(context, classname, options):
11✔
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
    """
1080
    conn = context.pywbem_server.conn
11✔
1081
    ns = options['namespace'] or conn.default_namespace
11✔
1082
    try:
11✔
1083
        class_ = conn.GetClass(
11✔
1084
            classname, namespace=ns, LocalOnly=False)
1085
    except CIMError as ce:
11✔
1086
        if ce.status_code == CIM_ERR_NOT_FOUND:
11✔
1087
            raise click.ClickException(
11✔
1088
                f'CIMClass: "{classname}" does not exist in '
1089
                f'namespace "{ns}" in WEB server: {conn}.')
1090
        raise pywbem_error_exception(ce)
11✔
1091

1092
    except Error as er:
11✔
1093
        raise pywbem_error_exception(er)
11✔
1094

1095
    properties = options['property']
11✔
1096

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

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

1108
        context.spinner_stop()
11✔
1109
        click.echo(f'{name}')
11✔
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):
11✔
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
    """
1130
    conn = context.pywbem_server.conn
11✔
1131
    instancepath = get_instancename(context, instancename, options)
11✔
1132

1133
    ns = options['namespace'] or conn.default_namespace
11✔
1134

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

1144
        raise pywbem_error_exception(ce)
11✔
1145
    except Error as er:
11✔
1146
        raise pywbem_error_exception(er)
11✔
1147

1148
    property_list = resolve_propertylist(options['propertylist'])
11✔
1149

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

1153
    modified_inst.path = instancepath
11✔
1154

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

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

1172

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

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

1186

1187
def get_filterquerylanguage(options):
11✔
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
    """
1195
    if options['filter_query']:
11✔
1196
        fql = options['filter_query_language'] or 'DMTF:FQL'
11✔
1197
    else:
1198
        fql = options['filter_query_language']
11✔
1199
    return fql
11✔
1200

1201

1202
def enumerate_instances(conn, context, options, namespace, classname,
11✔
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
    """
1213
    try:
11✔
1214
        if options['names_only']:
11✔
1215
            return conn.PyWbemcliEnumerateInstancePaths(
11✔
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

1222
        return conn.PyWbemcliEnumerateInstances(
11✔
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

1234
    except Error as er:
11✔
1235
        # Return either the original exception or the ClickException.
1236
        if return_original_err:
11✔
1237
            raise er
11✔
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.
1242
    except ValueError as ve:
11✔
1243
        raise click.ClickException(
11✔
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):
11✔
1251
    """
1252
    Enumerate CIM instances or CIM instance names
1253

1254
    Returns:
1255
        list of objects retrieved.
1256

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

1261
    property_list = resolve_propertylist(options['propertylist'])
11✔
1262

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

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

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

1277
        except Error as er:
11✔
1278
            raise pywbem_error_exception(er)
11✔
1279

1280
    results.display()
11✔
1281

1282

1283
def cmd_instance_references(context, instancename, options):
11✔
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
    """
1293
    conn = context.pywbem_server.conn
11✔
1294
    output_fmt = validate_output_format(context.output_format, ['CIM', 'TABLE'])
11✔
1295

1296
    instancepath = get_instancename(context, instancename, options)
11✔
1297

1298
    property_list = resolve_propertylist(options['propertylist'])
11✔
1299

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

1304
    for ns in results:
11✔
1305
        try:
11✔
1306
            instancepath.namespace = ns
11✔
1307
            if options['names_only']:
11✔
1308
                results.add(conn.PyWbemcliReferenceInstancePaths(
11✔
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:
1316
                results.add(conn.PyWbemcliReferenceInstances(
11✔
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

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

1332
        except Error as er:
11✔
1333
            raise pywbem_error_exception(er)
11✔
1334

1335
        except ValueError as ve:
11✔
1336
            raise click.ClickException(
11✔
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}')
1341
    results.display()
11✔
1342

1343

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

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

1354
    instancepath = get_instancename(context, instancename, options)
11✔
1355

1356
    property_list = resolve_propertylist(options['propertylist'])
11✔
1357

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

1362
    for ns in results:
11✔
1363
        try:
11✔
1364
            instancepath.namespace = ns
11✔
1365
            if options['names_only']:
11✔
1366
                results.add(conn.PyWbemcliAssociatorInstancePaths(
11✔
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:
1376
                results.add(conn.PyWbemcliAssociatorInstances(
11✔
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

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

1394
        except Error as er:
11✔
1395
            raise pywbem_error_exception(er)
11✔
1396

1397
        except ValueError as ve:
11✔
1398
            raise click.ClickException(
11✔
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

1404
    results.display()
11✔
1405

1406

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

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

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

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

1431
    ns_cln_tuples = []  # a list of tuples of namespace, classname
11✔
1432
    for namespace in ns_names:
11✔
1433
        # Get all classes in Namespace
1434
        try:
11✔
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
1438
            options['deep_inheritance'] = True
11✔
1439
            options['names_only'] = True
11✔
1440

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

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

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

1455
    display_data = []
11✔
1456
    error = 0
11✔
1457
    # Scan all of the class/namespace tuples to get count of instances
1458
    # of each class.
1459
    for tup in ns_cln_tuples:
11✔
1460
        ns = tup[0]
11✔
1461
        cln = tup[1]
11✔
1462
        if cln in class_ignore_list:
11✔
1463
            display_tuple = (ns, cln, "ignored")
11✔
1464
            display_data.append(display_tuple)
11✔
1465
            continue
11✔
1466
        # If an error has occurred, just display the remaining items with
1467
        # Not scanned msg.
1468
        if error:
11✔
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.
1476
        inst_names = None
11✔
1477
        try:
11✔
1478
            inst_names = conn.EnumerateInstanceNames(cln, namespace=ns)
11✔
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
1498
        if inst_names:
11✔
1499
            count = sum(1 for inst_name in inst_names
11✔
1500
                        if (inst_name.classname.lower() == cln.lower()))
1501
            # Display only non-zero elements
1502
            if count:
11✔
1503
                display_tuple = (ns, cln, count)
11✔
1504
                display_data.append(display_tuple)
11✔
1505

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

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

1517
    context.spinner_stop()
11✔
1518
    click.echo(format_table(rows, headers,
11✔
1519
                            title='Count of instances per class',
1520
                            table_format=output_fmt))
1521
    if error:
11✔
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):
11✔
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
    """
1534
    conn = context.pywbem_server.conn
11✔
1535
    output_fmt = validate_output_format(context.output_format, ['CIM', 'TABLE'])
11✔
1536

1537
    try:
11✔
1538
        results = conn.PyWbemcliQueryInstances(
11✔
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

1547
    except Error as er:
11✔
1548
        raise pywbem_error_exception(er)
11✔
1549

1550

1551
def cmd_instance_shrub(context, instancename, options):
11✔
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
    """
1557
    conn = context.pywbem_server.conn
11✔
1558

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

1562
    try:
11✔
1563

1564
        # Collect the data for the shrub
1565
        shrub = AssociationShrub(conn, instancepath,
11✔
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
1574
        context.spinner_stop()
11✔
1575
        shrub.display_shrub(context.output_format, options['summary'])
11✔
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