cli.py 127 KB
Newer Older
Iustin Pop's avatar
Iustin Pop committed
1
#
Iustin Pop's avatar
Iustin Pop committed
2
3
#

4
# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Google Inc.
Iustin Pop's avatar
Iustin Pop committed
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.


"""Module dealing with command line parsing"""


import sys
import textwrap
import os.path
28
import time
Iustin Pop's avatar
Iustin Pop committed
29
import logging
30
import errno
31
import itertools
32
import shlex
33
from cStringIO import StringIO
Iustin Pop's avatar
Iustin Pop committed
34
35
36
37

from ganeti import utils
from ganeti import errors
from ganeti import constants
38
from ganeti import opcodes
Iustin Pop's avatar
Iustin Pop committed
39
from ganeti import luxi
40
from ganeti import ssconf
41
from ganeti import rpc
42
from ganeti import ssh
43
from ganeti import compat
44
from ganeti import netutils
45
from ganeti import qlang
46
from ganeti import objects
47
from ganeti import pathutils
Iustin Pop's avatar
Iustin Pop committed
48

49
from optparse import (OptionParser, TitledHelpFormatter,
Iustin Pop's avatar
Iustin Pop committed
50
                      Option, OptionValueError)
Iustin Pop's avatar
Iustin Pop committed
51

52

