Makefile: Fix list of directories
[ganeti-local] / lib / cli.py
index 95f6994..950578e 100644 (file)
@@ -54,6 +54,7 @@ __all__ = [
   # Command line options
   "ABSOLUTE_OPT",
   "ADD_UIDS_OPT",
+  "ADD_RESERVED_IPS_OPT",
   "ALLOCATABLE_OPT",
   "ALLOC_POLICY_OPT",
   "ALL_OPT",
@@ -81,12 +82,15 @@ __all__ = [
   "EARLY_RELEASE_OPT",
   "ENABLED_HV_OPT",
   "ERROR_CODES_OPT",
+  "FAILURE_ONLY_OPT",
   "FIELDS_OPT",
   "FILESTORE_DIR_OPT",
   "FILESTORE_DRIVER_OPT",
   "FORCE_FILTER_OPT",
   "FORCE_OPT",
   "FORCE_VARIANT_OPT",
+  "GATEWAY_OPT",
+  "GATEWAY6_OPT",
   "GLOBAL_FILEDIR_OPT",
   "HID_OS_OPT",
   "GLOBAL_SHARED_FILEDIR_OPT",
@@ -111,6 +115,9 @@ __all__ = [
   "MC_OPT",
   "MIGRATION_MODE_OPT",
   "NET_OPT",
+  "NETWORK_OPT",
+  "NETWORK6_OPT",
+  "NETWORK_TYPE_OPT",
   "NEW_CLUSTER_CERT_OPT",
   "NEW_CLUSTER_DOMAIN_SECRET_OPT",
   "NEW_CONFD_HMAC_KEY_OPT",
@@ -118,6 +125,7 @@ __all__ = [
   "NEW_SECONDARY_OPT",
   "NEW_SPICE_CERT_OPT",
   "NIC_PARAMS_OPT",
+  "NOCONFLICTSCHECK_OPT",
   "NODE_FORCE_JOIN_OPT",
   "NODE_LIST_OPT",
   "NODE_PLACEMENT_OPT",
@@ -160,6 +168,7 @@ __all__ = [
   "READD_OPT",
   "REBOOT_TYPE_OPT",
   "REMOVE_INSTANCE_OPT",
+  "REMOVE_RESERVED_IPS_OPT",
   "REMOVE_UIDS_OPT",
   "RESERVED_LVS_OPT",
   "RUNTIME_MEM_OPT",
@@ -169,6 +178,7 @@ __all__ = [
   "SELECT_OS_OPT",
   "SEP_OPT",
   "SHOWCMD_OPT",
+  "SHOW_MACHINE_OPT",
   "SHUTDOWN_TIMEOUT_OPT",
   "SINGLE_NODE_OPT",
   "SPECS_CPU_COUNT_OPT",
@@ -235,11 +245,13 @@ __all__ = [
   "ARGS_MANY_INSTANCES",
   "ARGS_MANY_NODES",
   "ARGS_MANY_GROUPS",
+  "ARGS_MANY_NETWORKS",
   "ARGS_NONE",
   "ARGS_ONE_INSTANCE",
   "ARGS_ONE_NODE",
   "ARGS_ONE_GROUP",
   "ARGS_ONE_OS",
+  "ARGS_ONE_NETWORK",
   "ArgChoice",
   "ArgCommand",
   "ArgFile",
@@ -247,8 +259,10 @@ __all__ = [
   "ArgHost",
   "ArgInstance",
   "ArgJobId",
+  "ArgNetwork",
   "ArgNode",
   "ArgOs",
+  "ArgExtStorage",
   "ArgSuggest",
   "ArgUnknown",
   "OPT_COMPL_INST_ADD_NODES",
@@ -257,7 +271,9 @@ __all__ = [
   "OPT_COMPL_ONE_INSTANCE",
   "OPT_COMPL_ONE_NODE",
   "OPT_COMPL_ONE_NODEGROUP",
+  "OPT_COMPL_ONE_NETWORK",
   "OPT_COMPL_ONE_OS",
+  "OPT_COMPL_ONE_EXTSTORAGE",
   "cli_option",
   "SplitNodeOption",
   "CalculateOSNames",
@@ -301,6 +317,17 @@ TISPECS_CLUSTER_TYPES = {
   constants.ISPECS_STD: constants.VTYPE_INT,
   }
 
+#: 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",
+  }
+
 
 class _Argument:
   def __init__(self, min=0, max=None): # pylint: disable=W0622
@@ -355,6 +382,12 @@ class ArgNode(_Argument):
   """
 
 
+class ArgNetwork(_Argument):
+  """Network argument.
+
+  """
+
+
 class ArgGroup(_Argument):
   """Node group argument.
 
@@ -391,11 +424,19 @@ class ArgOs(_Argument):
   """
 
 
+class ArgExtStorage(_Argument):
+  """ExtStorage argument.
+
+  """
+
+
 ARGS_NONE = []
 ARGS_MANY_INSTANCES = [ArgInstance()]
+ARGS_MANY_NETWORKS = [ArgNetwork()]
 ARGS_MANY_NODES = [ArgNode()]
 ARGS_MANY_GROUPS = [ArgGroup()]
 ARGS_ONE_INSTANCE = [ArgInstance(min=1, max=1)]
+ARGS_ONE_NETWORK = [ArgNetwork(min=1, max=1)]
 ARGS_ONE_NODE = [ArgNode(min=1, max=1)]
 # TODO
 ARGS_ONE_GROUP = [ArgGroup(min=1, max=1)]
@@ -412,9 +453,10 @@ def _ExtractTagsObject(opts, args):
     raise errors.ProgrammerError("tag_type not passed to _ExtractTagsObject")
   kind = opts.tag_type
   if kind == constants.TAG_CLUSTER:
-    retval = kind, kind
+    retval = kind, None
   elif kind in (constants.TAG_NODEGROUP,
                 constants.TAG_NODE,
+                constants.TAG_NETWORK,
                 constants.TAG_INSTANCE):
     if not args:
       raise errors.OpPrereqError("no arguments passed to the command",
@@ -638,16 +680,20 @@ def check_maybefloat(option, opt, value): # pylint: disable=W0613
  OPT_COMPL_ONE_NODE,
  OPT_COMPL_ONE_INSTANCE,
  OPT_COMPL_ONE_OS,
+ OPT_COMPL_ONE_EXTSTORAGE,
  OPT_COMPL_ONE_IALLOCATOR,
+ OPT_COMPL_ONE_NETWORK,
  OPT_COMPL_INST_ADD_NODES,
- OPT_COMPL_ONE_NODEGROUP) = range(100, 107)
+ OPT_COMPL_ONE_NODEGROUP) = range(100, 109)
 
-OPT_COMPL_ALL = frozenset([
+OPT_COMPL_ALL = compat.UniqueFrozenset([
   OPT_COMPL_MANY_NODES,
   OPT_COMPL_ONE_NODE,
   OPT_COMPL_ONE_INSTANCE,
   OPT_COMPL_ONE_OS,
+  OPT_COMPL_ONE_EXTSTORAGE,
   OPT_COMPL_ONE_IALLOCATOR,
+  OPT_COMPL_ONE_NETWORK,
   OPT_COMPL_INST_ADD_NODES,
   OPT_COMPL_ONE_NODEGROUP,
   ])
@@ -734,7 +780,7 @@ SYNC_OPT = cli_option("--sync", dest="do_locking",
 DRY_RUN_OPT = cli_option("--dry-run", default=False,
                          action="store_true",
                          help=("Do not execute the operation, just run the"
-                               " check steps and verify it it could be"
+                               " check steps and verify if it could be"
                                " executed"))
 
 VERBOSE_OPT = cli_option("-v", "--verbose", default=False,
@@ -1335,9 +1381,30 @@ PRIMARY_IP_VERSION_OPT = \
                                   constants.IP6_VERSION),
                help="Cluster-wide IP version for primary IP")
 
+SHOW_MACHINE_OPT = cli_option("-M", "--show-machine-names", default=False,
+                              action="store_true",
+                              help="Show machine name for every line in output")
+
+FAILURE_ONLY_OPT = cli_option("--failure-only", default=False,
+                              action="store_true",
+                              help=("Hide successful results and show failures"
+                                    " only (determined by the exit code)"))
+
+
+def _PriorityOptionCb(option, _, value, parser):
+  """Callback for processing C{--priority} option.
+
+  """
+  value = _PRIONAME_TO_VALUE[value]
+
+  setattr(parser.values, option.dest, value)
+
+
 PRIORITY_OPT = cli_option("--priority", default=None, dest="priority",
                           metavar="|".join(name for name, _ in _PRIORITY_NAMES),
                           choices=_PRIONAME_TO_VALUE.keys(),
+                          action="callback", type="choice",
+                          callback=_PriorityOptionCb,
                           help="Priority for opcode processing")
 
 HID_OS_OPT = cli_option("--hidden", dest="hidden",
@@ -1440,6 +1507,44 @@ ABSOLUTE_OPT = cli_option("--absolute", dest="absolute",
                           help="Marks the grow as absolute instead of the"
                           " (default) relative mode")
 
+NETWORK_OPT = cli_option("--network",
+                         action="store", default=None, dest="network",
+                         help="IP network in CIDR notation")
+
+GATEWAY_OPT = cli_option("--gateway",
+                         action="store", default=None, dest="gateway",
+                         help="IP address of the router (gateway)")
+
+ADD_RESERVED_IPS_OPT = cli_option("--add-reserved-ips",
+                                  action="store", default=None,
+                                  dest="add_reserved_ips",
+                                  help="Comma-separated list of"
+                                  " reserved IPs to add")
+
+REMOVE_RESERVED_IPS_OPT = cli_option("--remove-reserved-ips",
+                                     action="store", default=None,
+                                     dest="remove_reserved_ips",
+                                     help="Comma-delimited list of"
+                                     " reserved IPs to remove")
+
+NETWORK_TYPE_OPT = cli_option("--network-type",
+                              action="store", default=None, dest="network_type",
+                              help="Network type: private, public, None")
+
+NETWORK6_OPT = cli_option("--network6",
+                          action="store", default=None, dest="network6",
+                          help="IP network in CIDR notation")
+
+GATEWAY6_OPT = cli_option("--gateway6",
+                          action="store", default=None, dest="gateway6",
+                          help="IP6 address of the router (gateway)")
+
+NOCONFLICTSCHECK_OPT = cli_option("--no-conflicts-check",
+                                  dest="conflicts_check",
+                                  default=True,
+                                  action="store_false",
+                                  help="Don't check for conflicting IPs")
+
 #: Options provided by all commands
 COMMON_OPTS = [DEBUG_OPT]
 
@@ -1456,6 +1561,7 @@ COMMON_CREATE_OPTS = [
   NET_OPT,
   NODE_PLACEMENT_OPT,
   NOIPCHECK_OPT,
+  NOCONFLICTSCHECK_OPT,
   NONAMECHECK_OPT,
   NONICS_OPT,
   NWSYNC_OPT,
@@ -2097,7 +2203,7 @@ def SetGenericOpcodeOpts(opcode_list, options):
     if hasattr(options, "dry_run"):
       op.dry_run = options.dry_run
     if getattr(options, "priority", None) is not None:
-      op.priority = _PRIONAME_TO_VALUE[options.priority]
+      op.priority = options.priority
 
 
 def GetClient(query=False):
@@ -2450,6 +2556,7 @@ def GenericInstanceCreate(mode, opts, args):
                                 disks=disks,
                                 disk_template=opts.disk_template,
                                 nics=nics,
+                                conflicts_check=opts.conflicts_check,
                                 pnode=pnode, snode=snode,
                                 ip_check=opts.ip_check,
                                 name_check=opts.name_check,
@@ -2978,6 +3085,21 @@ def GenericList(resource, fields, names, unit, separator, header, cl=None,
   return constants.EXIT_SUCCESS
 
 
+def _FieldDescValues(fdef):
+  """Helper function for L{GenericListFields} to get query field description.
+
+  @type fdef: L{objects.QueryFieldDefinition}
+  @rtype: list
+
+  """
+  return [
+    fdef.name,
+    _QFT_NAMES.get(fdef.kind, fdef.kind),
+    fdef.title,
+    fdef.doc,
+    ]
+
+
 def GenericListFields(resource, fields, separator, header, cl=None):
   """Generic implementation for listing fields for a resource.
 
@@ -3002,11 +3124,12 @@ def GenericListFields(resource, fields, separator, header, cl=None):
 
   columns = [
     TableColumn("Name", str, False),
+    TableColumn("Type", str, False),
     TableColumn("Title", str, False),
     TableColumn("Description", str, False),
     ]
 
-  rows = [[fdef.name, fdef.title, fdef.doc] for fdef in response.fields]
+  rows = map(_FieldDescValues, response.fields)
 
   for line in FormatTable(rows, columns, header, separator):
     ToStdout(line)