Fix punctuation in an error message
[ganeti-local] / lib / cli.py
index f59668b..c4a647d 100644 (file)
@@ -104,6 +104,7 @@ __all__ = [
   "NEW_RAPI_CERT_OPT",
   "NEW_SECONDARY_OPT",
   "NIC_PARAMS_OPT",
+  "NODE_FORCE_JOIN_OPT",
   "NODE_LIST_OPT",
   "NODE_PLACEMENT_OPT",
   "NODEGROUP_OPT",
@@ -337,7 +338,8 @@ ARGS_MANY_NODES = [ArgNode()]
 ARGS_MANY_GROUPS = [ArgGroup()]
 ARGS_ONE_INSTANCE = [ArgInstance(min=1, max=1)]
 ARGS_ONE_NODE = [ArgNode(min=1, max=1)]
-ARGS_ONE_GROUP = [ArgInstance(min=1, max=1)]
+# TODO
+ARGS_ONE_GROUP = [ArgGroup(min=1, max=1)]
 ARGS_ONE_OS = [ArgOs(min=1, max=1)]
 
 
@@ -422,7 +424,7 @@ def AddTags(opts, args):
   _ExtendTags(opts, args)
   if not args:
     raise errors.OpPrereqError("No tags to be added")
-  op = opcodes.OpAddTags(kind=kind, name=name, tags=args)
+  op = opcodes.OpTagsSet(kind=kind, name=name, tags=args)
   SubmitOpCode(op, opts=opts)
 
 
@@ -885,6 +887,9 @@ NOSSH_KEYCHECK_OPT = cli_option("--no-ssh-key-check", dest="ssh_key_check",
                                 default=True, action="store_false",
                                 help="Disable SSH key fingerprint checking")
 
+NODE_FORCE_JOIN_OPT = cli_option("--force-join", dest="force_join",
+                                 default=False, action="store_true",
+                                 help="Force the joining of a node")
 
 MC_OPT = cli_option("-C", "--master-candidate", dest="master_candidate",
                     type="bool", default=None, metavar=_YORNO,
@@ -892,11 +897,14 @@ MC_OPT = cli_option("-C", "--master-candidate", dest="master_candidate",
 
 OFFLINE_OPT = cli_option("-O", "--offline", dest="offline", metavar=_YORNO,
                          type="bool", default=None,
-                         help="Set the offline flag on the node")
+                         help=("Set the offline flag on the node"
+                               " (cluster does not communicate with offline"
+                               " nodes)"))
 
 DRAINED_OPT = cli_option("-D", "--drained", dest="drained", metavar=_YORNO,
                          type="bool", default=None,
-                         help="Set the drained flag on the node")
+                         help=("Set the drained flag on the node"
+                               " (excluded from allocation operations)"))
 
 CAPAB_MASTER_OPT = cli_option("--master-capable", dest="master_capable",
                     type="bool", default=None, metavar=_YORNO,
@@ -929,8 +937,9 @@ CP_SIZE_OPT = cli_option("-C", "--candidate-pool-size", default=None,
                          help="Set the candidate pool size")
 
 VG_NAME_OPT = cli_option("--vg-name", dest="vg_name",
-                         help="Enables LVM and specifies the volume group"
-                         " name (cluster-wide) for disk allocation [xenvg]",
+                         help=("Enables LVM and specifies the volume group"
+                               " name (cluster-wide) for disk allocation"
+                               " [%s]" % constants.DEFAULT_VG),
                          metavar="VG", default=None)
 
 YES_DOIT_OPT = cli_option("--yes-do-it", dest="yes_do_it",
@@ -1910,8 +1919,8 @@ def GenericMain(commands, override=None, aliases=None):
     for key, val in override.iteritems():
       setattr(options, key, val)
 
-  utils.SetupLogging(constants.LOG_COMMANDS, debug=options.debug,
-                     stderr_logging=True, program=binary)
+  utils.SetupLogging(constants.LOG_COMMANDS, binary, debug=options.debug,
+                     stderr_logging=True)
 
   if old_cmdline:
     logging.info("run with arguments '%s'", old_cmdline)
@@ -1925,6 +1934,11 @@ def GenericMain(commands, override=None, aliases=None):
     result, err_msg = FormatError(err)
     logging.exception("Error during command processing")
     ToStderr(err_msg)
+  except KeyboardInterrupt:
+    result = constants.EXIT_FAILURE
+    ToStderr("Aborted. Note that if the operation created any jobs, they"
+             " might have been submitted and"
+             " will continue to run in the background.")
 
   return result
 
@@ -2368,17 +2382,23 @@ class _QueryColumnFormatter:
   """Callable class for formatting fields of a query.
 
   """
-  def __init__(self, fn, status_fn):
+  def __init__(self, fn, status_fn, verbose):
     """Initializes this class.
 
     @type fn: callable
     @param fn: Formatting function
     @type status_fn: callable
     @param status_fn: Function to report fields' status
+    @type verbose: boolean
+    @param verbose: whether to use verbose field descriptions or not
 
     """
     self._fn = fn
     self._status_fn = status_fn
+    if verbose:
+      self._desc_index = 0
+    else:
+      self._desc_index = 1
 
   def __call__(self, data):
     """Returns a field's string representation.
@@ -2389,29 +2409,20 @@ class _QueryColumnFormatter:
     # Report status
     self._status_fn(status)
 
-    if status == constants.QRFS_NORMAL:
+    if status == constants.RS_NORMAL:
       return self._fn(value)
 
     assert value is None, \
            "Found value %r for abnormal status %s" % (value, status)
 
-    if status == constants.QRFS_UNKNOWN:
-      return "(unknown)"
-
-    if status == constants.QRFS_NODATA:
-      return "(nodata)"
-
-    if status == constants.QRFS_UNAVAIL:
-      return "(unavail)"
-
-    if status == constants.QRFS_OFFLINE:
-      return "(offline)"
+    if status in constants.RSS_DESCRIPTION:
+      return constants.RSS_DESCRIPTION[status][self._desc_index]
 
     raise NotImplementedError("Unknown status %s" % status)
 
 
 def FormatQueryResult(result, unit=None, format_override=None, separator=None,
-                      header=False):
+                      header=False, verbose=False):
   """Formats data in L{objects.QueryResponse}.
 
   @type result: L{objects.QueryResponse}
@@ -2426,6 +2437,8 @@ def FormatQueryResult(result, unit=None, format_override=None, separator=None,
   @param separator: String used to separate fields
   @type header: bool
   @param header: Whether to output header row
+  @type verbose: boolean
+  @param verbose: whether to use verbose field descriptions or not
 
   """
   if unit is None:
@@ -2437,7 +2450,7 @@ def FormatQueryResult(result, unit=None, format_override=None, separator=None,
   if format_override is None:
     format_override = {}
 
-  stats = dict.fromkeys(constants.QRFS_ALL, 0)
+  stats = dict.fromkeys(constants.RS_ALL, 0)
 
   def _RecordStatus(status):
     if status in stats:
@@ -2448,22 +2461,23 @@ def FormatQueryResult(result, unit=None, format_override=None, separator=None,
     assert fdef.title and fdef.name
     (fn, align_right) = _GetColumnFormatter(fdef, format_override, unit)
     columns.append(TableColumn(fdef.title,
-                               _QueryColumnFormatter(fn, _RecordStatus),
+                               _QueryColumnFormatter(fn, _RecordStatus,
+                                                     verbose),
                                align_right))
 
   table = FormatTable(result.data, columns, header, separator)
 
   # Collect statistics
-  assert len(stats) == len(constants.QRFS_ALL)
+  assert len(stats) == len(constants.RS_ALL)
   assert compat.all(count >= 0 for count in stats.values())
 
   # Determine overall status. If there was no data, unknown fields must be
   # detected via the field definitions.
-  if (stats[constants.QRFS_UNKNOWN] or
+  if (stats[constants.RS_UNKNOWN] or
       (not result.data and _GetUnknownFields(result.fields))):
     status = QR_UNKNOWN
   elif compat.any(count > 0 for key, count in stats.items()
-                  if key != constants.QRFS_NORMAL):
+                  if key != constants.RS_NORMAL):
     status = QR_INCOMPLETE
   else:
     status = QR_NORMAL
@@ -2497,7 +2511,7 @@ def _WarnUnknownFields(fdefs):
 
 
 def GenericList(resource, fields, names, unit, separator, header, cl=None,
-                format_override=None):
+                format_override=None, verbose=False):
   """Generic implementation for listing all items of a resource.
 
   @param resource: One of L{constants.QR_OP_LUXI}
@@ -2516,6 +2530,8 @@ def GenericList(resource, fields, names, unit, separator, header, cl=None,
   @type format_override: dict
   @param format_override: Dictionary for overriding field formatting functions,
     indexed by field name, contents like L{_DEFAULT_FORMAT_QUERY}
+  @type verbose: boolean
+  @param verbose: whether to use verbose field descriptions or not
 
   """
   if cl is None:
@@ -2530,7 +2546,8 @@ def GenericList(resource, fields, names, unit, separator, header, cl=None,
 
   (status, data) = FormatQueryResult(response, unit=unit, separator=separator,
                                      header=header,
-                                     format_override=format_override)
+                                     format_override=format_override,
+                                     verbose=verbose)
 
   for line in data:
     ToStdout(line)