53
54
__all__ = [
  # Command line options
55
  "ABSOLUTE_OPT",
56
  "ADD_UIDS_OPT",
57
  "ADD_RESERVED_IPS_OPT",
58
  "ALLOCATABLE_OPT",
59
  "ALLOC_POLICY_OPT",
60
  "ALL_OPT",
61
  "ALLOW_FAILOVER_OPT",
62
  "AUTO_PROMOTE_OPT",
63
  "AUTO_REPLACE_OPT",
64
  "BACKEND_OPT",
65
  "BLK_OS_OPT",
66
  "CAPAB_MASTER_OPT",
Iustin Pop's avatar
Iustin Pop committed
67
  "CAPAB_VM_OPT",
68
  "CLEANUP_OPT",
Michael Hanselmann's avatar
Michael Hanselmann committed
69
  "CLUSTER_DOMAIN_SECRET_OPT",
70
  "CONFIRM_OPT",
71
  "CP_SIZE_OPT",
72
  "DEBUG_OPT",
73
  "DEBUG_SIMERR_OPT",
74
  "DISKIDX_OPT",
75
  "DISK_OPT",
76
  "DISK_PARAMS_OPT",
77
  "DISK_TEMPLATE_OPT",
78
  "DRAINED_OPT",
79
  "DRY_RUN_OPT",
80
  "DRBD_HELPER_OPT",
81
  "DST_NODE_OPT",
82
  "EARLY_RELEASE_OPT",
83
  "ENABLED_HV_OPT",
84
  "ENABLED_DISK_TEMPLATES_OPT",
85
  "ERROR_CODES_OPT",
86
  "FAILURE_ONLY_OPT",
87
  "FIELDS_OPT",
88
  "FILESTORE_DIR_OPT",
89
  "FILESTORE_DRIVER_OPT",
90
  "FORCE_FILTER_OPT",
91
92
  "FORCE_OPT",
  "FORCE_VARIANT_OPT",
93
94
  "GATEWAY_OPT",
  "GATEWAY6_OPT",
95
  "GLOBAL_FILEDIR_OPT",
96
  "HID_OS_OPT",
97
  "GLOBAL_SHARED_FILEDIR_OPT",
98
  "HVLIST_OPT",
99
  "HVOPTS_OPT",
100
  "HYPERVISOR_OPT",
101
  "IALLOCATOR_OPT",
102
  "DEFAULT_IALLOCATOR_OPT",
103
  "IDENTIFY_DEFAULTS_OPT",
104
  "IGNORE_CONSIST_OPT",
105
  "IGNORE_ERRORS_OPT",
106
  "IGNORE_FAILURES_OPT",
107
  "IGNORE_OFFLINE_OPT",
108
  "IGNORE_REMOVE_FAILURES_OPT",
109
  "IGNORE_SECONDARIES_OPT",
110
  "IGNORE_SIZE_OPT",
Michael Hanselmann's avatar
Michael Hanselmann committed
111
  "INTERVAL_OPT",
112
  "MAC_PREFIX_OPT",
113
  "MAINTAIN_NODE_HEALTH_OPT",
114
  "MASTER_NETDEV_OPT",
115
  "MASTER_NETMASK_OPT",
116
  "MC_OPT",
117
  "MIGRATION_MODE_OPT",
Iustin Pop's avatar
Iustin Pop committed
118
  "NET_OPT",
119
120
  "NETWORK_OPT",
  "NETWORK6_OPT",
121
  "NEW_CLUSTER_CERT_OPT",
Michael Hanselmann's avatar
Michael Hanselmann committed
122
  "NEW_CLUSTER_DOMAIN_SECRET_OPT",
123
  "NEW_CONFD_HMAC_KEY_OPT",
124
  "NEW_RAPI_CERT_OPT",
125
  "NEW_PRIMARY_OPT",
126
  "NEW_SECONDARY_OPT",
127
  "NEW_SPICE_CERT_OPT",
128
  "NIC_PARAMS_OPT",
129
  "NOCONFLICTSCHECK_OPT",
130
  "NODE_FORCE_JOIN_OPT",
131
  "NODE_LIST_OPT",
132
  "NODE_PLACEMENT_OPT",
133
  "NODEGROUP_OPT",
134
  "NODE_PARAMS_OPT",
135
  "NODE_POWERED_OPT",
136
  "NODRBD_STORAGE_OPT",
137
  "NOHDR_OPT",
138
  "NOIPCHECK_OPT",
139
  "NO_INSTALL_OPT",
140
  "NONAMECHECK_OPT",
141
  "NOLVM_STORAGE_OPT",
142
  "NOMODIFY_ETCHOSTS_OPT",
143
  "NOMODIFY_SSH_SETUP_OPT",
Iustin Pop's avatar
Iustin Pop committed
144
  "NONICS_OPT",
Iustin Pop's avatar
Iustin Pop committed
145
  "NONLIVE_OPT",
146
  "NONPLUS1_OPT",
147
  "NORUNTIME_CHGS_OPT",
148
  "NOSHUTDOWN_OPT",
149
  "NOSTART_OPT",
150
  "NOSSH_KEYCHECK_OPT",
151
  "NOVOTING_OPT",
152
  "NO_REMEMBER_OPT",
153
  "NWSYNC_OPT",
154
155
  "OFFLINE_INST_OPT",
  "ONLINE_INST_OPT",
156
  "ON_PRIMARY_OPT",
157
  "ON_SECONDARY_OPT",
158
  "OFFLINE_OPT",
159
  "OSPARAMS_OPT",
Iustin Pop's avatar
Iustin Pop committed
160
  "OS_OPT",
Iustin Pop's avatar
Iustin Pop committed
161
  "OS_SIZE_OPT",
162
  "OOB_TIMEOUT_OPT",
163
  "POWER_DELAY_OPT",
164
  "PREALLOC_WIPE_DISKS_OPT",
165
  "PRIMARY_IP_VERSION_OPT",
166
  "PRIMARY_ONLY_OPT",
167
  "PRIORITY_OPT",
168
  "RAPI_CERT_OPT",
169
  "READD_OPT",
170
  "REASON_OPT",
171
  "REBOOT_TYPE_OPT",
172
  "REMOVE_INSTANCE_OPT",
173
  "REMOVE_RESERVED_IPS_OPT",
174
  "REMOVE_UIDS_OPT",
175
  "RESERVED_LVS_OPT",
176
  "RUNTIME_MEM_OPT",
177
  "ROMAN_OPT",
178
  "SECONDARY_IP_OPT",
179
  "SECONDARY_ONLY_OPT",
180
  "SELECT_OS_OPT",
181
  "SEP_OPT",
182
  "SHOWCMD_OPT",
183
  "SHOW_MACHINE_OPT",
Guido Trotter's avatar
Guido Trotter committed
184
  "SHUTDOWN_TIMEOUT_OPT",
185
  "SINGLE_NODE_OPT",
186
187
188
189
190
  "SPECS_CPU_COUNT_OPT",
  "SPECS_DISK_COUNT_OPT",
  "SPECS_DISK_SIZE_OPT",
  "SPECS_MEM_SIZE_OPT",
  "SPECS_NIC_COUNT_OPT",
191
  "IPOLICY_DISK_TEMPLATES",
192
  "IPOLICY_VCPU_RATIO",
193
194
  "SPICE_CACERT_OPT",
  "SPICE_CERT_OPT",
195
196
  "SRC_DIR_OPT",
  "SRC_NODE_OPT",
197
  "SUBMIT_OPT",
198
  "STARTUP_PAUSED_OPT",
199
  "STATIC_OPT",
200
  "SYNC_OPT",
201
  "TAG_ADD_OPT",
202
  "TAG_SRC_OPT",
Guido Trotter's avatar
Guido Trotter committed
203
  "TIMEOUT_OPT",
204
  "TO_GROUP_OPT",
205
  "UIDPOOL_OPT",
206
  "USEUNITS_OPT",
207
  "USE_EXTERNAL_MIP_SCRIPT",
208
  "USE_REPL_NET_OPT",
209
  "VERBOSE_OPT",
Iustin Pop's avatar
Iustin Pop committed
210
  "VG_NAME_OPT",
211
  "WFSYNC_OPT",
212
  "YES_DOIT_OPT",
213
214
  "DISK_STATE_OPT",
  "HV_STATE_OPT",
215
  "IGNORE_IPOLICY_OPT",
216
  "INSTANCE_POLICY_OPTS",
217
  # Generic functions for CLI programs
218
  "ConfirmOperation",
219
  "CreateIPolicyFromOpts",
220
  "GenericMain",
Iustin Pop's avatar
Iustin Pop committed
221
  "GenericInstanceCreate",
222
223
  "GenericList",
  "GenericListFields",
224
225
226
227
228
  "GetClient",
  "GetOnlineNodes",
  "JobExecutor",
  "JobSubmittedException",
  "ParseTimespec",
229
  "RunWhileClusterStopped",
230
231
232
233
234
235
  "SubmitOpCode",
  "SubmitOrSend",
  "UsesRPC",
  # Formatting functions
  "ToStderr", "ToStdout",
  "FormatError",
236
  "FormatQueryResult",
237
  "FormatParamsDictInfo",
238
  "FormatPolicyInfo",
239
  "PrintGenericInfo",
240
241
242
  "GenerateTable",
  "AskUser",
  "FormatTimestamp",
243
  "FormatLogMessage",
244
245
246
247
248
249
250
  # Tags functions
  "ListTags",
  "AddTags",
  "RemoveTags",
  # command line options support infrastructure
  "ARGS_MANY_INSTANCES",
  "ARGS_MANY_NODES",
251
  "ARGS_MANY_GROUPS",
252
  "ARGS_MANY_NETWORKS",
253
254
255
  "ARGS_NONE",
  "ARGS_ONE_INSTANCE",
  "ARGS_ONE_NODE",
256
  "ARGS_ONE_GROUP",
257
  "ARGS_ONE_OS",
258
  "ARGS_ONE_NETWORK",
259
260
261
  "ArgChoice",
  "ArgCommand",
  "ArgFile",
262
  "ArgGroup",
263
264
265
  "ArgHost",
  "ArgInstance",
  "ArgJobId",
266
  "ArgNetwork",
267
  "ArgNode",
268
  "ArgOs",
269
  "ArgExtStorage",
270
271
272
273
274
275
276
  "ArgSuggest",
  "ArgUnknown",
  "OPT_COMPL_INST_ADD_NODES",
  "OPT_COMPL_MANY_NODES",
  "OPT_COMPL_ONE_IALLOCATOR",
  "OPT_COMPL_ONE_INSTANCE",
  "OPT_COMPL_ONE_NODE",
277
  "OPT_COMPL_ONE_NODEGROUP",
278
  "OPT_COMPL_ONE_NETWORK",
279
  "OPT_COMPL_ONE_OS",
280
  "OPT_COMPL_ONE_EXTSTORAGE",
281
282
  "cli_option",
  "SplitNodeOption",
Guido Trotter's avatar
Guido Trotter committed
283
  "CalculateOSNames",
284
  "ParseFields",
285
  "COMMON_CREATE_OPTS",
286
  ]
