Implement more options for “gnt-backup import”
[ganeti-local] / scripts / gnt-instance
index d89cce9..5502334 100755 (executable)
@@ -39,6 +39,13 @@ _SHUTDOWN_NODES_PRI = "nodes-pri"
 _SHUTDOWN_NODES_SEC = "nodes-sec"
 _SHUTDOWN_INSTANCES = "instances"
 
+_VALUE_TRUE = "true"
+
+_LIST_DEF_FIELDS = [
+  "name", "os", "pnode", "status", "oper_ram",
+  ]
+
+
 def _ExpandMultiNames(mode, names):
   """Expand the given names using the passed mode.
 
@@ -130,7 +137,7 @@ def _ConfirmOperation(inames, text):
   choice = AskUser(ask, choices)
   if choice == 'v':
     choices.pop(1)
-    choice = AskUser(choices, msg + affected)
+    choice = AskUser(msg + affected, choices)
   return choice
 
 
@@ -156,14 +163,14 @@ def _TransformPath(user_input):
 
   return result_path
 
-
 def ListInstances(opts, args):
   """List instances and their properties.
 
   """
   if opts.output is None:
-    selected_fields = ["name", "os", "pnode", "admin_state",
-                       "oper_state", "oper_ram"]
+    selected_fields = _LIST_DEF_FIELDS
+  elif opts.output.startswith("+"):
+    selected_fields = _LIST_DEF_FIELDS + opts.output[1:].split(",")
   else:
     selected_fields = opts.output.split(",")
 
@@ -171,13 +178,27 @@ def ListInstances(opts, args):
   output = SubmitOpCode(op)
 
   if not opts.no_headers:
-    headers = {"name": "Instance", "os": "OS", "pnode": "Primary_node",
-               "snodes": "Secondary_Nodes", "admin_state": "Autostart",
-               "oper_state": "Status", "admin_ram": "Configured_memory",
-               "oper_ram": "Memory", "disk_template": "Disk_template",
-               "ip": "IP Address", "mac": "MAC Address",
-               "bridge": "Bridge",
-               "sda_size": "Disk/0", "sdb_size": "Disk/1"}
+    headers = {
+      "name": "Instance", "os": "OS", "pnode": "Primary_node",
+      "snodes": "Secondary_Nodes", "admin_state": "Autostart",
+      "oper_state": "Running", "admin_ram": "Configured_memory",
+      "oper_ram": "Memory", "disk_template": "Disk_template",
+      "ip": "IP_address", "mac": "MAC_address",
+      "bridge": "Bridge", "vcpus": "VCPUs",
+      "sda_size": "Disk/0", "sdb_size": "Disk/1",
+      "status": "Status", "tags": "Tags",
+      "auto_balance": "Auto_balance",
+      "network_port": "Network_port",
+      "kernel_path": "Kernel_path",
+      "initrd_path": "Initrd_path",
+      "hvm_boot_order": "HVM_boot_order",
+      "hvm_acpi": "HVM_ACPI",
+      "hvm_pae": "HVM_PAE",
+      "hvm_cdrom_image_path": "HVM_CDROM_image_path",
+      "hvm_nic_type": "HVM_NIC_type",
+      "hvm_disk_type": "HVM_disk_type",
+      "vnc_bind_address": "VNC_bind_address",
+      }
   else:
     headers = None
 
@@ -186,15 +207,16 @@ def ListInstances(opts, args):
   else:
     unitfields = None
 
-  numfields = ["admin_ram", "oper_ram", "sda_size", "sdb_size"]
+  numfields = ["admin_ram", "oper_ram", "sda_size", "sdb_size", "vcpus"]
 
+  list_type_fields = ("tags",)
   # change raw values to nicer strings
   for row in output:
     for idx, field in enumerate(selected_fields):
       val = row[idx]
       if field == "snodes":
         val = ",".join(val) or "-"
-      elif field == "admin_state":
+      elif field == "admin_state" or field == "auto_balance":
         if val:
           val = "yes"
         else:
@@ -212,6 +234,8 @@ def ListInstances(opts, args):
       elif field == "sda_size" or field == "sdb_size":
         if val is None:
           val = "N/A"
+      elif field in list_type_fields:
+        val = ",".join(val)
       row[idx] = str(val)
 
   data = GenerateTable(separator=opts.separator, headers=headers,
@@ -244,6 +268,17 @@ def AddInstance(opts, args):
   kernel_path = _TransformPath(opts.kernel_path)
   initrd_path = _TransformPath(opts.initrd_path)
 
+  hvm_acpi = opts.hvm_acpi == _VALUE_TRUE
+  hvm_pae = opts.hvm_pae == _VALUE_TRUE
+
+  if ((opts.hvm_cdrom_image_path is not None) and
+      (opts.hvm_cdrom_image_path.lower() == constants.VALUE_NONE)):
+    hvm_cdrom_image_path = None
+  else:
+    hvm_cdrom_image_path = opts.hvm_cdrom_image_path
+
+  auto_balance = opts.auto_balance == _VALUE_TRUE
+
   op = opcodes.OpCreateInstance(instance_name=instance, mem_size=opts.mem,
                                 disk_size=opts.size, swap_size=opts.swap,
                                 disk_template=opts.disk_template,
@@ -256,7 +291,15 @@ def AddInstance(opts, args):
                                 mac=opts.mac,
                                 kernel_path=kernel_path,
                                 initrd_path=initrd_path,
-                                hvm_boot_order=opts.hvm_boot_order)
+                                iallocator=opts.iallocator,
+                                hvm_boot_order=opts.hvm_boot_order,
+                                hvm_acpi=hvm_acpi, hvm_pae=hvm_pae,
+                                hvm_cdrom_image_path=hvm_cdrom_image_path,
+                                vnc_bind_address=opts.vnc_bind_address,
+                                hvm_nic_type=opts.hvm_nic_type,
+                                hvm_disk_type=opts.hvm_disk_type,
+                                auto_balance=auto_balance)
+
   SubmitOpCode(op)
   return 0
 
@@ -271,6 +314,34 @@ def ReinstallInstance(opts, args):
   """
   instance_name = args[0]
 
