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

pywbem / pywbemtools / 4407423805

pending completion
4407423805

push

github

GitHub
Add docs command to pywbemlistener (#1288)

32 of 38 new or added lines in 6 files covered. (84.21%)

4 existing lines in 3 files now uncovered.

5953 of 6417 relevant lines covered (92.77%)

14.56 hits per line

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

95.28
/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
"""
16✔
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
from __future__ import absolute_import, print_function
16✔
24

25
import six
16✔
26

27
import click
16✔
28

29
from pywbem import CIMInstanceName, CIMClassName, Error, CIMError, \
16✔
30
    CIM_ERR_NOT_FOUND
31

32
from .pywbemcli import cli
16✔
33
from ._common import pick_instance, resolve_propertylist, create_ciminstance, \
16✔
34
    filter_namelist, verify_operation, process_invokemethod, \
35
    pywbem_error_exception, parse_kv_pair
36

37
from ._display_cimobjects import display_cim_objects
16✔
38

39
from ._common_options import propertylist_option, names_only_option, \
16✔
40
    include_classorigin_instance_option, namespace_option, summary_option, \
41
    verify_option, multiple_namespaces_option_dflt_all, \
42
    multiple_namespaces_option_dflt_conn, class_filter_options, \
43
    object_order_option
44

45
from ._cimvalueformatter import mof_escaped
16✔
46

47
from ._association_shrub import AssociationShrub
16✔
48

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

58
#
59
#   Common option definitions for instance group
60
#
61

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

67
# Issue 224 - Exception in prompt-toolkit with python 2.7. Caused because
68
# with prompt-toolkit 2 + the completer requires unicode and click_repl not
69
# passing help as unicode in options as unicode
70
# NOTE: Insure that all option help attributes are unicode to get around this
71
#       issue
72

73

74
# This is instance-only because the default is False for include-qualifiers
75
# on instances but True on classes
76
include_qualifiers_get_option = [              # pylint: disable=invalid-name
16✔
77
    click.option('--iq', '--include-qualifiers', 'include_qualifiers',
78
                 is_flag=True, required=False,
79
                 help=u'Include qualifiers in the returned instance. '
80
                      u'Not all servers return qualifiers on instances. '
81
                      u'Default: Do not include qualifiers.')]
82

83
include_qualifiers_list_option = [              # pylint: disable=invalid-name
16✔
84
    click.option('--iq', '--include-qualifiers', 'include_qualifiers',
85
                 is_flag=True, required=False,
86
                 help=u'When traditional operations are used, include '
87
                      u'qualifiers in the returned instances. '
88
                      u'Some servers may ignore this option. '
89
                      u'By default, and when pull operations are used, '
90
                      u'qualifiers will never be included.')]
91

92
# specific to instance because DeepInheritance differs between class and
93
# instance operations.
94
deep_inheritance_enum_option = [              # pylint: disable=invalid-name
16✔
95
    click.option('--di', '--deep-inheritance', 'deep_inheritance',
96
                 is_flag=True, required=False,
97
                 help=u'Include subclass properties in the returned '
98
                      u'instances. '
99
                      u'Default: Do not include subclass properties.')]
100

101
local_only_get_option = [              # pylint: disable=invalid-name
16✔
102
    click.option('--lo', '--local-only', 'local_only', is_flag=True,
103
                 required=False,
104
                 help=u'Do not include superclass properties in the returned '
105
                      u'instance. '
106
                      u'Some servers may ignore this option. '
107
                      u'Default: Include superclass properties.')]
108

109
local_only_list_option = [              # pylint: disable=invalid-name
16✔
110
    click.option('--lo', '--local-only', 'local_only', is_flag=True,
111
                 required=False,
112
                 help=u'When traditional operations are used, do not include '
113
                      u'superclass properties in the returned instances. '
114
                      u'Some servers may ignore this option. '
115
                      u'By default, and when pull operations are used, '
116
                      u'superclass properties will always be included.')]
117

118
property_create_option = [              # pylint: disable=invalid-name
16✔
119
    click.option('-p', '--property', type=str, metavar='PROPERTYNAME=VALUE',
120
                 required=False, multiple=True,
121
                 help=u'Initial property value for the new instance. '
122
                      u'May be specified multiple times. '
123
                      u'Array property values are specified as a '
124
                      u'comma-separated list; embedded instances are not '
125
                      u'supported. '
126
                      u'Default: No initial properties provided.')]
127

128
property_modify_option = [              # pylint: disable=invalid-name
16✔
129
    click.option('-p', '--property', type=str, metavar='PROPERTYNAME=VALUE',
130
                 required=False, multiple=True,
131
                 help=u'Property to be modified, with its new value. '
132
                      u'May be specified once for each property to be '
133
                      u'modified. '
134
                      u'Array property values are specified as a '
135
                      u'comma-separated list; embedded instances are not '
136
                      u'supported. '
137
                      u'Default: No properties modified.')]
138

139
keybinding_key_option = [              # pylint: disable=invalid-name
16✔
140
    click.option('-k', '--key', type=str, metavar='KEYNAME=VALUE',
141
                 required=False, multiple=True,
142
                 help=u'Value for a key in keybinding of CIM instance name. '
143
                      u'May be specified multiple times. '
144
                      u'Allows defining keys without the issues of quotes. '
145
                      u'Default: No keybindings provided.')]
146

147
filter_query_language_option = [              # pylint: disable=invalid-name
16✔
148
    click.option('--fql', '--filter-query-language', 'filter_query_language',
149
                 type=str, metavar='QUERY-LANGUAGE', default=None,
150
                 help=u'The filter query language to be used with '
151
                      u'--filter-query. '
152
                      u'Default: DMTF:FQL.')]
153

154
filter_query_option = [              # pylint: disable=invalid-name
16✔
155
    click.option('--fq', '--filter-query', 'filter_query', type=str,
156
                 metavar='QUERY-STRING', default=None,
157
                 help=u'When pull operations are used, filter the instances in '
158
                      u'the result via a filter query. '
159
                      u'By default, and when traditional operations are used, '
160
                      u'no such filtering takes place.')]
161

162
help_instancename_option = [              # pylint: disable=invalid-name
16✔
163
    click.option('--hi', '--help-instancename', 'help_instancename',
164
                 is_flag=True, required=False, is_eager=True,
165
                 help=u'Show help message for specifying INSTANCENAME '
166
                      u'including use of the --key and --namespace options.')]
167

168
show_null_option = [              # pylint: disable=invalid-name
16✔
169
    click.option('--show-null', 'show_null', is_flag=True, required=False,
170
                 help=u'In the TABLE output formats, show properties with no '
171
                      u'value (i.e. Null) in all of the instances to be '
172
                      u'displayed. Otherwise only properties at least '
173
                      u'one instance has a non-Null property are displayed')]
174

175

176
##########################################################################
177
#
178
#   Click command group and command definitions
179
#   These decorated functions implement the commands, arguments, and
180
#
181
###########################################################################
182

183

184
@cli.group('instance', cls=PywbemtoolsGroup, options_metavar=GENERAL_OPTS_TXT,
16✔
185
           subcommand_metavar=SUBCMD_HELP_TXT)
186
@add_options(help_option)
16✔
187
def instance_group():
5✔
188
    """
189
    Command group for CIM instances.
190

191
    This command group defines commands to inspect instances, to invoke
192
    methods on instances, and to create and delete instances.
193

194
    Modification of instances is not currently supported.
195

196
    In addition to the command-specific options shown in this help text, the
197
    general options (see 'pywbemcli --help') can also be specified before the
198
    'instance' keyword.
199
    """
200
    pass  # pylint: disable=unnecessary-pass
16✔
201

202

203
@instance_group.command('enumerate', cls=PywbemtoolsCommand,
16✔
204
                        options_metavar=CMD_OPTS_TXT)
205
@click.argument('classname', type=str, metavar='CLASSNAME', required=True)
16✔
206
@add_options(local_only_list_option)
16✔
207
@add_options(deep_inheritance_enum_option)
16✔
208
@add_options(include_qualifiers_list_option)
16✔
209
@add_options(include_classorigin_instance_option)
16✔
210
@add_options(propertylist_option)
16✔
211
@add_options(multiple_namespaces_option_dflt_conn)
16✔
212
@add_options(names_only_option)
16✔
213
@add_options(summary_option)
16✔
214
@add_options(filter_query_option)
16✔
215
@add_options(filter_query_language_option)
16✔
216
@add_options(show_null_option)
16✔
217
@add_options(object_order_option)
16✔
218
@add_options(help_option)
16✔
219
@click.pass_obj
16✔
220
def instance_enumerate(context, classname, **options):
5✔
221
    """
222
    List the instances of a class.
223

224
    Enumerate the CIM instances of the specified class (CLASSNAME argument),
225
    including instances of subclasses in the specified CIM namespace(s)
226
    (--namespace option), and display the returned instances, or instance paths
227
    if --names-only was specified. If no namespace was specified, the default
228
    namespace of the connection is used.
229

230
    The instances to be retrieved can be filtered by the --filter-query option.
231

232
    The --local-only, --deep-inheritance, --include-qualifiers,
233
    --include-classorigin, and --propertylist options determine which parts
234
    are included in each retrieved instance.
235

236
    The --names-only option can be used to show only the instance paths.
237

238
    In the output, the instances and instance paths will be formatted as
239
    defined by the --output-format general option. Table formats on instances
240
    will be replaced with MOF format.
241
    """
242
    context.execute_cmd(
16✔
243
        lambda: cmd_instance_enumerate(context, classname, options))
244

245

246
@instance_group.command('get', cls=PywbemtoolsCommand,
16✔
247
                        options_metavar=CMD_OPTS_TXT)
248
@click.argument('instancename', type=str, metavar='INSTANCENAME',
16✔
249
                required=False)
250
@add_options(local_only_get_option)
16✔
251
@add_options(include_qualifiers_get_option)
16✔
252
@add_options(include_classorigin_instance_option)
16✔
253
@add_options(propertylist_option)
16✔
254
@add_options(keybinding_key_option)
16✔
255
@add_options(multiple_namespaces_option_dflt_conn)
16✔
256
@add_options(object_order_option)
16✔
257
@add_options(help_instancename_option)
16✔
258
@add_options(show_null_option)
16✔
259
@add_options(help_option)
16✔
260
@click.pass_obj
16✔
261
def instance_get(context, instancename, **options):
5✔
262
    """
263
    Get an instance of a class.
264

265
    For information on how to specify the instance using INSTANCENAME and the
266
    --key and --namespace options, invoke with --help-instancename.
267

268
    The --local-only, --include-qualifiers, --include-classorigin, and
269
    --propertylist options determine which parts are included in the retrieved
270
    instance.
271

272
    In the output, the instance will formatted as defined by the
273
    --output-format general option.
274
    """
275
    if options['help_instancename']:
16✔
276
        show_help_instancename()
16✔
277
        return
16✔
278
    validate_required_arg(instancename, 'INSTANCENAME')
16✔
279
    context.execute_cmd(
16✔
280
        lambda: cmd_instance_get(context, instancename, options))
281

282

283
@instance_group.command('delete', cls=PywbemtoolsCommand,
16✔
284
                        options_metavar=CMD_OPTS_TXT)
285
@click.argument('instancename', type=str, metavar='INSTANCENAME',
16✔
286
                required=False)
287
@add_options(keybinding_key_option)
16✔
288
@add_options(namespace_option)
16✔
289
@add_options(help_instancename_option)
16✔
290
@add_options(help_option)
16✔
291
@click.pass_obj
16✔
292
def instance_delete(context, instancename, **options):
5✔
293
    """
294
    Delete an instance of a class.
295

296
    WARNING: Deletion of instances will cause the removal of corresponding
297
    resources in the managed environment (i.e. in the real world). Some
298
    instances may not be deletable.
299

300
    For information on how to specify the instance using INSTANCENAME and the
301
    --key and --namespace options, invoke with --help-instancename.
302
    """
303
    if options['help_instancename']:
16✔
304
        show_help_instancename()
16✔
305
        return
16✔
306
    validate_required_arg(instancename, 'INSTANCENAME')
16✔
307
    context.execute_cmd(
16✔
308
        lambda: cmd_instance_delete(context, instancename, options))
309

310

311
@instance_group.command('create', cls=PywbemtoolsCommand,
16✔
312
                        options_metavar=CMD_OPTS_TXT)
313
@click.argument('classname', type=str, metavar='CLASSNAME', required=True)
16✔
314
@add_options(property_create_option)
16✔
315
@add_options(verify_option)
16✔
316
@add_options(namespace_option)
16✔
317
@add_options(help_option)
16✔
318
@click.pass_obj
16✔
319
def instance_create(context, classname, **options):
5✔
320
    """
321
    Create an instance of a class in a namespace.
322

323
    Create a CIM instance of the specified creation class (CLASSNAME
324
    argument) in the specified CIM namespace (--namespace option), with
325
    the specified properties (--property options) and display the CIM instance
326
    path of the created instance. If no namespace was specified, the default
327
    namespace of the connection is used.
328

329
    The properties to be initialized and their new values are specified using
330
    the --property option, which may be specified multiple times.
331

332
    Pywbemcli retrieves the class definition from the server in order to
333
    verify that the specified properties are consistent with the property
334
    characteristics in the class definition.
335

336
    Example:
337

338
      pywbemcli instance create CIM_blah -P id=3 -P arr="bla bla",foo
339
    """
340
    context.execute_cmd(
16✔
341
        lambda: cmd_instance_create(context, classname, options))
342

343

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

368
    For information on how to specify the instance using INSTANCENAME and the
369
    --key and --namespace options, invoke with --help-instancename.
370

371
    The properties to be modified and their new values are specified using the
372
    --property option, which may be specified multiple times.
373

374
    The --propertylist option allows restricting the set of properties to be
375
    modified. Given that the set of properties to be modified is already
376
    determined by the specified --property options, it does not need to be
377
    specified.
378

379
    Example:
380

381
      pywbemcli instance modify CIM_blah.fred=3 -P id=3 -P arr="bla bla",foo
382
    """
383
    if options['help_instancename']:
16✔
384
        show_help_instancename()
16✔
385
        return
16✔
386
    validate_required_arg(instancename, 'INSTANCENAME')
16✔
387
    context.execute_cmd(
16✔
388
        lambda: cmd_instance_modify(context, instancename, options))
389

390

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

427
    List the CIM instances that are associated with the specified CIM instance,
428
    and display the returned instances, or instance paths if --names-only was
429
    specified.
430

431
    For information on how to specify the instance using INSTANCENAME and the
432
    --key and --namespace options, invoke with --help-instancename.
433

434
    The instances to be retrieved can be filtered by the --filter-query,
435
    --role, --result-role, --assoc-class, and --result-class options.
436

437
    The --include-qualifiers, --include-classorigin, and --propertylist options
438
    determine which parts are included in each retrieved instance.
439

440
    The --names-only option can be used to show only the instance paths.
441

442
    In the output, the instances and instance paths will be formatted as
443
    defined by the --output-format general option. Table formats on instances
444
    will be replaced with MOF format.
445
    """
446
    if options['help_instancename']:
16✔
447
        show_help_instancename()
16✔
448
        return
16✔
449
    validate_required_arg(instancename, 'INSTANCENAME')
16✔
450
    context.execute_cmd(
16✔
451
        lambda: cmd_instance_associators(context, instancename, options))
452

453

454
@instance_group.command('references', cls=PywbemtoolsCommand,
16✔
455
                        options_metavar=CMD_OPTS_TXT)
456
@click.argument('instancename', type=str, metavar='INSTANCENAME',
16✔
457
                required=False)
458
@click.option('--rc', '--result-class', 'result_class', type=str,
16✔
459
              required=False, metavar='CLASSNAME',
460
              help=u'Filter the result set by result class name. '
461
                   u'Subclasses of the specified class also match.')
462
@click.option('-r', '--role', type=str, required=False, metavar='PROPERTYNAME',
16✔
463
              help=u'Filter the result set by source end role name.')
464
@add_options(include_qualifiers_list_option)
16✔
465
@add_options(include_classorigin_instance_option)
16✔
466
@add_options(propertylist_option)
16✔
467
@add_options(names_only_option)
16✔
468
@add_options(keybinding_key_option)
16✔
469
@add_options(multiple_namespaces_option_dflt_conn)
16✔
470
@add_options(summary_option)
16✔
471
@add_options(filter_query_option)
16✔
472
@add_options(show_null_option)
16✔
473
@add_options(filter_query_language_option)
16✔
474
@add_options(help_instancename_option)
16✔
475
@add_options(object_order_option)
16✔
476
@add_options(help_option)
16✔
477
@click.pass_obj
16✔
478
def instance_references(context, instancename, **options):
5✔
479
    """
480
    List the instances referencing an instance.
481

482
    List the CIM (association) instances that reference the specified CIM
483
    instance, and display the returned instances, or instance paths if
484
    --names-only was specified.
485

486
    For information on how to specify the instance using INSTANCENAME and the
487
    --key and --namespace options, invoke with --help-instancename.
488

489
    The instances to be retrieved can be filtered by the --filter-query, --role
490
    and --result-class options.
491

492
    The --include-qualifiers, --include-classorigin, and --propertylist options
493
    determine which parts are included in each retrieved instance.
494

495
    The --names-only option can be used to show only the instance paths.
496

497
    In the output, the instances and instance paths will be formatted as
498
    defined by the --output-format general option. Table formats on instances
499
    will be replaced with MOF format.
500
    """
501
    if options['help_instancename']:
16✔
502
        show_help_instancename()
16✔
503
        return
16✔
504
    validate_required_arg(instancename, 'INSTANCENAME')
16✔
505
    # pylint: disable=line-too-long
506
    context.execute_cmd(lambda: cmd_instance_references(context, instancename, options))  # noqa: E501
16✔
507

508

509
@instance_group.command('invokemethod', cls=PywbemtoolsCommand,
16✔
510
                        options_metavar=CMD_OPTS_TXT)
511
@click.argument('instancename', type=str, metavar='INSTANCENAME',
16✔
512
                required=False)
513
@click.argument('methodname', type=str, metavar='METHODNAME', required=False)
16✔
514
@click.option('-p', '--parameter', type=str, metavar='PARAMETERNAME=VALUE',
16✔
515
              required=False, multiple=True,
516
              help=u'Specify a method input parameter with its value. '
517
                   u'May be specified multiple times. '
518
                   u'Array property values are specified as a comma-separated '
519
                   u'list; embedded instances are not supported. '
520
                   u'Default: No input parameters.')
521
@add_options(keybinding_key_option)
16✔
522
@add_options(namespace_option)
16✔
523
@add_options(help_instancename_option)
16✔
524
@add_options(help_option)
16✔
525
@click.pass_obj
16✔
526
def instance_invokemethod(context, instancename, methodname, **options):
5✔
527
    """
528
    Invoke a method on an instance.
529

530
    Invoke a CIM method (METHODNAME argument) on a CIM instance with the
531
    specified input parameters (--parameter options), and display the method
532
    return value and output parameters.
533

534
    For information on how to specify the instance using INSTANCENAME and the
535
    --key and --namespace options, invoke with --help-instancename.
536

537
    The method input parameters are specified using the --parameter option,
538
    which may be specified multiple times.
539

540
    Pywbemcli retrieves the class definition of the creation class of the
541
    instance from the server in order to verify that the specified input
542
    parameters are consistent with the parameter characteristics in the method
543
    definition.
544

545
    Use the 'class invokemethod' command to invoke CIM methods on CIM classes.
546

547
    Example:
548

549
      pywbemcli -n myconn instance invokemethod CIM_x.id='hi" methodx -p id=3
550
    """
551
    if options['help_instancename']:
16✔
552
        show_help_instancename()
16✔
553
        return
16✔
554
    validate_required_arg(instancename, 'INSTANCENAME')
16✔
555
    validate_required_arg(methodname, 'METHODNAME')
16✔
556
    # pylint: disable=line-too-long
557
    context.execute_cmd(lambda: cmd_instance_invokemethod(context, instancename, methodname, options))  # noqa: E501
16✔
558

559

560
@instance_group.command('query', cls=PywbemtoolsCommand,
16✔
561
                        options_metavar=CMD_OPTS_TXT)
562
@click.argument('query', type=str, required=True, metavar='QUERY-STRING')
16✔
563
@click.option('--ql', '--query-language', 'query_language', type=str,
16✔
564
              metavar='QUERY-LANGUAGE', default=DEFAULT_QUERY_LANGUAGE,
565
              help=u'The query language to be used with --query. '
566
              u'Default: {default}.'.
567
              format(default=DEFAULT_QUERY_LANGUAGE))
568
@add_options(namespace_option)
16✔
569
@add_options(summary_option)
16✔
570
@add_options(help_option)
16✔
571
@click.pass_obj
16✔
572
def instance_query(context, query, **options):
5✔
573
    """
574
    Execute a query on instances in a namespace.
575

576
    Execute the specified query (QUERY_STRING argument) in the specified CIM
577
    namespace (--namespace option), and display the returned instances. If no
578
    namespace was specified, the default namespace of the connection is used.
579

580
    In the output, the instances will formatted as defined by the
581
    --output-format general option.
582
    """
583
    context.execute_cmd(lambda: cmd_instance_query(context, query, options))
16✔
584

585

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

611
    Display the count of instances of each CIM class whose class name
612
    matches the specified wildcard expression (CLASSNAME-GLOB) in all CIM
613
    namespaces of the WBEM server, or in the specified namespaces
614
    (--namespace option).  This differs from instance enumerate, etc. in that
615
    it counts the instances specifically for the classname of each instance
616
    returned, not including subclasses.
617

618
    The CLASSNAME-GLOB argument is a wildcard expression that is matched on
619
    class names case insensitively.
620
    The special characters from Unix file name wildcarding are supported
621
    ('*' to match zero or more characters, '?' to match a single character,
622
    and '[]' to match character ranges). To avoid shell expansion of wildcard
623
    characters, the CLASSNAME-GLOB argument should be put in quotes.
624

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

628
    For example, "pywbem_*" returns classes whose name begins with "PyWBEM_",
629
    "pywbem_", etc. "*system*" returns classes whose names include the case
630
    insensitive string "system".
631

632
    If a CIMError occurs on any enumerate, it is flagged with a warning message
633
    and the search for instances continues.  If an Error exception occurs
634
    (ex. Connection error) the scan is terminated under the assumption
635
    that the server may have failed and the remaining items are shown as
636
    "Not scanned".
637

638
    This command can take a long time to execute since it potentially
639
    enumerates all instance names for all classes in all namespaces.
640
    """
641
    context.execute_cmd(lambda: cmd_instance_count(context, classname, options))
16✔
642

643

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

678
    The shrub is a view of all of the instance association relationships for
679
    a defined INSTANCENAME showing the various components that are part of
680
    the association including Role, AssocClasse,ResultRole, And ResultClas
681

682
    The default view is a tree view from the INSTANCENAME to associated
683
    instances.
684

685
    Displays the shrub of association components for the association source
686
    instance defined by INSTANCENAME.
687

688
    For information on how to specify the instance using INSTANCENAME and the
689
    --key and --namespace options, invoke with --help-instancename.
690

691
    Normally the association information is displayed as a tree but it
692
    may also be displayed as a table or as one of the object formats (ex. MOF)
693
    of all instances that are part of the shrub if one of the cim object
694
    formats is selected with the global output_format parameter.
695

696
    Results are formatted as defined by the output format global option.
697
    """
698
    if options['help_instancename']:
16✔
699
        show_help_instancename()
16✔
700
        return
16✔
701
    validate_required_arg(instancename, 'INSTANCENAME')
16✔
702
    # pylint: disable=line-too-long
703
    context.execute_cmd(lambda: cmd_instance_shrub(context, instancename, options))  # noqa: E501
16✔
704

705

706
####################################################################
707
#
708
#  Common functions for cmd_instance processing
709
#
710
####################################################################
711

712
# Subject help used both in instance cmd group and in the help cmd
713

714
HELP_INSTANCENAME_MSG = """
16✔
715
An instance path is specified using the INSTANCENAME argument and optionally the
716
--key and --namespace options. It can be specified in three ways:
717

718
1. By specifying the instance path as an untyped WBEM URI in the INSTANCENAME
719
   argument. In this case, the keybindings of the instance are specified in the
720
   WBEM URI, and the --key option must not be used.
721

722
   String typed keybindings in WBEM URIs are using double quotes, so the
723
   processing of special characters by the shell (such as backslashes and
724
   quotes) needs to be considered.
725

726
   The CIM namespace of the instance can be specified in the WBEM URI, or using
727
   the --namespace option, or otherwise the default namespace of the connection
728
   will be used.
729

730
   If present, the scheme and host components in the WBEM URI will be ignored.
731

732
   Examples (for a shell such as 'bash'):
733

734
     cimv2/test:TST_Person.FirstName=\\"Albert\\",LastName=\\"Einstein\\"
735
     TST_Foo.ID=42 --namespace cimv2/test
736
     TST_Foo.ID=42                     # default namespace of connection is used
737
     TST_Foo.IntegerKey=42
738
     TST_Foo.BooleanKey=true
739
     TST_Foo.StringKey=\\"text\\"        # shell processes escapes
740
     'TST_Foo.StringKey="text"'        # shell processes outer squotes
741
     'TST_Foo.StringKey="42"'          # shell processes outer squotes
742
     'TST_Foo.StringKey="true"'        # shell processes outer squotes
743
     "TST_Foo.StringKey=\\"it's\\""      # shell proc. outer dquotes and escapes
744
     'TST_Foo.StringKey="1.75\\""'      # shell processes outer squotes
745
     'TST_Foo.StringKey="a b"'         # shell processes outer squotes
746
     'CIM_SubProfile.Main="CIM_RegisteredProfile.InstanceID=\\"acme.1\\"",
747
       Sub="CIM_RegisteredProfile.InstanceID=\\"acme.2\\""'
748

749
2. By specifying the class path of the creation class of the instance as an
750
   untyped WBEM URI in the INSTANCENAME argument and by using the --key option
751
   to specify the keybindings of the instance.
752

753
   This approach reduces the use of double quotes compared to the first
754
   approach and eliminates it for the most common cases, but the processing of
755
   special characters by the shell still needs to be considered.
756

757
   The --key option can be specified multiple times, once for each key of the
758
   instance name. The argument of the --key option has a NAME=VALUE format,
759
   where NAME is the name of the key property and VALUE is its value. The
760
   string/numeric/boolean type needed for creating a keybinding is determined
761
   automatically from VALUE. Valid integer numbers are interpreted as a numeric
762
   type, the strings "true" and "false" in any lexical case are interpreted as
763
   a boolean type, and anything else is interpreted as a string type. Starting
764
   and ending VALUE with double quotes forces interpretation as a string type;
765
   in that case double quotes and backslashes inside of the double quotes need
766
   to be backslash-escaped. This is useful for strings that have a numeric
767
   value, or the string values "true" or "false".
768

769
   The CIM namespace of the instance can be specified in the WBEM URI, or using
770
   the --namespace option, or otherwise the default namespace of the connection
771
   will be used.
772

773
   If present, the scheme and host components in the WBEM URI will be ignored.
774

775
   Examples (for a shell such as 'bash'):
776

777
     cimv2/test:TST_Person --key FirstName=Albert --key LastName=Einstein
778
     TST_Foo --namespace cimv2/test --key ID=42
779
     TST_Foo --key ID=42               # default namespace of connection is used
780
     TST_Foo --key IntegerKey=42
781
     TST_Foo --key BooleanKey=true
782
     TST_Foo --key StringKey=text
783
     TST_Foo --key StringKey=\\"42\\"    # shell processes escapes
784
     TST_Foo --key StringKey=\\"true\\"  # shell processes escapes
785
     TST_Foo --key "StringKey=it's"    # shell processes outer dquotes
786
     TST_Foo --key 'StringKey=1.75"'   # shell processes outer squotes
787
     TST_Foo --key "StringKey=a b"     # shell processes outer dquotes
788
     TST_Foo --key StringKey="a b"     # shell processes outer dquotes
789
     TST_Foo --key StringKey=a\\ b      # shell processes escapes
790
     CIM_SubProfile --key Main='CIM_RegisteredProfile.InstanceID="acme.1"'
791
       --key Sub='CIM_RegisteredProfile.InstanceID="acme.2"'
792

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

799
   The CIM namespace of the instance can be specified in the WBEM URI, or using
800
   the --namespace option, or otherwise the default namespace of the connection
801
   will be used.
802

803
   If present, the scheme and host components in the WBEM URI will be ignored.
804

805
   Example command:
806

807
     $ pywbemcli instance get cimv2/test:TST_Person.?
808
     Pick Instance name to process
809
     0: cimv2/test:TST_Person.FirstName="Albert",LastName="Einstein"
810
     1: cimv2/test:TST_Person.FirstName="Marie",LastName="Curie"
811
     Input integer between 0 and 1 or Ctrl-C to exit selection: _
812
"""
813

814

815
def show_help_instancename():
16✔
816
    """
817
    Show the help message on how to specify an instance using INSTANCENAME
818
    and the --key and --namespace options.
819
    """
820
    # Note: This help text has a fixed width since it is too complex to
821
    # dynamically render it to a given width.
822

823
    click.echo(HELP_INSTANCENAME_MSG)
16✔
824

825

826
def get_instancename(context, instancename, options, default_all_ns=False):
16✔
827
    """
828
    Common function to construct a CIMInstanceName object from the
829
    INSTANCENAME argument and the --key and --namespace options specified
830
    in the command line.
831

832
    The keybindings of the returned CIM instance path(s) must be specified in
833
    exactly one of these ways:
834

835
    * If the keybindings component in the instance name string is "?"
836
      (e.g. "CIM_Foo.?"), the instances of that class are listed and the user
837
      is prompted to pick instance name. If multiple namespaces are specified
838
      in the "--namespaces" option the instances in all requested namespaces
839
      are listed for the user to pick one.
840

841
    * If the "key" option is non-empty, the so specified key values are used as
842
      keybindings for the returned instance path, and the instancename string
843
      is interpreted as a class WBEM URI.
844

845
    * If the instance name string specifies keybindings, these keybindings
846
      are used to define the instance name to return.
847

848
    The namespace of the returned CIM instance path must be specified in
849
    exactly one of these ways:
850

851
    * If the instance name string specifies a namespace, it is used.
852

853
    * If the "--namespace" option is non-empty, it is used. If the "--namespace"
854
      option is a list, the request is to return instance names in any of the
855
      namespaces.
856

857
    * Otherwise, the default namespace of the connection in the context is used.
858

859
    Parameters:
860

861
      context (:class:`'~pywbemtools._context_obj.ContextObj`):
862
        The Click context object.
863

864
      instancename (:term:`string`):
865
        The INSTANCENAME argument from the command line.
866

867
      options (dict):
868
        Command-specific options from the command line (including "-key" and
869
        "--namespace" if specified).
870

871
      default_all_ns (:class:`py:bool`)
872
        If True, the default is to return all namespaces.  Otherwise the
873
        default is to return None.
874

875
    Returns:
876

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

881
    Raises:
882

883
      ClickException: Various reasons.
884
    """
885
    conn = context.pywbem_server.conn
16✔
886

887
    def validate_namespace_option(class_path):
16✔
888
        """Validate either namespace in instance or --namespace but not both"""
889
        if class_path.namespace:
16✔
890
            if options['namespace']:
16✔
891
                raise click.ClickException(
16✔
892
                    "Using --namespace option: {} conflicts with specifying "
893
                    "namespace in INSTANCENAME: {}".format(options['namespace'],
894
                                                           instancename))
895

896
    # If option is a tuple, expand option to get list of all namespaces
897
    # defined. Option may be multiple uses of the option and/or comma-separated
898
    # string for any option value
899
    if isinstance(options['namespace'], tuple):
16✔
900
        ns_names = get_namespaces(context, options['namespace'],
16✔
901
                                  default_all_ns=default_all_ns)
902
    else:
903
        ns_names = options['namespace']
16✔
904

905
    # Process the 3 exclusive cmd option (".?", --key option, instance name )
906
    if instancename.endswith(".?"):
16✔
907
        if options['key']:
16✔
908
            raise click.ClickException(
16✔
909
                "Using the --key option conflicts with specifying a "
910
                "wildcard keybinding in INSTANCENAME: {}".
911
                format(instancename))
912

913
        class_uri = instancename[:-2]
16✔
914
        try:
16✔
915
            class_path = CIMClassName.from_wbem_uri(class_uri)
16✔
916
        except ValueError as exc:
16✔
917
            raise click.ClickException(str(exc))
16✔
918

919
        validate_namespace_option(class_path)
16✔
920

921
        try:
16✔
922
            # User picks one instance.  returned instance path includes
923
            # namespace.
924
            instance_path = pick_instance(
16✔
925
                context, class_path.classname, ns_names)
926
            # Reset the namespace in instance name if multiple namespaces
927
            if instance_path:
16✔
928
                if ns_names:
16✔
929
                    instance_path.namespace = None
16✔
930
        except ValueError as exc:
16✔
931
            raise click.ClickException(str(exc))
×
932

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

971
            kb_strs.append("{}={}".format(key, kb_value))
16✔
972

973
        # We perform an extra verification that instance name was a class
974
        # path to get a more understandable error message if it is not,
975
        # compared to leaving that to CIMInstanceName.from_wbem_uri().
976
        try:
16✔
977
            CIMClassName.from_wbem_uri(instancename)
16✔
978
        except ValueError as exc:
16✔
979
            raise click.ClickException(str(exc))
16✔
980

981
        instancename_kb = "{}.{}".format(instancename, ','.join(kb_strs))
16✔
982

983
        try:
16✔
984
            instance_path = CIMInstanceName.from_wbem_uri(instancename_kb)
16✔
985
            validate_namespace_option(instance_path)
16✔
986
        except ValueError as exc:
16✔
987
            raise click.ClickException(str(exc))
16✔
988

989
    else:  # else for not options['key']] or ".?", i.e. full key in inst path
990
        try:
16✔
991
            instance_path = CIMInstanceName.from_wbem_uri(instancename)
16✔
992
            validate_namespace_option(instance_path)
16✔
993
        except ValueError as exc:
16✔
994
            raise click.ClickException(str(exc))
16✔
995

996
    if instance_path is None:
16✔
997
        raise click.ClickException(
16✔
998
            "No instance paths found for instancename {0}".format(instancename))
999

1000
    # Set namespace into path if ns_names not set
1001
    if not instance_path.namespace:
16✔
1002
        if not ns_names:
16✔
1003
            instance_path.namespace = options.get('namespace') or \
16✔
1004
                conn.default_namespace
1005
        if isinstance(ns_names, six.string_types):
16✔
1006
            instance_path.namespace = ns_names
16✔
1007

1008
    return instance_path
16✔
1009

1010

1011
####################################################################
1012
#
1013
#  cmd_instance_<action> processors
1014
#
1015
####################################################################
1016

1017

1018
def cmd_instance_get(context, instancename, options):
16✔
1019
    """
1020
    Get and display an instance of a CIM Class.
1021

1022
    Gets the instance defined by instancename argument in the namespaces defined
1023
    and displays in output format defined.  If multiple namespaces are defined
1024
    this method may get multiple instances.
1025

1026
    If the wildcard key is used (CLASSNAME.?), pywbemcli presents a list of
1027
    instances to the console from which one can be picked to get from the
1028
    server and display.
1029
    """
1030
    conn = context.pywbem_server.conn
16✔
1031
    output_fmt = validate_output_format(context.output_format, ['CIM', 'TABLE'])
16✔
1032

1033
    # Returns list of namespaces from namespace option
1034
    instancepath = get_instancename(context, instancename, options)
16✔
1035

1036
    property_list = resolve_propertylist(options['propertylist'])
16✔
1037

1038
    results = ResultsHandler(context, options, output_fmt, "instance",
16✔
1039
                             instancepath, instpath=instancepath,
1040
                             property_list=property_list)
1041

1042
    for ns in results:
16✔
1043
        try:
16✔
1044
            instancepath.namespace = ns
16✔
1045
            results.add(conn.GetInstance(
16✔
1046
                instancepath,
1047
                LocalOnly=options['local_only'],
1048
                IncludeQualifiers=options['include_qualifiers'],
1049
                IncludeClassOrigin=options['include_classorigin'],
1050
                PropertyList=property_list))
1051

1052
        except CIMError as ce:
16✔
1053
            # Process error and continue or generate exception
1054
            results.handle_exception(ns, ce)
16✔
1055
            continue
16✔
1056

1057
        except Error as er:
16✔
1058
            raise pywbem_error_exception(er)
16✔
1059

1060
    results.display()
16✔
1061

1062

1063
def cmd_instance_delete(context, instancename, options):
16✔
1064
    """
1065
        If option interactive is set, get instances of the class defined
1066
        by instance name and allow the user to select the instance to
1067
        delete. This method allows only a single namespace.
1068

1069
        Otherwise attempt to delete the instance defined by instancename
1070
    """
1071
    conn = context.pywbem_server.conn
16✔
1072

1073
    instancepath = get_instancename(context, instancename, options)
16✔
1074

1075
    try:
16✔
1076
        conn.DeleteInstance(instancepath)
16✔
1077

1078
        if context.verbose:
16✔
1079
            context.spinner_stop()
16✔
1080
            click.echo('Deleted instance {}'.format(instancepath))
16✔
1081

1082
    except Error as er:
16✔
1083
        raise pywbem_error_exception(er)
16✔
1084

1085

1086
def cmd_instance_create(context, classname, options):
16✔
1087
    """
1088
       Create an instance and submit to wbemserver.
1089
       If successful, this operation returns the new instance name. Otherwise
1090
       it raises an exception
1091
    """
1092
    conn = context.pywbem_server.conn
16✔
1093
    ns = options['namespace'] or conn.default_namespace
16✔
1094
    try:
16✔
1095
        class_ = conn.GetClass(
16✔
1096
            classname, namespace=ns, LocalOnly=False)
1097
    except CIMError as ce:
16✔
1098
        if ce.status_code == CIM_ERR_NOT_FOUND:
16✔
1099
            raise click.ClickException(
16✔
1100
                'CIMClass: "{}" does not exist in namespace "{}" in WEB '
1101
                'server: {}.'.
1102
                format(classname, ns, conn))
1103
        raise pywbem_error_exception(ce)
16✔
1104

1105
    except Error as er:
16✔
1106
        raise pywbem_error_exception(er)
16✔
1107

1108
    properties = options['property']
16✔
1109

1110
    # properties is a tuple of name,value pairs
1111
    new_inst = create_ciminstance(class_, properties)
16✔
1112

1113
    if options['verify']:
16✔
1114
        context.spinner_stop()
16✔
1115
        click.echo(new_inst.tomof())
16✔
1116
        if not verify_operation("Execute CreateInstance", msg=True):
16✔
1117
            return
16✔
1118
    try:
16✔
1119
        name = conn.CreateInstance(new_inst, namespace=ns)
16✔
1120

1121
        context.spinner_stop()
16✔
1122
        click.echo('{}'.format(name))
16✔
1123
    except Error as er:
×
1124
        raise click.ClickException(
×
1125
            'Server Error creating instance in namespace {}. Exception: '
1126
            '{}: {}'.
1127
            format(ns, er.__class__.__name__, er))
1128

1129

1130
def cmd_instance_modify(context, instancename, options):
16✔
1131
    """
1132
    Build an instance defined by the options and submit to wbemserver
1133
    as a ModifyInstance method.
1134

1135
    This method allows only a single namespace.
1136

1137
    In order to make a correct instance, this method first gets the
1138
    corresponding class and uses that as the template for creating the intance.
1139
    The class provides property names, types, array flags, etc. to assure
1140
    that the instance is correctly built.
1141

1142
    If successful, this operation returns nothing.
1143
    """
1144
    conn = context.pywbem_server.conn
16✔
1145
    instancepath = get_instancename(context, instancename, options)
16✔
1146

1147
    ns = options['namespace'] or conn.default_namespace
16✔
1148

1149
    try:
16✔
1150
        class_ = conn.GetClass(
16✔
1151
            instancepath.classname, namespace=ns, LocalOnly=False)
1152
    except CIMError as ce:
16✔
1153
        if ce.status_code == CIM_ERR_NOT_FOUND:
16✔
1154
            raise click.ClickException(
16✔
1155
                'CIMClass: {!r} does not exist in WEB server: {}'
1156
                .format(instancepath.classname, conn.url))
1157

1158
        raise pywbem_error_exception(ce)
16✔
1159
    except Error as er:
16✔
1160
        raise pywbem_error_exception(er)
16✔
1161

1162
    property_list = resolve_propertylist(options['propertylist'])
16✔
1163

1164
    # properties is a tuple of name,value pairs
1165
    modified_inst = create_ciminstance(class_, options['property'])
16✔
1166

1167
    modified_inst.path = instancepath
16✔
1168

1169
    if options['verify']:
16✔
1170
        context.spinner_stop()
16✔
1171
        click.echo(modified_inst.tomof())
16✔
1172
        if not verify_operation("Execute ModifyInstance", msg=True):
16✔
1173
            return
16✔
1174

1175
    try:
16✔
1176
        conn.ModifyInstance(modified_inst, PropertyList=property_list)
16✔
1177
        if context.verbose:
16✔
1178
            context.spinner_stop()
16✔
1179
            click.echo('Modified instance {}'.format(instancepath))
16✔
1180
    except Error as er:
16✔
1181
        raise click.ClickException('Server Error modifying instance {} '
16✔
1182
                                   'in namespace {}. Exception: {}: {}'.format
1183
                                   (instancepath, ns, er.__class__.__name__,
1184
                                    er))
1185

1186

1187
def cmd_instance_invokemethod(context, instancename, methodname,
16✔
1188
                              options):
1189
    """
1190
    Create an instance and submit to wbemserver
1191
    """
1192
    instancepath = get_instancename(context, instancename, options)
16✔
1193

1194
    try:
16✔
1195
        process_invokemethod(context, instancepath, methodname,
16✔
1196
                             options['namespace'], options['parameter'])
1197
    except Error as er:
16✔
1198
        raise pywbem_error_exception(er)
16✔
1199

1200

1201
def get_filterquerylanguage(options):
16✔
1202
    """
1203
    Get the filterquery language based on what is in the filterquery option
1204
    and the filterquerylanguage options.
1205
    If filterquery exists but filterquerylanguage does not, use DMTF as
1206
    the filter query language.
1207
    if filterquery does not exist but filterquerylanguage does, just return it
1208
    """
1209
    if options['filter_query']:
16✔
1210
        fql = options['filter_query_language'] or 'DMTF:FQL'
16✔
1211
    else:
1212
        fql = options['filter_query_language']
16✔
1213
    return fql
16✔
1214

1215

1216
def enumerate_instances(conn, context, options, namespace, classname,
16✔
1217
                        property_list, return_original_err=False):
1218
    """
1219
    Internal method.
1220

1221
    Issue the command to enumerate either the paths or instances for the
1222
    namespace defined by the namespace parameter.
1223

1224
    If the return_original_err is True, reraise any  Error or CIMError
1225
    exception.
1226
    """
1227
    try:
16✔
1228
        if options['names_only']:
16✔
1229
            return conn.PyWbemcliEnumerateInstancePaths(
16✔
1230
                ClassName=classname,
1231
                namespace=namespace,
1232
                FilterQuery=options['filter_query'],
1233
                FilterQueryLanguage=get_filterquerylanguage(options),
1234
                MaxObjectCount=context.pywbem_server.pull_max_cnt)
1235

1236
        return conn.PyWbemcliEnumerateInstances(
16✔
1237
            ClassName=classname,
1238
            namespace=namespace,
1239
            LocalOnly=options['local_only'],
1240
            IncludeQualifiers=options['include_qualifiers'],
1241
            DeepInheritance=options['deep_inheritance'],
1242
            IncludeClassOrigin=options['include_classorigin'],
1243
            FilterQuery=options['filter_query'],
1244
            FilterQueryLanguage=get_filterquerylanguage(options),
1245
            MaxObjectCount=context.pywbem_server.pull_max_cnt,
1246
            PropertyList=property_list)
1247

1248
    except Error as er:
16✔
1249
        # Return either the original exception or the ClickException.
1250
        if return_original_err:
16✔
1251
            raise er
16✔
UNCOV
1252
        raise pywbem_error_exception(er)
×
1253

1254
    # Exception from Enumerate and the FilterQuery.  This exception would
1255
    # apply  to all namespaces so just terminate.
1256
    except ValueError as ve:
16✔
1257
        raise click.ClickException(
16✔
1258
            'Instance enumerate failed because FilterQuery not allowed with '
1259
            'traditional EnumerateInstance. --use-pull: {}. Exception: {}: {}'
1260
            .format(context.pywbem_server.use_pull, ve.__class__.__name__, ve))
1261

1262

1263
def cmd_instance_enumerate(context, classname, options):
16✔
1264
    """
1265
    Enumerate CIM instances or CIM instance names
1266

1267
    Returns:
1268
        list of objects retrieved.
1269

1270
    """
1271
    conn = context.pywbem_server.conn
16✔
1272
    output_fmt = validate_output_format(context.output_format, ['CIM', 'TABLE'])
16✔
1273

1274
    property_list = resolve_propertylist(options['propertylist'])
16✔
1275

1276
    results = ResultsHandler(context, options, output_fmt, "class", classname,
16✔
1277
                             property_list=property_list)
1278

1279
    for ns in results:
16✔
1280
        try:
16✔
1281
            results.add(enumerate_instances(conn, context, options, ns,
16✔
1282
                                            classname, property_list,
1283
                                            return_original_err=True))
1284

1285
        except CIMError as ce:
16✔
1286
            # Process error and continue or generate exception
1287
            results.handle_exception(ns, ce)
16✔
1288
            continue
16✔
1289

1290
        except Error as er:
16✔
1291
            raise pywbem_error_exception(er)
16✔
1292

1293
    results.display()
16✔
1294

1295

1296
def cmd_instance_references(context, instancename, options):
16✔
1297
    """Execute the references request operation to get references for
1298
       the classname defined. This may be either interactive or if the
1299
       interactive option is set or use the instancename directly.
1300

1301
       This method allows multiple namespaces
1302

1303
       If the interactive option is selected, the instancename MUST BE
1304
       a classname.
1305
    """
1306
    conn = context.pywbem_server.conn
16✔
1307
    output_fmt = validate_output_format(context.output_format, ['CIM', 'TABLE'])
16✔
1308

1309
    instancepath = get_instancename(context, instancename, options)
16✔
1310

1311
    property_list = resolve_propertylist(options['propertylist'])
16✔
1312

1313
    results = ResultsHandler(context, options, output_fmt, "instance",
16✔
1314
                             instancepath, instpath=instancepath,
1315
                             property_list=property_list)
1316

1317
    for ns in results:
16✔
1318
        try:
16✔
1319
            instancepath.namespace = ns
16✔
1320
            if options['names_only']:
16✔
1321
                results.add(conn.PyWbemcliReferenceInstancePaths(
16✔
1322
                    instancepath,
1323
                    ResultClass=options['result_class'],
1324
                    Role=options['role'],
1325
                    FilterQuery=options['filter_query'],
1326
                    FilterQueryLanguage=get_filterquerylanguage(options),
1327
                    MaxObjectCount=context.pywbem_server.pull_max_cnt))
1328
            else:
1329
                results.add(conn.PyWbemcliReferenceInstances(
16✔
1330
                    instancepath,
1331
                    ResultClass=options['result_class'],
1332
                    Role=options['role'],
1333
                    IncludeQualifiers=options['include_qualifiers'],
1334
                    IncludeClassOrigin=options['include_classorigin'],
1335
                    FilterQuery=options['filter_query'],
1336
                    FilterQueryLanguage=get_filterquerylanguage(options),
1337
                    MaxObjectCount=context.pywbem_server.pull_max_cnt,
1338
                    PropertyList=property_list))
1339

1340
        except CIMError as ce:
16✔
1341
            # Process error and continue or generate exception
1342
            results.handle_exception(ns, ce)
16✔
UNCOV
1343
            continue
×
1344

1345
        except Error as er:
16✔
1346
            raise pywbem_error_exception(er)
16✔
1347

1348
        except ValueError as ve:
16✔
1349
            raise click.ClickException(
16✔
1350
                'Instance references failed because FilterQuery not allowed '
1351
                'with traditional References. --use-pull {}. Exception: {}: {}'
1352
                .format(context.pywbem_server.use_pull, ve.__class__.__name__,
1353
                        ve))
1354
    results.display()
16✔
1355

1356

1357
def cmd_instance_associators(context, instancename, options):
16✔
1358
    """
1359
    Execute the references request operation to get references for
1360
    the classname defined.
1361

1362
    This method allows multiple namespaces.
1363
    """
1364
    conn = context.pywbem_server.conn
16✔
1365
    output_fmt = validate_output_format(context.output_format, ['CIM', 'TABLE'])
16✔
1366

1367
    instancepath = get_instancename(context, instancename, options)
16✔
1368

1369
    property_list = resolve_propertylist(options['propertylist'])
16✔
1370

1371
    results = ResultsHandler(context, options, output_fmt, "class",
16✔
1372
                             instancepath, instpath=instancepath,
1373
                             property_list=property_list)
1374

1375
    for ns in results:
16✔
1376
        try:
16✔
1377
            instancepath.namespace = ns
16✔
1378
            if options['names_only']:
16✔
1379
                results.add(conn.PyWbemcliAssociatorInstancePaths(
16✔
1380
                    instancepath,
1381
                    AssocClass=options['assoc_class'],
1382
                    Role=options['role'],
1383
                    ResultClass=options['result_class'],
1384
                    ResultRole=options['result_role'],
1385
                    FilterQuery=options['filter_query'],
1386
                    FilterQueryLanguage=get_filterquerylanguage(options),
1387
                    MaxObjectCount=context.pywbem_server.pull_max_cnt))
1388
            else:
1389
                results.add(conn.PyWbemcliAssociatorInstances(
16✔
1390
                    instancepath,
1391
                    AssocClass=options['assoc_class'],
1392
                    Role=options['role'],
1393
                    ResultClass=options['result_class'],
1394
                    ResultRole=options['result_role'],
1395
                    IncludeQualifiers=options['include_qualifiers'],
1396
                    IncludeClassOrigin=options['include_classorigin'],
1397
                    FilterQuery=options['filter_query'],
1398
                    FilterQueryLanguage=get_filterquerylanguage(options),
1399
                    MaxObjectCount=context.pywbem_server.pull_max_cnt,
1400
                    PropertyList=property_list))
1401

1402
        except CIMError as ce:
16✔
1403
            # Process error and continue or generate exception
1404
            results.handle_exception(ns, ce)
16✔
1405
            continue
16✔
1406

1407
        except Error as er:
16✔
1408
            raise pywbem_error_exception(er)
16✔
1409

1410
        except ValueError as ve:
16✔
1411
            raise click.ClickException(
16✔
1412
                'Instance associators failed because FilterQuery not allowed '
1413
                'with traditional Associators. --use-pull: {}. Exception: {}: '
1414
                '{}'
1415
                .format(context.pywbem_server.use_pull, ve.__class__.__name__,
1416
                        ve))
1417

1418
    results.display()
16✔
1419

1420

1421
def cmd_instance_count(context, classname, options):
16✔
1422
    """
1423
    Get the number of instances of each class in the namespace
1424
    """
1425
    conn = context.pywbem_server.conn
16✔
1426
    output_fmt = validate_output_format(context.output_format, 'TABLE')
16✔
1427

1428
    class_ignore_list = []
16✔
1429
    for cls in options['ignore_class']:
16✔
1430
        if ',' in cls:
16✔
1431
            class_ignore_list.extend(cls.split(','))
16✔
1432
        else:
1433
            class_ignore_list.append(cls)
16✔
1434

1435
    # Differs from class find because the classname is optional.
1436
    # If None, select all
1437
    if classname is None:
16✔
1438
        classname = '*'
16✔
1439

1440
    # Create list of namespaces from the option or from all namespaces
1441
    # default_rtn forces
1442
    ns_names = get_namespaces(context, options['namespace'],
16✔
1443
                              default_all_ns=True)
1444

1445
    ns_cln_tuples = []  # a list of tuples of namespace, classname
16✔
1446
    for namespace in ns_names:
16✔
1447
        # Get all classes in Namespace
1448
        try:
16✔
1449
            # Set cmd options that are required for this command.
1450
            # 1. Always use deep_inheritance
1451
            # 2. Set namespace to each namespace in loop
1452
            options['deep_inheritance'] = True
16✔
1453
            options['names_only'] = True
16✔
1454

1455
            classnames = enumerate_classes_filtered(context, namespace, None,
16✔
1456
                                                    options)
1457
        except Error as er:
16✔
1458
            raise pywbem_error_exception(er)
16✔
1459

1460
        if classnames:
16✔
1461
            classlist = filter_namelist(classname, classnames, ignore_case=True)
16✔
1462
            cl_tup = [(namespace, cln) for cln in classlist]
16✔
1463
            ns_cln_tuples.extend(cl_tup)
16✔
1464

1465
    # Sort since normal output for this command is  namespace, classname
1466
    # alphabetic order.
1467
    ns_cln_tuples.sort(key=lambda tup: (tup[0], tup[1]))
16✔
1468

1469
    display_data = []
16✔
1470
    error = 0
16✔
1471
    # Scan all of the class/namespace tuples to get count of instances
1472
    # of each class.
1473
    for tup in ns_cln_tuples:
16✔
1474
        ns = tup[0]
16✔
1475
        cln = tup[1]
16✔
1476
        if cln in class_ignore_list:
16✔
1477
            display_tuple = (ns, cln, "ignored")
16✔
1478
            display_data.append(display_tuple)
16✔
1479
            continue
16✔
1480
        # If an error has occurred, just display the remaining items with
1481
        # Not scanned msg.
1482
        if error:
16✔
1483
            display_tuple = (ns, cln, "Not scanned")
×
1484
            display_data.append(display_tuple)
×
1485
            continue
×
1486
        # Try block allows issues where enumerate does not properly execute
1487
        # The totals may be wrong but at least it gets what it can.
1488
        # This accounts for issues with some servers where there
1489
        # are providers that return errors from the enumerate.
1490
        inst_names = None
16✔
1491
        try:
16✔
1492
            inst_names = conn.EnumerateInstanceNames(cln, namespace=ns)
16✔
1493
        except CIMError as ce:
×
1494
            warning_msg("Server CIMError {0} with namepace={1}, class={2}. "
×
1495
                        "Continuing scan."
1496
                        .format(ce.status_code_name, ns, cln))
1497
            display_tuple = (ns, cln, "CIMError {}".format(ce.status_code_name))
×
1498
            display_data.append(display_tuple)
×
1499
            continue
×
1500
        # Error exception caused termination of the connection. Add this
1501
        # item to the display with Server Fail message instead of count
1502
        except Error as er:
×
1503
            error = er
×
1504
            warning_msg("Server Error {0} with namepace={1}, class={2}. "
×
1505
                        "Terminating scan."
1506
                        .format(er, ns, cln))
1507
            display_tuple = (ns, cln, "Server Fail")
×
1508
            display_data.append(display_tuple)
×
1509
            continue
×
1510

1511
        # Sum the number of instances with the defined classname.
1512
        # this counts only classes with that specific classname and not
1513
        # subclasses
1514
        if inst_names:
16✔
1515
            count = sum(1 for inst_name in inst_names
16✔
1516
                        if (inst_name.classname.lower() == cln.lower()))
1517
            # Display only non-zero elements
1518
            if count:
16✔
1519
                display_tuple = (ns, cln, count)
16✔
1520
                display_data.append(display_tuple)
16✔
1521

1522
    # Post scan processing
1523
    # If sort set, re-sort by count size
1524
    if options['sort']:
16✔
1525
        display_data.sort(key=lambda x: x[2])
16✔
1526

1527
    headers = ['Namespace', 'Class', 'count']
16✔
1528
    rows = []
16✔
1529
    if display_data:
16✔
1530
        for item in display_data:
16✔
1531
            rows.append([item[0], item[1], item[2]])
16✔
1532

1533
    context.spinner_stop()
16✔
1534
    click.echo(format_table(rows, headers,
16✔
1535
                            title='Count of instances per class',
1536
                            table_format=output_fmt))
1537
    if error:
16✔
1538
        raise click.ClickException(
×
1539
            "Server Error {0} at namespace={1}, class:{2}. Scan incomplete."
1540
            .format(error, ns, cln))
1541

1542

1543
def cmd_instance_query(context, query, options):
16✔
1544
    """
1545
    Execute the query defined by the inputs.
1546

1547
    This commands creates a Query request based on the command input variables
1548
    and options and outputs the result in either CIM or TABLE format.
1549
    """
1550
    conn = context.pywbem_server.conn
16✔
1551
    output_fmt = validate_output_format(context.output_format, ['CIM', 'TABLE'])
16✔
1552

1553
    try:
16✔
1554
        results = conn.PyWbemcliQueryInstances(
16✔
1555
            options['query_language'],
1556
            query,
1557
            namespace=options['namespace'],
1558
            MaxObjectCount=context.pywbem_server.pull_max_cnt)
1559

1560
        display_cim_objects(
×
1561
            context, results, output_fmt, summary=options['summary'])
1562

1563
    except Error as er:
16✔
1564
        raise pywbem_error_exception(er)
16✔
1565

1566

1567
def cmd_instance_shrub(context, instancename, options):
16✔
1568
    """
1569
    Display the association information defined by instancename as a tree
1570
    showing the various steps to get through the roles, references, etc. to
1571
    return the names of associated instances.
1572
    """
1573
    conn = context.pywbem_server.conn
16✔
1574

1575
    # ns_names = get_namespaces(context, options['namespace'], default_rtn=None)
1576
    instancepath = get_instancename(context, instancename, options)
16✔
1577

1578
    try:
16✔
1579

1580
        # Collect the data for the shrub
1581
        shrub = AssociationShrub(conn, instancepath,
16✔
1582
                                 Role=options['role'],
1583
                                 AssocClass=options['assoc_class'],
1584
                                 ResultRole=options['result_role'],
1585
                                 ResultClass=options['result_class'],
1586
                                 verbose=context.verbose,
1587
                                 fullpath=options['fullpath'])
1588

1589
        # display the shrub
1590
        context.spinner_stop()
16✔
1591
        shrub.display_shrub(context.output_format, options['summary'])
16✔
1592
    except Error as er:
×
1593
        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