287

288
289
NO_PREFIX = "no_"
UN_PREFIX = "-"
290

291
292
293
294
295
296
297
298
299
300
301
302
#: Priorities (sorted)
_PRIORITY_NAMES = [
  ("low", constants.OP_PRIO_LOW),
  ("normal", constants.OP_PRIO_NORMAL),
  ("high", constants.OP_PRIO_HIGH),
  ]

#: Priority dictionary for easier lookup
# TODO: Replace this and _PRIORITY_NAMES with a single sorted dictionary once
# we migrate to Python 2.6
_PRIONAME_TO_VALUE = dict(_PRIORITY_NAMES)

303
304
305
306
307
# Query result status for clients
(QR_NORMAL,
 QR_UNKNOWN,
 QR_INCOMPLETE) = range(3)

308
309
310
#: Maximum batch size for ChooseJob
_CHOOSE_BATCH = 25

311

312
313
314
315
316
317
318
319
320
321
322
323
# constants used to create InstancePolicy dictionary
TISPECS_GROUP_TYPES = {
  constants.ISPECS_MIN: constants.VTYPE_INT,
  constants.ISPECS_MAX: constants.VTYPE_INT,
  }

TISPECS_CLUSTER_TYPES = {
  constants.ISPECS_MIN: constants.VTYPE_INT,
  constants.ISPECS_MAX: constants.VTYPE_INT,
  constants.ISPECS_STD: constants.VTYPE_INT,
  }

324
325
326
327
328
329
330
331
332
333
334
#: User-friendly names for query2 field types
_QFT_NAMES = {
  constants.QFT_UNKNOWN: "Unknown",
  constants.QFT_TEXT: "Text",
  constants.QFT_BOOL: "Boolean",
  constants.QFT_NUMBER: "Number",
  constants.QFT_UNIT: "Storage size",
  constants.QFT_TIMESTAMP: "Timestamp",
  constants.QFT_OTHER: "Custom",
  }

335

336
class _Argument:
337
  def __init__(self, min=0, max=None): # pylint: disable=W0622
338
339
340
341
342
343
344
345
346
347
348
349
350
351
    self.min = min
    self.max = max

  def __repr__(self):
    return ("<%s min=%s max=%s>" %
            (self.__class__.__name__, self.min, self.max))


class ArgSuggest(_Argument):
  """Suggesting argument.

  Value can be any of the ones passed to the constructor.

  """
352
  # pylint: disable=W0622
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
  def __init__(self, min=0, max=None, choices=None):
    _Argument.__init__(self, min=min, max=max)
    self.choices = choices

  def __repr__(self):
    return ("<%s min=%s max=%s choices=%r>" %
            (self.__class__.__name__, self.min, self.max, self.choices))


class ArgChoice(ArgSuggest):
  """Choice argument.

  Value can be any of the ones passed to the constructor. Like L{ArgSuggest},
  but value must be one of the choices.

  """


class ArgUnknown(_Argument):
  """Unknown argument to program (e.g. determined at runtime).

  """


class ArgInstance(_Argument):
  """Instances argument.

  """


class ArgNode(_Argument):
  """Node argument.

  """

388

389
390
391
392
393
class ArgNetwork(_Argument):
  """Network argument.

  """

394

395
396
397
398
399
400
class ArgGroup(_Argument):
  """Node group argument.

  """


401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
class ArgJobId(_Argument):
  """Job ID argument.

  """


class ArgFile(_Argument):
  """File path argument.

  """


class ArgCommand(_Argument):
  """Command argument.

  """


Michael Hanselmann's avatar
Michael Hanselmann committed
419
420
421
422
423
424
class ArgHost(_Argument):
  """Host argument.

  """


425
426
427
428
429
430
class ArgOs(_Argument):
  """OS argument.

  """


431
432
433
434
435
436
class ArgExtStorage(_Argument):
  """ExtStorage argument.

  """


437
438
ARGS_NONE = []
ARGS_MANY_INSTANCES = [ArgInstance()]
439
ARGS_MANY_NETWORKS = [ArgNetwork()]
440
ARGS_MANY_NODES = [ArgNode()]
441
ARGS_MANY_GROUPS = [ArgGroup()]
442
ARGS_ONE_INSTANCE = [ArgInstance(min=1, max=1)]
443
ARGS_ONE_NETWORK = [ArgNetwork(min=1, max=1)]
444
ARGS_ONE_NODE = [ArgNode(min=1, max=1)]
445
446
# TODO
ARGS_ONE_GROUP = [ArgGroup(min=1, max=1)]
447
ARGS_ONE_OS = [ArgOs(min=1, max=1)]
448
449