+  if opts.interactive is True:
+    op = opcodes.OpDiagnoseOS(output_fields=["name", "valid"], names=[])
+    result = SubmitOpCode(op)
+
+    if not result:
+      logger.ToStdout("Can't get the OS list")
+      return 1
+
+    logger.ToStdout("Available OS templates:")
+    number = 0
+    choices = []
+    for entry in result:
+      logger.ToStdout("%3s: %s" % (number, entry[0]))
+      choices.append(("%s" % number, entry[0], entry[0]))
+      number = number + 1
+
+    choices.append(('x', 'exit', 'Exit gnt-instance reinstall'))
+    selected = AskUser("Enter OS template name or number (or x to abort):",
+                       choices)
+
+    if selected == 'exit':
+      logger.ToStdout("User aborted reinstall, exiting")
+      return 1
+
+    os = selected
+  else:
+    os = opts.os
+
   if not opts.force:
     usertext = ("This will reinstall the instance %s and remove"
                 " all data. Continue?") % instance_name
@@ -278,7 +349,7 @@ def ReinstallInstance(opts, args):
       return 1
 
   op = opcodes.OpReinstallInstance(instance_name=instance_name,
-                                   os_type=opts.os)
+                                   os_type=os)
   SubmitOpCode(op)
 
   return 0
@@ -354,6 +425,22 @@ def DeactivateDisks(opts, args):
   return 0
 
 
+def GrowDisk(opts, args):
+  """Command-line interface for _ShutdownInstanceBlockDevices.
+
+  This function takes the instance name, looks for its primary node
+  and the tries to shutdown its block devices on that node.
+
+  """
+  instance = args[0]
+  disk = args[1]
+  amount = utils.ParseUnit(args[2])
+  op = opcodes.OpGrowDisk(instance_name=instance, disk=disk, amount=amount,
+                          wait_for_sync=opts.wait_for_sync)
+  SubmitOpCode(op)
+  return 0
+
+
 def StartupInstance(opts, args):
   """Startup an instance.
 
@@ -470,6 +557,7 @@ def ReplaceDisks(opts, args):
   """
   instance_name = args[0]
   new_2ndary = opts.new_secondary
+  iallocator = opts.iallocator
   if opts.disks is None:
     disks = ["sda", "sdb"]
   else:
@@ -478,14 +566,16 @@ def ReplaceDisks(opts, args):
     mode = constants.REPLACE_DISK_ALL
   elif opts.on_primary: # only on primary:
     mode = constants.REPLACE_DISK_PRI
-    if new_2ndary is not None:
+    if new_2ndary is not None or iallocator is not None:
       raise errors.OpPrereqError("Can't change secondary node on primary disk"
                                  " replacement")
