locking: Allow checking if lock is owned in certain mode
[ganeti-local] / lib / cli.py
index 38d2b64..63f2dfb 100644 (file)
@@ -29,6 +29,7 @@ import time
 import logging
 import errno
 import itertools
+import shlex
 from cStringIO import StringIO
 
 from ganeti import utils
@@ -92,6 +93,7 @@ __all__ = [
   "DEFAULT_IALLOCATOR_OPT",
   "IDENTIFY_DEFAULTS_OPT",
   "IGNORE_CONSIST_OPT",
+  "IGNORE_ERRORS_OPT",
   "IGNORE_FAILURES_OPT",
   "IGNORE_OFFLINE_OPT",
   "IGNORE_REMOVE_FAILURES_OPT",
@@ -101,6 +103,7 @@ __all__ = [
   "MAC_PREFIX_OPT",
   "MAINTAIN_NODE_HEALTH_OPT",
   "MASTER_NETDEV_OPT",
+  "MASTER_NETMASK_OPT",
   "MC_OPT",
   "MIGRATION_MODE_OPT",
   "NET_OPT",
@@ -109,6 +112,7 @@ __all__ = [
   "NEW_CONFD_HMAC_KEY_OPT",
   "NEW_RAPI_CERT_OPT",
   "NEW_SECONDARY_OPT",
+  "NEW_SPICE_CERT_OPT",
   "NIC_PARAMS_OPT",
   "NODE_FORCE_JOIN_OPT",
   "NODE_LIST_OPT",
@@ -133,6 +137,8 @@ __all__ = [
   "NOVOTING_OPT",
   "NO_REMEMBER_OPT",
   "NWSYNC_OPT",
+  "OFFLINE_INST_OPT",
+  "ONLINE_INST_OPT",
   "ON_PRIMARY_OPT",
   "ON_SECONDARY_OPT",
   "OFFLINE_OPT",
@@ -159,6 +165,8 @@ __all__ = [
   "SHOWCMD_OPT",
   "SHUTDOWN_TIMEOUT_OPT",
   "SINGLE_NODE_OPT",
+  "SPICE_CACERT_OPT",
+  "SPICE_CERT_OPT",
   "SRC_DIR_OPT",
   "SRC_NODE_OPT",
   "SUBMIT_OPT",
@@ -171,6 +179,7 @@ __all__ = [
   "TO_GROUP_OPT",
   "UIDPOOL_OPT",
   "USEUNITS_OPT",
+  "USE_EXTERNAL_MIP_SCRIPT",
   "USE_REPL_NET_OPT",
   "VERBOSE_OPT",
   "VG_NAME_OPT",
@@ -678,6 +687,14 @@ NWSYNC_OPT = cli_option("--no-wait-for-sync", dest="wait_for_sync",
                         default=True, action="store_false",
                         help="Don't wait for sync (DANGEROUS!)")
 
+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")
+
 DISK_TEMPLATE_OPT = cli_option("-t", "--disk-template", dest="disk_template",
                                help=("Custom disk setup (%s)" %
                                      utils.CommaJoin(constants.DISK_TEMPLATES)),
@@ -1005,6 +1022,18 @@ MASTER_NETDEV_OPT = cli_option("--master-netdev", dest="master_netdev",
                                metavar="NETDEV",
                                default=None)
 
+MASTER_NETMASK_OPT = cli_option("--master-netmask", dest="master_netmask",
+                                help="Specify the netmask of the master IP",
+                                metavar="NETMASK",
+                                default=None)
+
+USE_EXTERNAL_MIP_SCRIPT = cli_option("--use-external-mip-script",
+                                dest="use_external_mip_script",
+                                help="Specify whether to run a user-provided"
+                                " script for the master IP address turnup and"
+                                " turndown operations",
+                                type="bool", metavar=_YORNO, default=None)
+
 GLOBAL_FILEDIR_OPT = cli_option("--file-storage-dir", dest="file_storage_dir",
                                 help="Specify the default directory (cluster-"
                                 "wide) for storing the file-based disks [%s]" %
@@ -1086,6 +1115,21 @@ NEW_RAPI_CERT_OPT = cli_option("--new-rapi-certificate", dest="new_rapi_cert",
                                help=("Generate a new self-signed RAPI"
                                      " certificate"))
 
+SPICE_CERT_OPT = cli_option("--spice-certificate", dest="spice_cert",
+                           default=None,
+                           help="File containing new SPICE certificate")
+
+SPICE_CACERT_OPT = cli_option("--spice-ca-certificate", dest="spice_cacert",
+                           default=None,
+                           help="File containing the certificate of the CA"
+                                " which signed the SPICE certificate")
+
+NEW_SPICE_CERT_OPT = cli_option("--new-spice-certificate",
+                               dest="new_spice_cert", default=None,
+                               action="store_true",
+                               help=("Generate a new self-signed SPICE"
+                                     " certificate"))
+
 NEW_CONFD_HMAC_KEY_OPT = cli_option("--new-confd-hmac-key",
                                     dest="new_confd_hmac_key",
                                     default=False, action="store_true",
@@ -1238,6 +1282,11 @@ TO_GROUP_OPT = cli_option("--to", dest="to", metavar="<group>",
                           default=None, action="append",
                           completion_suggest=OPT_COMPL_ONE_NODEGROUP)
 
+IGNORE_ERRORS_OPT = cli_option("-I", "--ignore-errors", default=[],
+                               action="append", dest="ignore_errors",
+                               choices=list(constants.CV_ALL_ECODES_STRINGS),
+                               help="Error code to be ignored")
+
 
 #: Options provided by all commands
 COMMON_OPTS = [DEBUG_OPT]
@@ -1267,7 +1316,7 @@ COMMON_CREATE_OPTS = [
   ]
 
 
-def _ParseArgs(argv, commands, aliases):
+def _ParseArgs(argv, commands, aliases, env_override):
   """Parser for the command line arguments.
 
   This function parses the arguments and returns the function which
@@ -1277,8 +1326,11 @@ def _ParseArgs(argv, commands, aliases):
   @param commands: dictionary with special contents, see the design
       doc for cmdline handling
   @param aliases: dictionary with command aliases {'alias': 'target, ...}
+  @param env_override: list of env variables allowed for default args
 
   """
+  assert not (env_override - set(commands))
+
   if len(argv) == 0:
     binary = "<command>"
   else:
@@ -1332,13 +1384,19 @@ def _ParseArgs(argv, commands, aliases):
 
     cmd = aliases[cmd]
 
+  if cmd in env_override:
+    args_env_name = ("%s_%s" % (binary.replace("-", "_"), cmd)).upper()
+    env_args = os.environ.get(args_env_name)
+    if env_args:
+      argv = utils.InsertAtPos(argv, 1, shlex.split(env_args))
+
   func, args_def, parser_opts, usage, description = commands[cmd]
   parser = OptionParser(option_list=parser_opts + COMMON_OPTS,
                         description=description,
                         formatter=TitledHelpFormatter(),
                         usage="%%prog %s %s" % (cmd, usage))
   parser.disable_interspersed_args()
-  options, args = parser.parse_args()
+  options, args = parser.parse_args(args=argv[1:])
 
   if not _CheckArguments(cmd, args_def, args):
     return None, None, None
@@ -1972,16 +2030,18 @@ def FormatError(err):
   return retcode, obuf.getvalue().rstrip("\n")
 
 
-def GenericMain(commands, override=None, aliases=None):
+def GenericMain(commands, override=None, aliases=None,
+                env_override=frozenset()):
   """Generic main function for all the gnt-* commands.
 
-  Arguments:
-    - commands: a dictionary with a special structure, see the design doc
-                for command line handling.
-    - override: if not None, we expect a dictionary with keys that will
-                override command line options; this can be used to pass
-                options from the scripts to generic functions
-    - aliases: dictionary with command aliases {'alias': 'target, ...}
+  @param commands: a dictionary with a special structure, see the design doc
+                   for command line handling.
+  @param override: if not None, we expect a dictionary with keys that will
+                   override command line options; this can be used to pass
+                   options from the scripts to generic functions
+  @param aliases: dictionary with command aliases {'alias': 'target, ...}
+  @param env_override: list of environment names which are allowed to submit
+                       default args for commands
 
   """
   # save the program name and the entire command line for later logging
@@ -2000,7 +2060,7 @@ def GenericMain(commands, override=None, aliases=None):
     aliases = {}
 
   try:
-    func, options, args = _ParseArgs(sys.argv, commands, aliases)
+    func, options, args = _ParseArgs(sys.argv, commands, aliases, env_override)
   except errors.ParameterError, err:
     result, err_msg = FormatError(err)
     ToStderr(err_msg)
@@ -2152,7 +2212,7 @@ def GenericInstanceCreate(mode, opts, args):
   else:
     tags = []
 
-  utils.ForceDictType(opts.beparams, constants.BES_PARAMETER_TYPES)
+  utils.ForceDictType(opts.beparams, constants.BES_PARAMETER_COMPAT)
   utils.ForceDictType(hvparams, constants.HVS_PARAMETER_TYPES)
 
   if mode == constants.INSTANCE_CREATE:
@@ -2658,15 +2718,15 @@ def GenericList(resource, fields, names, unit, separator, header, cl=None,
   @param verbose: whether to use verbose field descriptions or not
 
   """
-  if cl is None:
-    cl = GetClient()
-
   if not names:
     names = None
 
-  filter_ = qlang.MakeFilter(names, force_filter)
+  qfilter = qlang.MakeFilter(names, force_filter)
+
+  if cl is None:
+    cl = GetClient()
 
-  response = cl.Query(resource, fields, filter_)
+  response = cl.Query(resource, fields, qfilter)
 
   found_unknown = _WarnUnknownFields(response.fields)
 
@@ -2895,24 +2955,24 @@ def GetOnlineNodes(nodes, cl=None, nowarn=False, secondary_ips=False,
   if cl is None:
     cl = GetClient()
 
-  filter_ = []
+  qfilter = []
 
   if nodes:
-    filter_.append(qlang.MakeSimpleFilter("name", nodes))
+    qfilter.append(qlang.MakeSimpleFilter("name", nodes))
 
   if nodegroup is not None:
-    filter_.append([qlang.OP_OR, [qlang.OP_EQUAL, "group", nodegroup],
+    qfilter.append([qlang.OP_OR, [qlang.OP_EQUAL, "group", nodegroup],
                                  [qlang.OP_EQUAL, "group.uuid", nodegroup]])
 
   if filter_master:
-    filter_.append([qlang.OP_NOT, [qlang.OP_TRUE, "master"]])
+    qfilter.append([qlang.OP_NOT, [qlang.OP_TRUE, "master"]])
 
-  if filter_:
-    if len(filter_) > 1:
-      final_filter = [qlang.OP_AND] + filter_
+  if qfilter:
+    if len(qfilter) > 1:
+      final_filter = [qlang.OP_AND] + qfilter
     else:
-      assert len(filter_) == 1
-      final_filter = filter_[0]
+      assert len(qfilter) == 1
+      final_filter = qfilter[0]
   else:
     final_filter = None