450
451
452
453
454
455
456
457
458
459
def _ExtractTagsObject(opts, args):
  """Extract the tag type object.

  Note that this function will modify its args parameter.

  """
  if not hasattr(opts, "tag_type"):
    raise errors.ProgrammerError("tag_type not passed to _ExtractTagsObject")
  kind = opts.tag_type
  if kind == constants.TAG_CLUSTER:
460
    retval = kind, None
461
462
  elif kind in (constants.TAG_NODEGROUP,
                constants.TAG_NODE,
463
                constants.TAG_NETWORK,
464
                constants.TAG_INSTANCE):
465
    if not args:
466
467
      raise errors.OpPrereqError("no arguments passed to the command",
                                 errors.ECODE_INVAL)
468
469
470
471
472
473
474
    name = args.pop(0)
    retval = kind, name
  else:
    raise errors.ProgrammerError("Unhandled tag type '%s'" % kind)
  return retval


475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
def _ExtendTags(opts, args):
  """Extend the args if a source file has been given.

  This function will extend the tags with the contents of the file
  passed in the 'tags_source' attribute of the opts parameter. A file
  named '-' will be replaced by stdin.

  """
  fname = opts.tags_source
  if fname is None:
    return
  if fname == "-":
    new_fh = sys.stdin
  else:
    new_fh = open(fname, "r")
  new_data = []
  try:
    # we don't use the nice 'new_data = [line.strip() for line in fh]'
    # because of python bug 1633941
    while True:
      line = new_fh.readline()
      if not line:
        break
      new_data.append(line.strip())
  finally:
    new_fh.close()
  args.extend(new_data)


504
505
506
507
508
509
510
511
512
513
def ListTags(opts, args):
  """List the tags on a given object.

  This is a generic implementation that knows how to deal with all
  three cases of tag objects (cluster, node, instance). The opts
  argument is expected to contain a tag_type field denoting what
  object type we work on.

  """
  kind, name = _ExtractTagsObject(opts, args)
514
  cl = GetClient(query=True)
Iustin Pop's avatar
Iustin Pop committed
515
  result = cl.QueryTags(kind, name)
516
517
518
  result = list(result)
  result.sort()
  for tag in result:
519
    ToStdout(tag)
520
521
522
523
524
525
526
527
528
529
530
531


def AddTags(opts, args):
  """Add tags on a given object.

  This is a generic implementation that knows how to deal with all
  three cases of tag objects (cluster, node, instance). The opts
  argument is expected to contain a tag_type field denoting what
  object type we work on.

  """
  kind, name = _ExtractTagsObject(opts, args)
532
  _ExtendTags(opts, args)
533
  if not args:
534
    raise errors.OpPrereqError("No tags to be added", errors.ECODE_INVAL)
Iustin Pop's avatar
Iustin Pop committed
535
  op = opcodes.OpTagsSet(kind=kind, name=name, tags=args)
536
  SubmitOrSend(op, opts)
537
538
539
540
541
542
543
544
545
546
547
548


def RemoveTags(opts, args):
  """Remove tags from a given object.

  This is a generic implementation that knows how to deal with all
  three cases of tag objects (cluster, node, instance). The opts
  argument is expected to contain a tag_type field denoting what
  object type we work on.

  """
  kind, name = _ExtractTagsObject(opts, args)
549
  _ExtendTags(opts, args)
550
  if not args:
551
    raise errors.OpPrereqError("No tags to be removed", errors.ECODE_INVAL)
Iustin Pop's avatar
Iustin Pop committed
552
  op = opcodes.OpTagsDel(kind=kind, name=name, tags=args)
553
  SubmitOrSend(op, opts)
554

Iustin Pop's avatar
Iustin Pop committed
555

556
def check_unit(option, opt, value): # pylint: disable=W0613
Iustin Pop's avatar
Iustin Pop committed
557
558
559
  """OptParsers custom converter for units.

  """
Iustin Pop's avatar
Iustin Pop committed
560
561
562
  try:
    return utils.ParseUnit(value)
  except errors.UnitParseError, err:
563
    raise OptionValueError("option %s: %s" % (opt, err))
Iustin Pop's avatar
Iustin Pop committed
564
565


566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
def _SplitKeyVal(opt, data):
  """Convert a KeyVal string into a dict.

  This function will convert a key=val[,...] string into a dict. Empty
  values will be converted specially: keys which have the prefix 'no_'
  will have the value=False and the prefix stripped, the others will
  have value=True.

  @type opt: string
  @param opt: a string holding the option name for which we process the
      data, used in building error messages
  @type data: string
  @param data: a string of the format key=val,key=val,...
  @rtype: dict
  @return: {key=val, key=val}
  @raises errors.ParameterError: if there are duplicate keys

  """
  kv_dict = {}
585
  if data:
586
    for elem in utils.UnescapeAndSplit(data, sep=","):
587
588
      if "=" in elem:
        key, val = elem.split("=", 1)
589
      else:
590
591
592
593
594
595
596
597
598
599
        if elem.startswith(NO_PREFIX):
          key, val = elem[len(NO_PREFIX):], False
        elif elem.startswith(UN_PREFIX):
          key, val = elem[len(UN_PREFIX):], None
        else:
          key, val = elem, True
      if key in kv_dict:
        raise errors.ParameterError("Duplicate key '%s' in option %s" %
                                    (key, opt))
      kv_dict[key] = val
600
601
602
  return kv_dict


603
def check_ident_key_val(option, opt, value):  # pylint: disable=W0613
604
605
606
607
  """Custom parser for ident:key=val,key=val options.

  This will store the parsed values as a tuple (ident, {key: val}). As such,
  multiple uses of this option via action=append is possible.
608
609
610

  """
  if ":" not in value:
Iustin Pop's avatar
Iustin Pop committed
611
    ident, rest = value, ""