-  elif opts.on_secondary is not None: # only on secondary
+  elif opts.on_secondary is not None or iallocator is not None:
+    # only on secondary
     mode = constants.REPLACE_DISK_SEC
 
   op = opcodes.OpReplaceDisks(instance_name=args[0], disks=disks,
-                              remote_node=new_2ndary, mode=mode)
+                              remote_node=new_2ndary, mode=mode,
+                              iallocator=iallocator)
   SubmitOpCode(op)
   return 0
 
@@ -519,6 +609,41 @@ def FailoverInstance(opts, args):
   return 0
 
 
+def MigrateInstance(opts, args):
+  """Migrate an instance.
+
+  The migrate is done without shutdown.
+
+  Args:
+    opts - class with options as members
+    args - list with a single element, the instance name
+  Opts used:
+    force - whether to migrate without asking questions.
+
+  """
+  instance_name = args[0]
+  force = opts.force
+
+  if not force:
+    if opts.cleanup:
+      usertext = ("Instance %s will be recovered from a failed migration."
+                  " Note that the migration procedure (including cleanup)" %
+                  (instance_name,))
+    else:
+      usertext = ("Instance %s will be migrated. Note that migration" %
+                  (instance_name,))
+    usertext += (" is **experimental** in this version."
+                " This might impact the instance if anything goes wrong."
+                " Continue?")
+    if not AskUser(usertext):
+      return 1
+
+  op = opcodes.OpMigrateInstance(instance_name=instance_name, live=opts.live,
+                                 cleanup=opts.cleanup)
+  SubmitOpCode(op)
+  return 0
+
+
 def ConnectToInstanceConsole(opts, args):
   """Connect to the console of an instance.
 
@@ -549,7 +674,7 @@ def _FormatBlockDevInfo(buf, dev, indent_level):
 
   """
   def helper(buf, dtype, status):
-    """Format one line for phsyical device status."""
+    """Format one line for physical device status."""
     if not status:
       buf.write("not active\n")
     else:
@@ -610,6 +735,10 @@ def ShowInstanceConfig(opts, args):
   retcode = 0
   op = opcodes.OpQueryInstanceData(instances=args)
   result = SubmitOpCode(op)
+  hvm_parameters = ("hvm_acpi", "hvm_pae", "hvm_cdrom_image_path",
+                    "hvm_boot_order", "hvm_nic_type", "hvm_disk_type")
+
+  pvm_parameters = ("kernel_path", "initrd_path")
 
   if not result:
     logger.ToStdout("No instances.")
@@ -622,23 +751,38 @@ def ShowInstanceConfig(opts, args):
     buf.write("Instance name: %s\n" % instance["name"])
     buf.write("State: configured to be %s, actual state is %s\n" %
               (instance["config_state"], instance["run_state"]))
+    buf.write("Considered for memory checks in cluster verify: %s\n" %
+              instance["auto_balance"])
     buf.write("  Nodes:\n")
     buf.write("    - primary: %s\n" % instance["pnode"])
     buf.write("    - secondaries: %s\n" % ", ".join(instance["snodes"]))
     buf.write("  Operating system: %s\n" % instance["os"])
-    buf.write("  Allocated network port: %s\n" % instance["network_port"])
-    if instance["kernel_path"] in (None, constants.VALUE_DEFAULT):
-      kpath = "(default: %s)" % constants.XEN_KERNEL
-    else:
-      kpath = instance["kernel_path"]
-    buf.write("  Kernel path: %s\n" % kpath)
-    if instance["initrd_path"] in (None, constants.VALUE_DEFAULT):
-      initrd = "(default: %s)" % constants.XEN_INITRD
-    elif instance["initrd_path"] == constants.VALUE_NONE:
-      initrd = "(none)"
-    else:
-      initrd = instance["initrd_path"]
-    buf.write("       initrd: %s\n" % initrd)
+    if instance.has_key("network_port"):
+      buf.write("  Allocated network port: %s\n" % instance["network_port"])
+    if False not in map(instance.has_key, pvm_parameters):
+      if instance["kernel_path"] in (None, constants.VALUE_DEFAULT):
+        kpath = "(default: %s)" % constants.XEN_KERNEL
+      else:
+        kpath = instance["kernel_path"]
+      buf.write("  Kernel path: %s\n" % kpath)
+      if instance["initrd_path"] in (None, constants.VALUE_DEFAULT):
+        initrd = "(default: %s)" % constants.XEN_INITRD
+      elif instance["initrd_path"] == constants.VALUE_NONE:
+        initrd = "(none)"
+      else:
+        initrd = instance["initrd_path"]
+      buf.write("       initrd: %s\n" % initrd)
+    if False not in map(instance.has_key, hvm_parameters):
+      buf.write("  HVM:\n")
+      buf.write("    - boot order: %s\n" % instance["hvm_boot_order"])
+      buf.write("    - ACPI support: %s\n" % instance["hvm_acpi"])
+      buf.write("    - PAE support: %s\n" % instance["hvm_pae"])
+      buf.write("    - virtual CDROM: %s\n" % instance["hvm_cdrom_image_path"])
+      buf.write("    - virtual NIC type: %s\n" %  instance["hvm_nic_type"])
+      buf.write("    - virtual disk type: %s\n" %  instance["hvm_disk_type"])
+    if instance.has_key("vnc_bind_address"):
+      buf.write("  VNC bind address: %s\n" % instance["vnc_bind_address"])
+      buf.write("  VNC console port: %s\n" % instance["vnc_console_port"])
     buf.write("  Hardware:\n")
     buf.write("    - VCPUs: %d\n" % instance["vcpus"])
     buf.write("    - memory: %dMiB\n" % instance["memory"])