612
613
  else:
    ident, rest = value.split(":", 1)
614
615
616
617
618
619

  if ident.startswith(NO_PREFIX):
    if rest:
      msg = "Cannot pass options when removing parameter groups: %s" % value
      raise errors.ParameterError(msg)
    retval = (ident[len(NO_PREFIX):], False)
620
621
622
  elif (ident.startswith(UN_PREFIX) and
        (len(ident) <= len(UN_PREFIX) or
         not ident[len(UN_PREFIX)][0].isdigit())):
623
624
625
626
627
    if rest:
      msg = "Cannot pass options when removing parameter groups: %s" % value
      raise errors.ParameterError(msg)
    retval = (ident[len(UN_PREFIX):], None)
  else:
628
629
630
631
632
    kv_dict = _SplitKeyVal(opt, rest)
    retval = (ident, kv_dict)
  return retval


633
def check_key_val(option, opt, value):  # pylint: disable=W0613
634
635
636
  """Custom parser class for key=val,key=val options.

  This will store the parsed values as a dict {key: val}.
637
638
639
640
641

  """
  return _SplitKeyVal(opt, value)


642
def check_bool(option, opt, value): # pylint: disable=W0613
Iustin Pop's avatar
Iustin Pop committed
643
644
645
646
647
648
649
650
651
652
653
654
655
656
  """Custom parser for yes/no options.

  This will store the parsed value as either True or False.

  """
  value = value.lower()
  if value == constants.VALUE_FALSE or value == "no":
    return False
  elif value == constants.VALUE_TRUE or value == "yes":
    return True
  else:
    raise errors.ParameterError("Invalid boolean value '%s'" % value)


Iustin Pop's avatar
Iustin Pop committed
657
658
659
660
661
662
663
664
665
666
667
668
def check_list(option, opt, value): # pylint: disable=W0613
  """Custom parser for comma-separated lists.

  """
  # we have to make this explicit check since "".split(",") is [""],
  # not an empty list :(
  if not value:
    return []
  else:
    return utils.UnescapeAndSplit(value)


669
670
671
672
673
674
675
676
677
678
679
680
def check_maybefloat(option, opt, value): # pylint: disable=W0613
  """Custom parser for float numbers which might be also defaults.

  """
  value = value.lower()

  if value == constants.VALUE_DEFAULT:
    return value
  else:
    return float(value)


681
682
683
684
685
686
# completion_suggestion is normally a list. Using numeric values not evaluating
# to False for dynamic completion.
(OPT_COMPL_MANY_NODES,
 OPT_COMPL_ONE_NODE,
 OPT_COMPL_ONE_INSTANCE,
 OPT_COMPL_ONE_OS,
687
 OPT_COMPL_ONE_EXTSTORAGE,
688
 OPT_COMPL_ONE_IALLOCATOR,
689
 OPT_COMPL_ONE_NETWORK,
690
 OPT_COMPL_INST_ADD_NODES,
691
 OPT_COMPL_ONE_NODEGROUP) = range(100, 109)
692

693
OPT_COMPL_ALL = compat.UniqueFrozenset([
694
695
696
697
  OPT_COMPL_MANY_NODES,
  OPT_COMPL_ONE_NODE,
  OPT_COMPL_ONE_INSTANCE,
  OPT_COMPL_ONE_OS,
698
  OPT_COMPL_ONE_EXTSTORAGE,
699
  OPT_COMPL_ONE_IALLOCATOR,
700
  OPT_COMPL_ONE_NETWORK,
701
  OPT_COMPL_INST_ADD_NODES,
702
  OPT_COMPL_ONE_NODEGROUP,
703
704
705
  ])


706
707
class CliOption(Option):
  """Custom option class for optparse.
708
709

  """
710
711
712
  ATTRS = Option.ATTRS + [
    "completion_suggest",
    ]
713
714
715
716
  TYPES = Option.TYPES + (
    "identkeyval",
    "keyval",
    "unit",
Iustin Pop's avatar
Iustin Pop committed
717
    "bool",
Iustin Pop's avatar
Iustin Pop committed
718
    "list",
719
    "maybefloat",
720
721
722
    )
  TYPE_CHECKER = Option.TYPE_CHECKER.copy()
  TYPE_CHECKER["identkeyval"] = check_ident_key_val
723
  TYPE_CHECKER["keyval"] = check_key_val
724
  TYPE_CHECKER["unit"] = check_unit
Iustin Pop's avatar
Iustin Pop committed
725
  TYPE_CHECKER["bool"] = check_bool
Iustin Pop's avatar
Iustin Pop committed
726
  TYPE_CHECKER["list"] = check_list
727
  TYPE_CHECKER["maybefloat"] = check_maybefloat
728
729


Iustin Pop's avatar
Iustin Pop committed
730
731
732
733
# optparse.py sets make_option, so we do it for our own option class, too
cli_option = CliOption


734
735
_YORNO = "yes|no"

736
737
DEBUG_OPT = cli_option("-d", "--debug", default=0, action="count",
                       help="Increase debugging level")
738
739
740
741
742
743
744
745
746
747
748

NOHDR_OPT = cli_option("--no-headers", default=False,
                       action="store_true", dest="no_headers",
                       help="Don't display column headers")

SEP_OPT = cli_option("--separator", default=None,
                     action="store", dest="separator",
                     help=("Separator between output fields"
                           " (defaults to one space)"))

USEUNITS_OPT = cli_option("--units", default=None,
Iustin Pop's avatar
Iustin Pop committed
749
                          dest="units", choices=("h", "m", "g", "t"),
750
                          help="Specify units for output (one of h/m/g/t)")
751
752
753
754
755
756
757
758
759
760
761

FIELDS_OPT = cli_option("-o", "--output", dest="output", action="store",
                        type="string", metavar="FIELDS",
                        help="Comma separated list of output fields")

FORCE_OPT = cli_option("-f", "--force", dest="force", action="store_true",
                       default=False, help="Force the operation")

CONFIRM_OPT = cli_option("--yes", dest="confirm", action="store_true",
                         default=False, help="Do not require confirmation")

762
763
764
765
766
IGNORE_OFFLINE_OPT = cli_option("--ignore-offline", dest="ignore_offline",
                                  action="store_true", default=False,
                                  help=("Ignore offline nodes and do as much"
                                        " as possible"))

767
768
769
770
TAG_ADD_OPT = cli_option("--tags", dest="tags",
                         default=None, help="Comma-separated list of instance"
                                            " tags")

771
772
773
774
775
776
777
778
779
780
781
782
783
TAG_SRC_OPT = cli_option("--from", dest="tags_source",
                         default=None, help="File with tag names")

SUBMIT_OPT = cli_option("--submit", dest="submit_only",
                        default=False, action="store_true",
                        help=("Submit the job and return the job ID, but"
                              " don't wait for the job to finish"))

SYNC_OPT = cli_option("--sync", dest="do_locking",
                      default=False, action="store_true",
                      help=("Grab locks while doing the queries"
                            " in order to ensure more consistent results"))

784
785
786
DRY_RUN_OPT = cli_option("--dry-run", default=False,
                         action="store_true",
                         help=("Do not execute the operation, just run the"
Michael Hanselmann's avatar
Michael Hanselmann committed
787
                               " check steps and verify if it could be"
788
                               " executed"))
789

790
791
792
793
VERBOSE_OPT = cli_option("-v", "--verbose", default=False,
                         action="store_true",
                         help="Increase the verbosity of the operation")

794
795
796
797
798
DEBUG_SIMERR_OPT = cli_option("--debug-simulate-errors", default=False,
                              action="store_true", dest="simulate_errors",
                              help="Debugging option that makes the operation"
                              " treat most runtime checks as failed")

799
800
801
802
NWSYNC_OPT = cli_option("--no-wait-for-sync", dest="wait_for_sync",
                        default=True, action="store_false",
                        help="Don't wait for sync (DANGEROUS!)")

803
804
805
806
WFSYNC_OPT = cli_option("--wait-for-sync", dest="wait_for_sync",
                        default=False, action="store_true",
                        help="Wait for disks to sync")

807
808
809
810
811
812
813
814
ONLINE_INST_OPT = cli_option("--online", dest="online_inst",
                             action="store_true", default=False,
                             help="Enable offline instance")

OFFLINE_INST_OPT = cli_option("--offline", dest="offline_inst",
                              action="store_true", default=False,
                              help="Disable down instance")

815
DISK_TEMPLATE_OPT = cli_option("-t", "--disk-template", dest="disk_template",
816
817
                               help=("Custom disk setup (%s)" %
                                     utils.CommaJoin(constants.DISK_TEMPLATES)),
818
819
820
                               default=None, metavar="TEMPL",
                               choices=list(constants.DISK_TEMPLATES))

Iustin Pop's avatar
Iustin Pop committed
821
822
823
824
NONICS_OPT = cli_option("--no-nics", default=False, action="store_true",
                        help="Do not create any network cards for"
                        " the instance")

825
826
827
828
829
FILESTORE_DIR_OPT = cli_option("--file-storage-dir", dest="file_storage_dir",
                               help="Relative path under default cluster-wide"
                               " file storage dir to store file-based disks",
                               default=None, metavar="<DIR>")

830
831
832
833
834
FILESTORE_DRIVER_OPT = cli_option("--file-driver", dest="file_driver",
                                  help="Driver to use for image files",
                                  default="loop", metavar="<DRIVER>",
                                  choices=list(constants.FILE_DRIVER))

835
836
837
838
839
840
IALLOCATOR_OPT = cli_option("-I", "--iallocator", metavar="<NAME>",
                            help="Select nodes for the instance automatically"
                            " using the <NAME> iallocator plugin",
                            default=None, type="string",
                            completion_suggest=OPT_COMPL_ONE_IALLOCATOR)

841
DEFAULT_IALLOCATOR_OPT = cli_option("-I", "--default-iallocator",
Iustin Pop's avatar
Iustin Pop committed
842
843
844
845
846
                                    metavar="<NAME>",
                                    help="Set the default instance"
                                    " allocator plugin",
                                    default=None, type="string",
                                    completion_suggest=OPT_COMPL_ONE_IALLOCATOR)
847

Iustin Pop's avatar
Iustin Pop committed
848
849
850
851
OS_OPT = cli_option("-o", "--os-type", dest="os", help="What OS to run",
                    metavar="<os>",
                    completion_suggest=OPT_COMPL_ONE_OS)

852
OSPARAMS_OPT = cli_option("-O", "--os-parameters", dest="osparams",
Iustin Pop's avatar
Iustin Pop committed
853
854
                          type="keyval", default={},
                          help="OS parameters")
855

856
857
858
859
FORCE_VARIANT_OPT = cli_option("--force-variant", dest="force_variant",
                               action="store_true", default=False,
                               help="Force an unknown variant")

860
861
862
863
864
NO_INSTALL_OPT = cli_option("--no-install", dest="no_install",
                            action="store_true", default=False,
                            help="Do not install the OS (will"
                            " enable no-start)")

865
866
867
868
869
NORUNTIME_CHGS_OPT = cli_option("--no-runtime-changes",
                                dest="allow_runtime_chgs",
                                default=True, action="store_false",
                                help="Don't allow runtime changes")

870
871
872
BACKEND_OPT = cli_option("-B", "--backend-parameters", dest="beparams",
                         type="keyval", default={},
                         help="Backend parameters")