@@ -670,23 +814,61 @@ def SetInstanceParms(opts, args):
 
   """
   if not (opts.mem or opts.vcpus or opts.ip or opts.bridge or opts.mac or
-          opts.kernel_path or opts.initrd_path or opts.hvm_boot_order):
+          opts.kernel_path or opts.initrd_path or opts.hvm_boot_order or
+          opts.hvm_acpi or opts.hvm_pae or opts.hvm_cdrom_image_path or
+          opts.vnc_bind_address or opts.hvm_nic_type or opts.hvm_disk_type or
+          opts.auto_balance):
     logger.ToStdout("Please give at least one of the parameters.")
     return 1
 
   kernel_path = _TransformPath(opts.kernel_path)
   initrd_path = _TransformPath(opts.initrd_path)
-  if opts.hvm_boot_order.lower() == 'default':
+  if opts.hvm_boot_order == 'default':
     hvm_boot_order = constants.VALUE_DEFAULT
   else:
     hvm_boot_order = opts.hvm_boot_order
 
+  if opts.hvm_acpi is None:
+    hvm_acpi = opts.hvm_acpi
+  else:
+    hvm_acpi = opts.hvm_acpi == _VALUE_TRUE
+
+  if opts.hvm_pae is None:
+    hvm_pae = opts.hvm_pae
+  else:
+    hvm_pae = opts.hvm_pae == _VALUE_TRUE
+
+  if opts.hvm_nic_type == constants.VALUE_NONE:
+    hvm_nic_type = None
+  else:
+    hvm_nic_type = opts.hvm_nic_type
+
+  if opts.hvm_disk_type == constants.VALUE_NONE:
+    hvm_disk_type = None
+  else:
+    hvm_disk_type = opts.hvm_disk_type
+
+  if opts.auto_balance is None:
+    auto_balance = opts.auto_balance
+  else:
+    auto_balance = opts.auto_balance == _VALUE_TRUE
+
+
   op = opcodes.OpSetInstanceParms(instance_name=args[0], mem=opts.mem,
                                   vcpus=opts.vcpus, ip=opts.ip,
                                   bridge=opts.bridge, mac=opts.mac,
                                   kernel_path=opts.kernel_path,
                                   initrd_path=opts.initrd_path,
-                                  hvm_boot_order=hvm_boot_order)
+                                  hvm_boot_order=hvm_boot_order,
+                                  hvm_acpi=hvm_acpi, hvm_pae=hvm_pae,
+                                  hvm_cdrom_image_path=
+                                  opts.hvm_cdrom_image_path,
+                                  vnc_bind_address=opts.vnc_bind_address,
+                                  hvm_nic_type=hvm_nic_type,
+                                  hvm_disk_type=hvm_disk_type,
+                                  force=opts.force,
+                                  auto_balance=auto_balance)
+
   result = SubmitOpCode(op)
 
   if result:
@@ -778,13 +960,46 @@ add_opts = [
               default=None,
               type="string", metavar="<FILENAME>"),
   make_option("--hvm-boot-order", dest="hvm_boot_order",
-              help="boot device order for HVM (one or more of [acdn])",
+              help="Boot device order for HVM (one or more of [acdn])",
               default=None, type="string", metavar="<BOOTORDER>"),
+  make_option("--iallocator", metavar="<NAME>",
+              help="Select nodes for the instance automatically using the"
+              " <NAME> iallocator plugin", default=None, type="string"),
+  make_option("--hvm-acpi", dest="hvm_acpi",
+              help="ACPI support for HVM (true|false)",
+              metavar="<BOOL>", choices=["true", "false"]),
+  make_option("--hvm-nic-type", dest="hvm_nic_type",
+              help="Type of virtual NIC for HVM "
+              "(rtl8139,ne2k_pci,ne2k_isa,paravirtual)",
+              metavar="NICTYPE", choices=[constants.HT_HVM_NIC_RTL8139,
+                                          constants.HT_HVM_NIC_NE2K_PCI,
+                                          constants.HT_HVM_NIC_NE2K_ISA,
+                                          constants.HT_HVM_DEV_PARAVIRTUAL],
+              default=constants.HT_HVM_NIC_RTL8139),
+  make_option("--hvm-disk-type", dest="hvm_disk_type",
+              help="Type of virtual disks for HVM (ioemu,paravirtual)",
+              metavar="DISKTYPE", choices=[constants.HT_HVM_DEV_IOEMU,
+                                           constants.HT_HVM_DEV_PARAVIRTUAL],
+              default=constants.HT_HVM_DEV_IOEMU,),
+  make_option("--hvm-pae", dest="hvm_pae",
+              help="PAE support for HVM (true|false)",
+              metavar="<BOOL>", choices=["true", "false"]),
+  make_option("--hvm-cdrom-image-path", dest="hvm_cdrom_image_path",
+              help="CDROM image path for HVM (absolute path or None)",
+              default=None, type="string", metavar="<CDROMIMAGE>"),
+  make_option("--vnc-bind-address", dest="vnc_bind_address",
+              help="bind address for VNC (IP address)",
+              default=None, type="string", metavar="<VNCADDRESS>"),
+  make_option("--auto-balance", dest="auto_balance",
+              help="consider instance memory requirements for"
+              " failover in cluster verify (true|false)",
+              default=_VALUE_TRUE,
+              metavar="<BOOL>", choices=["true", "false"]),
   ]
 
 commands = {
   'add': (AddInstance, ARGS_ONE, add_opts,
-          "[opts...] <name>",
+          "[...] -t disk-type -n node[:secondary-node] -o os-type <name>",
           "Creates and adds a new instance to the cluster"),
   'add-mirror': (AddMDDRBDComponent, ARGS_ONE,
                 [DEBUG_OPT, node_opt,
@@ -805,14 +1020,46 @@ commands = {
                 ],
                "[-f] <instance>",
                "Stops the instance and starts it on the backup node, using"
-               " the remote mirror (only for instances of type remote_raid1)"),
+               " the remote mirror (only for instances of type drbd or"
+               " remote_raid1)"),
+  'migrate': (MigrateInstance, ARGS_ONE,
+               [DEBUG_OPT, FORCE_OPT,
+                make_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)"),
+                make_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"),
+                ],
+               "[-f] <instance>",
+               "Migrate instance to its secondary node"
+               " (only for instances of type drbd)"),
   'info': (ShowInstanceConfig, ARGS_ANY, [DEBUG_OPT], "[<instance>...]",
            "Show information on the specified instance"),
   'list': (ListInstances, ARGS_NONE,
-           [DEBUG_OPT, NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT],
-           "", "Lists the instances and their status"),
-  'reinstall': (ReinstallInstance, ARGS_ONE, [DEBUG_OPT, FORCE_OPT, os_opt],
-                "[-f] <instance>", "Reinstall the instance"),
+           [DEBUG_OPT, NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT], "",
+           "Lists the instances and their status. The available fields are"
+           " (see the man page for details): status, oper_state, oper_ram,"
+           " name, os, pnode, snodes, admin_state, admin_ram, disk_template,"
+           " ip, mac, bridge, sda_size, sdb_size, vcpus, auto_balance."
+           " The default field"
+           " list is (in order): %s." % ", ".join(_LIST_DEF_FIELDS),
+           ),
+  'reinstall': (ReinstallInstance, ARGS_ONE,
+                [DEBUG_OPT, FORCE_OPT, os_opt,
+                 make_option("--interactive", dest="interactive",
+                             action="store_true", default=False,
+                             help="Interactive reinstall, lists available"
+                             " OS templates for selection")],
+                "[-f] <instance>", "Reinstall a stopped instance"),
   'remove': (RemoveInstance, ARGS_ONE,
              [DEBUG_OPT, FORCE_OPT,
               make_option("--ignore-failures", dest="ignore_failures",
@@ -859,8 +1106,14 @@ commands = {
                                  help=("Comma-separated list of disks"
                                        " to replace (e.g. sda) (optional,"
                                        " defaults to all disks")),
+                     make_option("--iallocator", metavar="<NAME>",
+                                 help="Select new secondary for the instance"
+                                 " automatically using the"
+                                 " <NAME> iallocator plugin (enables"
+                                 " secondary node replacement)",
+                                 default=None, type="string"),
                      ],
-                    "[-n NODE] <instance>",
+                    "[-s|-p|-n NODE] <instance>",
                     "Replaces all disks for the instance"),
   'modify': (SetInstanceParms, ARGS_ONE,
              [DEBUG_OPT, FORCE_OPT,
@@ -891,6 +1144,41 @@ commands = {
                           help="boot device order for HVM"
                           "(either one or more of [acdn] or 'default')",
                           default=None, type="string", metavar="<BOOTORDER>"),
+              make_option("--hvm-acpi", dest="hvm_acpi",
+                          help="ACPI support for HVM (true|false)",
+                          metavar="<BOOL>", choices=["true", "false"]),
+              make_option("--hvm-pae", dest="hvm_pae",
+                          help="PAE support for HVM (true|false)",
+                          metavar="<BOOL>", choices=["true", "false"]),
+              make_option("--hvm-cdrom-image-path",
+                          dest="hvm_cdrom_image_path",
+                          help="CDROM image path for HVM"
+                          "(absolute path or None)",
+                          default=None, type="string", metavar="<CDROMIMAGE>"),
+              make_option("--hvm-nic-type", dest="hvm_nic_type",
+                          help="Type of virtual NIC for HVM "
+                          "(rtl8139,ne2k_pci,ne2k_isa,paravirtual)",
+                          metavar="NICTYPE",
+                          choices=[constants.HT_HVM_NIC_RTL8139,
+                                   constants.HT_HVM_NIC_NE2K_PCI,
+                                   constants.HT_HVM_NIC_NE2K_ISA,
+                                   constants.HT_HVM_DEV_PARAVIRTUAL],
+                          default=None),
+              make_option("--hvm-disk-type", dest="hvm_disk_type",
+                          help="Type of virtual disks for HVM "
+                          "(ioemu,paravirtual)",
+                          metavar="DISKTYPE",
+                          choices=[constants.HT_HVM_DEV_IOEMU,
+                                   constants.HT_HVM_DEV_PARAVIRTUAL],
+                          default=None),
+              make_option("--vnc-bind-address", dest="vnc_bind_address",
+                          help="bind address for VNC (IP address)",
+                          default=None, type="string", metavar="<VNCADDRESS>"),
+              make_option("--auto-balance", dest="auto_balance",
+                          help="consider instance memory requirements for"
+                          " failover in cluster verify (true|false)",
+                          default=None,
+                          metavar="<BOOL>", choices=["true", "false"]),
               ],
              "<instance>", "Alters the parameters of an instance"),
   'shutdown': (ShutdownInstance, ARGS_ANY,
@@ -929,6 +1217,14 @@ commands = {
   'deactivate-disks': (DeactivateDisks, ARGS_ONE, [DEBUG_OPT],
                        "<instance>",
                        "Deactivate an instance's disks"),
+  'grow-disk': (GrowDisk, ARGS_FIXED(3),
+                [DEBUG_OPT,
+                 make_option("--no-wait-for-sync",
+                             dest="wait_for_sync", default=True,
+                             action="store_false",
+                             help="Don't wait for sync (DANGEROUS!)"),
+                 ],
+                "<instance> <disk> <size>", "Grow an instance's disk"),
   'list-tags': (ListTags, ARGS_ONE, [DEBUG_OPT],
                 "<node_name>", "List the tags of the given instance"),
   'add-tags': (AddTags, ARGS_ATLEAST(1), [DEBUG_OPT, TAG_SRC_OPT],
@@ -937,6 +1233,13 @@ commands = {
                   "<node_name> tag...", "Remove tags from given instance"),
   }
 
+aliases = {
+  'activate_block_devs': 'activate-disks',
+  'replace_disks': 'replace-disks',
+  'start': 'startup',
+  'stop': 'shutdown',
+  }
+
 if __name__ == '__main__':
-  sys.exit(GenericMain(commands,
+  sys.exit(GenericMain(commands, aliases=aliases,
                        override={"tag_type": constants.TAG_INSTANCE}))