873

Michael Hanselmann's avatar
Michael Hanselmann committed
874
875
876
HVOPTS_OPT = cli_option("-H", "--hypervisor-parameters", type="keyval",
                        default={}, dest="hvparams",
                        help="Hypervisor parameters")
877

878
879
880
881
882
DISK_PARAMS_OPT = cli_option("-D", "--disk-parameters", dest="diskparams",
                             help="Disk template parameters, in the format"
                             " template:option=value,option=value,...",
                             type="identkeyval", action="append", default=[])

883
884
SPECS_MEM_SIZE_OPT = cli_option("--specs-mem-size", dest="ispecs_mem_size",
                                 type="keyval", default={},
885
886
887
                                 help="Memory size specs: list of key=value,"
                                " where key is one of min, max, std"
                                 " (in MB or using a unit)")
888
889
890

SPECS_CPU_COUNT_OPT = cli_option("--specs-cpu-count", dest="ispecs_cpu_count",
                                 type="keyval", default={},
891
892
                                 help="CPU count specs: list of key=value,"
                                 " where key is one of min, max, std")
893
894
895
896

SPECS_DISK_COUNT_OPT = cli_option("--specs-disk-count",
                                  dest="ispecs_disk_count",
                                  type="keyval", default={},
897
898
                                  help="Disk count specs: list of key=value,"
                                  " where key is one of min, max, std")
899
900
901

SPECS_DISK_SIZE_OPT = cli_option("--specs-disk-size", dest="ispecs_disk_size",
                                 type="keyval", default={},
902
                                 help="Disk size specs: list of key=value,"
Iustin Pop's avatar
Iustin Pop committed
903
                                 " where key is one of min, max, std"
904
                                 " (in MB or using a unit)")
905
906
907

SPECS_NIC_COUNT_OPT = cli_option("--specs-nic-count", dest="ispecs_nic_count",
                                 type="keyval", default={},
908
909
                                 help="NIC count specs: list of key=value,"
                                 " where key is one of min, max, std")
910

911
IPOLICY_DISK_TEMPLATES = cli_option("--ipolicy-disk-templates",
Iustin Pop's avatar
Iustin Pop committed
912
913
914
915
                                    dest="ipolicy_disk_templates",
                                    type="list", default=None,
                                    help="Comma-separated list of"
                                    " enabled disk templates")
916

917
918
IPOLICY_VCPU_RATIO = cli_option("--ipolicy-vcpu-ratio",
                                 dest="ipolicy_vcpu_ratio",
919
                                 type="maybefloat", default=None,
920
921
                                 help="The maximum allowed vcpu-to-cpu ratio")

922
923
IPOLICY_SPINDLE_RATIO = cli_option("--ipolicy-spindle-ratio",
                                   dest="ipolicy_spindle_ratio",
924
                                   type="maybefloat", default=None,
925
926
927
                                   help=("The maximum allowed instances to"
                                         " spindle ratio"))

928
929
930
931
HYPERVISOR_OPT = cli_option("-H", "--hypervisor-parameters", dest="hypervisor",
                            help="Hypervisor and hypervisor options, in the"
                            " format hypervisor:option=value,option=value,...",
                            default=None, type="identkeyval")
932
933
934
935
936

HVLIST_OPT = cli_option("-H", "--hypervisor-parameters", dest="hvparams",
                        help="Hypervisor and hypervisor options, in the"
                        " format hypervisor:option=value,option=value,...",
                        default=[], action="append", type="identkeyval")
937

938
939
940
941
942
NOIPCHECK_OPT = cli_option("--no-ip-check", dest="ip_check", default=True,
                           action="store_false",
                           help="Don't check that the instance's IP"
                           " is alive")

943
944
945
946
947
NONAMECHECK_OPT = cli_option("--no-name-check", dest="name_check",
                             default=True, action="store_false",
                             help="Don't check that the instance's name"
                             " is resolvable")

Iustin Pop's avatar
Iustin Pop committed
948
949
950
NET_OPT = cli_option("--net",
                     help="NIC parameters", default=[],
                     dest="nics", action="append", type="identkeyval")
951
952
953

DISK_OPT = cli_option("--disk", help="Disk parameters", default=[],
                      dest="disks", action="append", type="identkeyval")
954

955
956
957
958
959
DISKIDX_OPT = cli_option("--disks", dest="disks", default=None,
                         help="Comma-separated list of disks"
                         " indices to act on (e.g. 0,2) (optional,"
                         " defaults to all disks)")

Iustin Pop's avatar
Iustin Pop committed
960
961
962
963
964
OS_SIZE_OPT = cli_option("-s", "--os-size", dest="sd_size",
                         help="Enforces a single-disk configuration using the"
                         " given disk size, in MiB unless a suffix is used",
                         default=None, type="unit", metavar="<size>")

965
966
967
968
969
970
IGNORE_CONSIST_OPT = cli_option("--ignore-consistency",
                                dest="ignore_consistency",
                                action="store_true", default=False,
                                help="Ignore the consistency of the disks on"
                                " the secondary")

971
972
973
974
975
976
ALLOW_FAILOVER_OPT = cli_option("--allow-failover",
                                dest="allow_failover",
                                action="store_true", default=False,
                                help="If migration is not possible fallback to"
                                     " failover")

Iustin Pop's avatar
Iustin Pop committed
977
978
979
980
981
982
NONLIVE_OPT = cli_option("--non-live", dest="live",
                         default=True, action="store_false",
                         help="Do a non-live migration (this usually means"
                         " freeze the instance, save the state, transfer and"
                         " only then resume running on the secondary node)")

983
MIGRATION_MODE_OPT = cli_option("--migration-mode", dest="migration_mode",
984
                                default=None,
985
986
                                choices=list(constants.HT_MIGRATION_MODES),
                                help="Override default migration mode (choose"
987
988
                                " either live or non-live")

989
990
991
992
993
NODE_PLACEMENT_OPT = cli_option("-n", "--node", dest="node",
                                help="Target node and optional secondary node",
                                metavar="<pnode>[:<snode>]",
                                completion_suggest=OPT_COMPL_INST_ADD_NODES)

994
995
996
997
998
NODE_LIST_OPT = cli_option("-n", "--node", dest="nodes", default=[],
                           action="append", metavar="<node>",
                           help="Use only this node (can be used multiple"
                           " times, if not given defaults to all nodes)",
                           completion_suggest=OPT_COMPL_ONE_NODE)
999

1000
1001
NODEGROUP_OPT_NAME = "--node-group"
NODEGROUP_OPT = cli_option("-g", NODEGROUP_OPT_NAME,
1002
1003
1004
1005
1006
1007
                           dest="nodegroup",
                           help="Node group (name or uuid)",
                           metavar="<nodegroup>",
                           default=None, type="string",
                           completion_suggest=OPT_COMPL_ONE_NODEGROUP)

1008
1009
1010
SINGLE_NODE_OPT = cli_option("-n", "--node", dest="node", help="Target node",
                             metavar="<node>",
                             completion_suggest=OPT_COMPL_ONE_NODE)
1011

1012
1013
1014
1015
NOSTART_OPT = cli_option("--no-start", dest="start", default=True,
                         action="store_false",
                         help="Don't start the instance after creation")

1016
1017
1018
1019
SHOWCMD_OPT = cli_option("--show-cmd", dest="show_command",
                         action="store_true", default=False,
                         help="Show command instead of executing it")

1020
1021
1022
1023
1024
1025
1026
1027
1028
CLEANUP_OPT = cli_option("--cleanup", dest="cleanup",
                         default=False, action="store_true",
                         help="Instead of performing the migration, try to"
                         " recover from a failed cleanup. This is safe"
                         " to run even if the instance is healthy, but it"
                         " will create extra replication traffic and "
                         " disrupt briefly the replication (like during the"
                         " migration")

1029
1030
1031
1032
STATIC_OPT = cli_option("-s", "--static", dest="static",
                        action="store_true", default=False,
                        help="Only show configuration data, not runtime data")

1033
1034
1035
1036
1037
ALL_OPT = cli_option("--all", dest="show_all",
                     default=False, action="store_true",
                     help="Show info on all instances on the cluster."
                     " This can take a long time to run, use wisely")

1038
1039
1040
1041
SELECT_OS_OPT = cli_option("--select-os", dest="select_os",
                           action="store_true", default=False,
                           help="Interactive OS reinstall, lists available"
                           " OS templates for selection")
1042

1043
1044
1045
1046
1047
1048
IGNORE_FAILURES_OPT = cli_option("--ignore-failures", dest="ignore_failures",
                                 action="store_true", default=False,
                                 help="Remove the instance from the cluster"
                                 " configuration even if there are failures"
                                 " during the removal process")

1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
IGNORE_REMOVE_FAILURES_OPT = cli_option("--ignore-remove-failures",
                                        dest="ignore_remove_failures",
                                        action="store_true", default=False,
                                        help="Remove the instance from the"
                                        " cluster configuration even if there"
                                        " are failures during the removal"
                                        " process")

REMOVE_INSTANCE_OPT = cli_option("--remove-instance", dest="remove_instance",
                                 action="store_true", default=False,
                                 help="Remove the instance from the cluster")

1061
1062
1063
1064
1065
DST_NODE_OPT = cli_option("-n", "--target-node", dest="dst_node",
                               help="Specifies the new node for the instance",
                               metavar="NODE", default=None,
                               completion_suggest=OPT_COMPL_ONE_NODE)

1066
1067
1068
1069
1070
NEW_SECONDARY_OPT = cli_option("-n", "--new-secondary", dest="dst_node",
                               help="Specifies the new secondary node",
                               metavar="NODE", default=None,
                               completion_suggest=OPT_COMPL_ONE_NODE)

1071
1072
1073
1074
1075
NEW_PRIMARY_OPT = cli_option("--new-primary", dest="new_primary_node",
                             help="Specifies the new primary node",
                             metavar="<node>", default=None,
                             completion_suggest=OPT_COMPL_ONE_NODE)

1076
1077
1078
ON_PRIMARY_OPT = cli_option("-p", "--on-primary", dest="on_primary",
                            default=False, action="store_true",
                            help="Replace the disk(s) on the primary"
1079
1080
1081
                                 " node (applies only to internally mirrored"
                                 " disk templates, e.g. %s)" %
                                 utils.CommaJoin(constants.DTS_INT_MIRROR))
1082
1083
1084
1085

ON_SECONDARY_OPT = cli_option("-s", "--on-secondary", dest="on_secondary",
                              default=False, action="store_true",
                              help="Replace the disk(s) on the secondary"
1086
1087
1088
                                   " node (applies only to internally mirrored"
                                   " disk templates, e.g. %s)" %
                                   utils.CommaJoin(constants.DTS_INT_MIRROR))
1089

1090
1091
1092
1093
1094
AUTO_PROMOTE_OPT = cli_option("--auto-promote", dest="auto_promote",
                              default=False, action="store_true",
                              help="Lock all nodes and auto-promote as needed"
                              " to MC status")

1095
1096
1097
AUTO_REPLACE_OPT = cli_option("-a", "--auto", dest="auto",
                              default=False, action="store_true",
                              help="Automatically replace faulty disks"
1098
1099
1100
                                   " (applies only to internally mirrored"
                                   " disk templates, e.g. %s)" %
                                   utils.CommaJoin(constants.DTS_INT_MIRROR))