grow-disk: wait until resync is completed
[ganeti-local] / scripts / gnt-instance
index eb97521..e7528fb 100755 (executable)
@@ -40,6 +40,13 @@ _SHUTDOWN_NODES_SEC = "nodes-sec"
 _SHUTDOWN_INSTANCES = "instances"
 
 
 _SHUTDOWN_INSTANCES = "instances"
 
 
+_VALUE_TRUE = "true"
+
+_LIST_DEF_FIELDS = [
+  "name", "hypervisor", "os", "pnode", "status", "oper_ram",
+  ]
+
+
 def _ExpandMultiNames(mode, names):
   """Expand the given names using the passed mode.
 
 def _ExpandMultiNames(mode, names):
   """Expand the given names using the passed mode.
 
@@ -62,8 +69,8 @@ def _ExpandMultiNames(mode, names):
   if mode == _SHUTDOWN_CLUSTER:
     if names:
       raise errors.OpPrereqError("Cluster filter mode takes no arguments")
   if mode == _SHUTDOWN_CLUSTER:
     if names:
       raise errors.OpPrereqError("Cluster filter mode takes no arguments")
-    op = opcodes.OpQueryInstances(output_fields=["name"], names=[])
-    idata = SubmitOpCode(op)
+    client = GetClient()
+    idata = client.QueryInstances([], ["name"])
     inames = [row[0] for row in idata]
 
   elif mode in (_SHUTDOWN_NODES_BOTH,
     inames = [row[0] for row in idata]
 
   elif mode in (_SHUTDOWN_NODES_BOTH,
@@ -71,9 +78,8 @@ def _ExpandMultiNames(mode, names):
                 _SHUTDOWN_NODES_SEC):
     if not names:
       raise errors.OpPrereqError("No node names passed")
                 _SHUTDOWN_NODES_SEC):
     if not names:
       raise errors.OpPrereqError("No node names passed")
-    op = opcodes.OpQueryNodes(output_fields=["name", "pinst_list",
-                                             "sinst_list"], names=names)
-    ndata = SubmitOpCode(op)
+    client = GetClient()
+    ndata = client.QueryNodes(names, ["name", "pinst_list", "sinst_list"])
     ipri = [row[1] for row in ndata]
     pri_names = list(itertools.chain(*ipri))
     isec = [row[2] for row in ndata]
     ipri = [row[1] for row in ndata]
     pri_names = list(itertools.chain(*ipri))
     isec = [row[2] for row in ndata]
@@ -90,8 +96,8 @@ def _ExpandMultiNames(mode, names):
   elif mode == _SHUTDOWN_INSTANCES:
     if not names:
       raise errors.OpPrereqError("No instance names passed")
   elif mode == _SHUTDOWN_INSTANCES:
     if not names:
       raise errors.OpPrereqError("No instance names passed")
-    op = opcodes.OpQueryInstances(output_fields=["name"], names=names)
-    idata = SubmitOpCode(op)
+    client = GetClient()
+    idata = client.QueryInstances(names, ["name"])
     inames = [row[0] for row in idata]
 
   else:
     inames = [row[0] for row in idata]
 
   else:
@@ -163,34 +169,52 @@ def ListInstances(opts, args):
 
   """
   if opts.output is None:
 
   """
   if opts.output is None:
-    selected_fields = ["name", "os", "pnode", "status", "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(",")
 
   else:
     selected_fields = opts.output.split(",")
 
-  op = opcodes.OpQueryInstances(output_fields=selected_fields, names=[])
-  output = SubmitOpCode(op)
+  output = GetClient().QueryInstances([], selected_fields)
 
   if not opts.no_headers:
     headers = {
       "name": "Instance", "os": "OS", "pnode": "Primary_node",
       "snodes": "Secondary_Nodes", "admin_state": "Autostart",
 
   if not opts.no_headers:
     headers = {
       "name": "Instance", "os": "OS", "pnode": "Primary_node",
       "snodes": "Secondary_Nodes", "admin_state": "Autostart",
-      "oper_state": "Running", "admin_ram": "Configured_memory",
+      "oper_state": "Running",
       "oper_ram": "Memory", "disk_template": "Disk_template",
       "oper_ram": "Memory", "disk_template": "Disk_template",
-      "ip": "IP Address", "mac": "MAC Address",
-      "bridge": "Bridge", "vcpus": "VCPUs",
+      "ip": "IP_address", "mac": "MAC_address",
+      "bridge": "Bridge",
       "sda_size": "Disk/0", "sdb_size": "Disk/1",
       "sda_size": "Disk/0", "sdb_size": "Disk/1",
-      "status": "Status",
+      "status": "Status", "tags": "Tags",
+      "network_port": "Network_port",
+      "hv/kernel_path": "Kernel_path",
+      "hv/initrd_path": "Initrd_path",
+      "hv/boot_order": "HVM_boot_order",
+      "hv/acpi": "HVM_ACPI",
+      "hv/pae": "HVM_PAE",
+      "hv/cdrom_image_path": "HVM_CDROM_image_path",
+      "hv/nic_type": "HVM_NIC_type",
+      "hv/disk_type": "HVM_Disk_type",
+      "vnc_bind_address": "VNC_bind_address",
+      "serial_no": "SerialNo", "hypervisor": "Hypervisor",
+      "hvparams": "Hypervisor_parameters",
+      "be/memory": "Configured_memory",
+      "be/vcpus": "VCPUs",
+      "be/auto_balance": "Auto_balance",
       }
   else:
     headers = None
 
   if opts.human_readable:
       }
   else:
     headers = None
 
   if opts.human_readable:
-    unitfields = ["admin_ram", "oper_ram", "sda_size", "sdb_size"]
+    unitfields = ["be/memory", "oper_ram", "sda_size", "sdb_size"]
   else:
     unitfields = None
 
   else:
     unitfields = None
 
-  numfields = ["admin_ram", "oper_ram", "sda_size", "sdb_size", "vcpus"]
+  numfields = ["be/memory", "oper_ram", "sda_size", "sdb_size", "be/vcpus",
+               "serial_no"]
 
 
+  list_type_fields = ("tags",)
   # change raw values to nicer strings
   for row in output:
     for idx, field in enumerate(selected_fields):
   # change raw values to nicer strings
   for row in output:
     for idx, field in enumerate(selected_fields):
@@ -215,6 +239,10 @@ def ListInstances(opts, args):
       elif field == "sda_size" or field == "sdb_size":
         if val is None:
           val = "N/A"
       elif field == "sda_size" or field == "sdb_size":
         if val is None:
           val = "N/A"
+      elif field in list_type_fields:
+        val = ",".join(val)
+      elif val is None:
+        val = "-"
       row[idx] = str(val)
 
   data = GenerateTable(separator=opts.separator, headers=headers,
       row[idx] = str(val)
 
   data = GenerateTable(separator=opts.separator, headers=headers,
@@ -244,26 +272,44 @@ def AddInstance(opts, args):
 
   (pnode, snode) = SplitNodeOption(opts.node)
 
 
   (pnode, snode) = SplitNodeOption(opts.node)
 
-  kernel_path = _TransformPath(opts.kernel_path)
-  initrd_path = _TransformPath(opts.initrd_path)
+  hypervisor = None
+  hvparams = {}
+  if opts.hypervisor:
+    hypervisor, hvparams = opts.hypervisor
+
+  bep = ValidateBeParams(opts.beparams)
 
 
-  op = opcodes.OpCreateInstance(instance_name=instance, mem_size=opts.mem,
+##  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
+
+  op = opcodes.OpCreateInstance(instance_name=instance,
                                 disk_size=opts.size, swap_size=opts.swap,
                                 disk_template=opts.disk_template,
                                 mode=constants.INSTANCE_CREATE,
                                 os_type=opts.os, pnode=pnode,
                                 disk_size=opts.size, swap_size=opts.swap,
                                 disk_template=opts.disk_template,
                                 mode=constants.INSTANCE_CREATE,
                                 os_type=opts.os, pnode=pnode,
-                                snode=snode, vcpus=opts.vcpus,
+                                snode=snode,
                                 ip=opts.ip, bridge=opts.bridge,
                                 start=opts.start, ip_check=opts.ip_check,
                                 wait_for_sync=opts.wait_for_sync,
                                 mac=opts.mac,
                                 ip=opts.ip, bridge=opts.bridge,
                                 start=opts.start, ip_check=opts.ip_check,
                                 wait_for_sync=opts.wait_for_sync,
                                 mac=opts.mac,
-                                kernel_path=kernel_path,
-                                initrd_path=initrd_path,
-                                hvm_boot_order=opts.hvm_boot_order,
-                                file_storage_dir = opts.file_storage_dir,
-                                file_driver = opts.file_driver,
-                                iallocator=opts.iallocator)
-  SubmitOpCode(op)
+                                hypervisor=hypervisor,
+                                hvparams=hvparams,
+                                beparams=opts.beparams,
+                                iallocator=opts.iallocator,
+                                file_storage_dir=opts.file_storage_dir,
+                                file_driver=opts.file_driver,
+                                )
+
+  SubmitOrSend(op, opts)
   return 0
 
 
   return 0
 
 
@@ -277,6 +323,34 @@ def ReinstallInstance(opts, args):
   """
   instance_name = args[0]
 
   """
   instance_name = args[0]
 
+  if opts.select_os 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
   if not opts.force:
     usertext = ("This will reinstall the instance %s and remove"
                 " all data. Continue?") % instance_name
@@ -284,8 +358,8 @@ def ReinstallInstance(opts, args):
       return 1
 
   op = opcodes.OpReinstallInstance(instance_name=instance_name,
       return 1
 
   op = opcodes.OpReinstallInstance(instance_name=instance_name,
-                                   os_type=opts.os)
-  SubmitOpCode(op)
+                                   os_type=os)
+  SubmitOrSend(op, opts)
 
   return 0
 
 
   return 0
 
@@ -310,7 +384,7 @@ def RemoveInstance(opts, args):
 
   op = opcodes.OpRemoveInstance(instance_name=instance_name,
                                 ignore_failures=opts.ignore_failures)
 
   op = opcodes.OpRemoveInstance(instance_name=instance_name,
                                 ignore_failures=opts.ignore_failures)
-  SubmitOpCode(op)
+  SubmitOrSend(op, opts)
   return 0
 
 
   return 0
 
 
@@ -325,8 +399,7 @@ def RenameInstance(opts, args):
   op = opcodes.OpRenameInstance(instance_name=args[0],
                                 new_name=args[1],
                                 ignore_ip=opts.ignore_ip)
   op = opcodes.OpRenameInstance(instance_name=args[0],
                                 new_name=args[1],
                                 ignore_ip=opts.ignore_ip)
-  SubmitOpCode(op)
-
+  SubmitOrSend(op, opts)
   return 0
 
 
   return 0
 
 
@@ -341,7 +414,7 @@ def ActivateDisks(opts, args):
   """
   instance_name = args[0]
   op = opcodes.OpActivateInstanceDisks(instance_name=instance_name)
   """
   instance_name = args[0]
   op = opcodes.OpActivateInstanceDisks(instance_name=instance_name)
-  disks_info = SubmitOpCode(op)
+  disks_info = SubmitOrSend(op, opts)
   for host, iname, nname in disks_info:
     print "%s:%s:%s" % (host, iname, nname)
   return 0
   for host, iname, nname in disks_info:
     print "%s:%s:%s" % (host, iname, nname)
   return 0
@@ -356,7 +429,23 @@ def DeactivateDisks(opts, args):
   """
   instance_name = args[0]
   op = opcodes.OpDeactivateInstanceDisks(instance_name=instance_name)
   """
   instance_name = args[0]
   op = opcodes.OpDeactivateInstanceDisks(instance_name=instance_name)
-  SubmitOpCode(op)
+  SubmitOrSend(op, opts)
+  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)
+  SubmitOrSend(op, opts)
   return 0
 
 
   return 0
 
 
@@ -383,7 +472,11 @@ def StartupInstance(opts, args):
                                    extra_args=opts.extra_args)
     if multi_on:
       logger.ToStdout("Starting up %s" % name)
                                    extra_args=opts.extra_args)
     if multi_on:
       logger.ToStdout("Starting up %s" % name)
-    SubmitOpCode(op)
+    try:
+      SubmitOrSend(op, opts)
+    except JobSubmittedException, err:
+      _, txt = FormatError(err)
+      logger.ToStdout("%s" % txt)
   return 0
 
 
   return 0
 
 
@@ -409,7 +502,7 @@ def RebootInstance(opts, args):
                                   reboot_type=opts.reboot_type,
                                   ignore_secondaries=opts.ignore_secondaries)
 
                                   reboot_type=opts.reboot_type,
                                   ignore_secondaries=opts.ignore_secondaries)
 
-    SubmitOpCode(op)
+    SubmitOrSend(op, opts)
   return 0
 
 
   return 0
 
 
@@ -434,7 +527,11 @@ def ShutdownInstance(opts, args):
     op = opcodes.OpShutdownInstance(instance_name=name)
     if multi_on:
       logger.ToStdout("Shutting down %s" % name)
     op = opcodes.OpShutdownInstance(instance_name=name)
     if multi_on:
       logger.ToStdout("Shutting down %s" % name)
-    SubmitOpCode(op)
+    try:
+      SubmitOrSend(op, opts)
+    except JobSubmittedException, err:
+      _, txt = FormatError(err)
+      logger.ToStdout("%s" % txt)
   return 0
 
 
   return 0
 
 
@@ -448,6 +545,7 @@ def ReplaceDisks(opts, args):
   """
   instance_name = args[0]
   new_2ndary = opts.new_secondary
   """
   instance_name = args[0]
   new_2ndary = opts.new_secondary
+  iallocator = opts.iallocator
   if opts.disks is None:
     disks = ["sda", "sdb"]
   else:
   if opts.disks is None:
     disks = ["sda", "sdb"]
   else:
@@ -456,15 +554,17 @@ def ReplaceDisks(opts, args):
     mode = constants.REPLACE_DISK_ALL
   elif opts.on_primary: # only on primary:
     mode = constants.REPLACE_DISK_PRI
     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")
       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,
     mode = constants.REPLACE_DISK_SEC
 
   op = opcodes.OpReplaceDisks(instance_name=args[0], disks=disks,
-                              remote_node=new_2ndary, mode=mode)
-  SubmitOpCode(op)
+                              remote_node=new_2ndary, mode=mode,
+                              iallocator=iallocator)
+  SubmitOrSend(op, opts)
   return 0
 
 
   return 0
 
 
@@ -493,7 +593,7 @@ def FailoverInstance(opts, args):
 
   op = opcodes.OpFailoverInstance(instance_name=instance_name,
                                   ignore_consistency=opts.ignore_consistency)
 
   op = opcodes.OpFailoverInstance(instance_name=instance_name,
                                   ignore_consistency=opts.ignore_consistency)
-  SubmitOpCode(op)
+  SubmitOrSend(op, opts)
   return 0
 
 
   return 0
 
 
@@ -513,8 +613,6 @@ def ConnectToInstanceConsole(opts, args):
   if opts.show_command:
     print utils.ShellQuoteArgs(cmd)
   else:
   if opts.show_command:
     print utils.ShellQuoteArgs(cmd)
   else:
-    # drop lock and exec so other commands can run while we have console
-    utils.Unlock("cmd")
     try:
       os.execvp(cmd[0], cmd)
     finally:
     try:
       os.execvp(cmd[0], cmd)
     finally:
@@ -523,7 +621,7 @@ def ConnectToInstanceConsole(opts, args):
       os._exit(1)
 
 
       os._exit(1)
 
 
-def _FormatBlockDevInfo(buf, dev, indent_level):
+def _FormatBlockDevInfo(buf, dev, indent_level, static):
   """Show block device information.
 
   This is only used by ShowInstanceConfig(), but it's too big to be
   """Show block device information.
 
   This is only used by ShowInstanceConfig(), but it's too big to be
@@ -536,8 +634,18 @@ def _FormatBlockDevInfo(buf, dev, indent_level):
       buf.write("not active\n")
     else:
       (path, major, minor, syncp, estt, degr, ldisk) = status
       buf.write("not active\n")
     else:
       (path, major, minor, syncp, estt, degr, ldisk) = status
-      buf.write("%s (%d:%d)" % (path, major, minor))
-      if dtype in (constants.LD_MD_R1, constants.LD_DRBD7, constants.LD_DRBD8):
+      if major is None:
+        major_string = "N/A"
+      else:
+        major_string = str(major)
+
+      if minor is None:
+        minor_string = "N/A"
+      else:
+        minor_string = str(minor)
+
+      buf.write("%s (%s:%s)" % (path, major_string, minor_string))
+      if dtype in (constants.LD_DRBD8, ):
         if syncp is not None:
           sync_text = "*RECOVERING* %5.2f%%," % syncp
           if estt:
         if syncp is not None:
           sync_text = "*RECOVERING* %5.2f%%," % syncp
           if estt:
@@ -573,16 +681,17 @@ def _FormatBlockDevInfo(buf, dev, indent_level):
   elif dev["physical_id"] is not None:
     data += ", physical_id: %s" % (dev["physical_id"],)
   buf.write("%*s%s\n" % (2*indent_level, "", data))
   elif dev["physical_id"] is not None:
     data += ", physical_id: %s" % (dev["physical_id"],)
   buf.write("%*s%s\n" % (2*indent_level, "", data))
-  buf.write("%*s    primary:   " % (2*indent_level, ""))
-  helper(buf, dev["dev_type"], dev["pstatus"])
+  if not static:
+    buf.write("%*s    primary:   " % (2*indent_level, ""))
+    helper(buf, dev["dev_type"], dev["pstatus"])
 
 
-  if dev["sstatus"]:
+  if dev["sstatus"] and not static:
     buf.write("%*s    secondary: " % (2*indent_level, ""))
     helper(buf, dev["dev_type"], dev["sstatus"])
 
   if dev["children"]:
     for child in dev["children"]:
     buf.write("%*s    secondary: " % (2*indent_level, ""))
     helper(buf, dev["dev_type"], dev["sstatus"])
 
   if dev["children"]:
     for child in dev["children"]:
-      _FormatBlockDevInfo(buf, child, indent_level+1)
+      _FormatBlockDevInfo(buf, child, indent_level+1, static)
 
 
 def ShowInstanceConfig(opts, args):
 
 
 def ShowInstanceConfig(opts, args):
@@ -590,9 +699,8 @@ def ShowInstanceConfig(opts, args):
 
   """
   retcode = 0
 
   """
   retcode = 0
-  op = opcodes.OpQueryInstanceData(instances=args)
+  op = opcodes.OpQueryInstanceData(instances=args, static=opts.static)
   result = SubmitOpCode(op)
   result = SubmitOpCode(op)
-
   if not result:
     logger.ToStdout("No instances.")
     return 1
   if not result:
     logger.ToStdout("No instances.")
     return 1
@@ -602,37 +710,68 @@ def ShowInstanceConfig(opts, args):
   for instance_name in result:
     instance = result[instance_name]
     buf.write("Instance name: %s\n" % instance["name"])
   for instance_name in result:
     instance = result[instance_name]
     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("State: configured to be %s" % instance["config_state"])
+    if not opts.static:
+      buf.write(", actual state is %s" % instance["run_state"])
+    buf.write("\n")
+    ##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("  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)"
+    if instance.has_key("network_port"):
+      buf.write("  Allocated network port: %s\n" % instance["network_port"])
+    buf.write("  Hypervisor: %s\n" % instance["hypervisor"])
+    if instance["hypervisor"] == constants.HT_XEN_PVM:
+      hvattrs = ((constants.HV_KERNEL_PATH, "kernel path"),
+                 (constants.HV_INITRD_PATH, "initrd path"))
+    elif instance["hypervisor"] == constants.HT_XEN_HVM:
+      hvattrs = ((constants.HV_BOOT_ORDER, "boot order"),
+                 (constants.HV_ACPI, "ACPI"),
+                 (constants.HV_PAE, "PAE"),
+                 (constants.HV_CDROM_IMAGE_PATH, "virtual CDROM"),
+                 (constants.HV_NIC_TYPE, "NIC type"),
+                 (constants.HV_DISK_TYPE, "Disk type"),
+                 (constants.HV_VNC_BIND_ADDRESS, "VNC bind address"),
+                 )
+      # custom console information for HVM
+      vnc_bind_address = instance["hv_actual"][constants.HV_VNC_BIND_ADDRESS]
+      if vnc_bind_address == constants.BIND_ADDRESS_GLOBAL:
+        vnc_console_port = "%s:%s" % (instance["pnode"],
+                                      instance["network_port"])
+      elif vnc_bind_address == constants.LOCALHOST_IP_ADDRESS:
+        vnc_console_port = "%s:%s on node %s" % (vnc_bind_address,
+                                                 instance["network_port"],
+                                                 instance["pnode"])
+      else:
+        vnc_console_port = "%s:%s" % (vnc_bind_address,
+                                      instance["network_port"])
+      buf.write("    - console connection: vnc to %s\n" % vnc_console_port)
+
     else:
     else:
-      initrd = instance["initrd_path"]
-    buf.write("       initrd: %s\n" % initrd)
-    buf.write("  HVM boot order: %s\n" % instance["hvm_boot_order"])
+      # auto-handle other hypervisor types
+      hvattrs = [(key, key) for key in instance["hv_actual"]]
+
+    for key, desc in hvattrs:
+      if key in instance["hv_instance"]:
+        val = instance["hv_instance"][key]
+      else:
+        val = "default (%s)" % instance["hv_actual"][key]
+      buf.write("    - %s: %s\n" % (desc, val))
     buf.write("  Hardware:\n")
     buf.write("  Hardware:\n")
-    buf.write("    - VCPUs: %d\n" % instance["vcpus"])
-    buf.write("    - memory: %dMiB\n" % instance["memory"])
+    buf.write("    - VCPUs: %d\n" %
+              instance["be_actual"][constants.BE_VCPUS])
+    buf.write("    - memory: %dMiB\n" %
+              instance["be_actual"][constants.BE_MEMORY])
     buf.write("    - NICs: %s\n" %
     buf.write("    - NICs: %s\n" %
-        ", ".join(["{MAC: %s, IP: %s, bridge: %s}" %
-                   (mac, ip, bridge)
-                     for mac, ip, bridge in instance["nics"]]))
+              ", ".join(["{MAC: %s, IP: %s, bridge: %s}" %
+                         (mac, ip, bridge)
+                         for mac, ip, bridge in instance["nics"]]))
     buf.write("  Block devices:\n")
 
     for device in instance["disks"]:
     buf.write("  Block devices:\n")
 
     for device in instance["disks"]:
-      _FormatBlockDevInfo(buf, device, 1)
+      _FormatBlockDevInfo(buf, device, 1, opts.static)
 
   logger.ToStdout(buf.getvalue().rstrip('\n'))
   return retcode
 
   logger.ToStdout(buf.getvalue().rstrip('\n'))
   return retcode
@@ -647,30 +786,23 @@ def SetInstanceParams(opts, args):
     opts - class with options as members
     args - list with a single element, the instance name
   Opts used:
     opts - class with options as members
     args - list with a single element, the instance name
   Opts used:
-    memory - the new memory size
-    vcpus - the new number of cpus
     mac - the new MAC address of the instance
 
   """
   if not (opts.mem or opts.vcpus or opts.ip or opts.bridge or opts.mac or
     mac - the new MAC address of the instance
 
   """
   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.hypervisor):
     logger.ToStdout("Please give at least one of the parameters.")
     return 1
 
     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 == 'default':
-    hvm_boot_order = constants.VALUE_DEFAULT
-  else:
-    hvm_boot_order = opts.hvm_boot_order
-
-  op = opcodes.OpSetInstanceParams(instance_name=args[0], mem=opts.mem,
-                                   vcpus=opts.vcpus, ip=opts.ip,
+  op = opcodes.OpSetInstanceParams(instance_name=args[0],
+                                   ip=opts.ip,
                                    bridge=opts.bridge, mac=opts.mac,
                                    bridge=opts.bridge, mac=opts.mac,
-                                   kernel_path=opts.kernel_path,
-                                   initrd_path=opts.initrd_path,
-                                   hvm_boot_order=hvm_boot_order)
-  result = SubmitOpCode(op)
+                                   hvparams=opts.hypervisor,
+                                   beparams=opts.beparams,
+                                   force=opts.force)
+
+  # even if here we process the result, we allow submit only
+  result = SubmitOrSend(op, opts)
 
   if result:
     logger.ToStdout("Modified instance %s" % args[0])
 
   if result:
     logger.ToStdout("Modified instance %s" % args[0])
@@ -728,10 +860,9 @@ add_opts = [
              " suffix is used",
              default=4 * 1024, type="unit", metavar="<size>"),
   os_opt,
              " suffix is used",
              default=4 * 1024, type="unit", metavar="<size>"),
   os_opt,
-  cli_option("-m", "--memory", dest="mem", help="Memory size (in MiB)",
-              default=128, type="unit", metavar="<mem>"),
-  make_option("-p", "--cpu", dest="vcpus", help="Number of virtual CPUs",
-              default=1, type="int", metavar="<PROC>"),
+  keyval_option("-B", "--backend", dest="beparams",
+                type="keyval", default={},
+                help="Backend parameters"),
   make_option("-t", "--disk-template", dest="disk_template",
               help="Custom disk setup (diskless, file, plain or drbd)",
               default=None, metavar="TEMPL"),
   make_option("-t", "--disk-template", dest="disk_template",
               help="Custom disk setup (diskless, file, plain or drbd)",
               default=None, metavar="TEMPL"),
@@ -772,11 +903,19 @@ add_opts = [
   make_option("--iallocator", metavar="<NAME>",
               help="Select nodes for the instance automatically using the"
               " <NAME> iallocator plugin", default=None, type="string"),
   make_option("--iallocator", metavar="<NAME>",
               help="Select nodes for the instance automatically using the"
               " <NAME> iallocator plugin", default=None, type="string"),
+  ikv_option("-H", "--hypervisor", dest="hypervisor",
+              help="Hypervisor and hypervisor options, in the format"
+              " hypervisor:option=value,option=value,...", default=None,
+              type="identkeyval"),
+  make_option("--vnc-bind-address", dest="vnc_bind_address",
+              help="bind address for VNC (IP address)",
+              default=None, type="string", metavar="<VNCADDRESS>"),
+  SUBMIT_OPT,
   ]
 
 commands = {
   'add': (AddInstance, ARGS_ONE, add_opts,
   ]
 
 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"),
   'console': (ConnectToInstanceConsole, ARGS_ONE,
               [DEBUG_OPT,
           "Creates and adds a new instance to the cluster"),
   'console': (ConnectToInstanceConsole, ARGS_ONE,
               [DEBUG_OPT,
@@ -791,21 +930,36 @@ commands = {
                             action="store_true", default=False,
                             help="Ignore the consistency of the disks on"
                             " the secondary"),
                             action="store_true", default=False,
                             help="Ignore the consistency of the disks on"
                             " the secondary"),
+                SUBMIT_OPT,
                 ],
                "[-f] <instance>",
                "Stops the instance and starts it on the backup node, using"
                " the remote mirror (only for instances of type drbd)"),
                 ],
                "[-f] <instance>",
                "Stops the instance and starts it on the backup node, using"
                " the remote mirror (only for instances of type drbd)"),
-  'info': (ShowInstanceConfig, ARGS_ANY, [DEBUG_OPT], "[<instance>...]",
-           "Show information on the specified instance"),
+  'info': (ShowInstanceConfig, ARGS_ANY,
+           [DEBUG_OPT,
+            make_option("-s", "--static", dest="static",
+                        action="store_true", default=False,
+                        help="Only show configuration data, not runtime data"),
+            ], "[-s] [<instance>...]",
+           "Show information on the specified instance(s)"),
   'list': (ListInstances, ARGS_NONE,
            [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,"
   'list': (ListInstances, ARGS_NONE,
            [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. The default field"
-           " list is (in order): name, os, pnode, status,"
-           " oper_ram."),
-  'reinstall': (ReinstallInstance, ARGS_ONE, [DEBUG_OPT, FORCE_OPT, os_opt],
+           " ip, mac, bridge, sda_size, sdb_size, vcpus, serial_no,"
+           " hypervisor."
+           " The default field"
+           " list is (in order): %s." % ", ".join(_LIST_DEF_FIELDS),
+           ),
+  'reinstall': (ReinstallInstance, ARGS_ONE,
+                [DEBUG_OPT, FORCE_OPT, os_opt,
+                 make_option("--select-os", dest="select_os",
+                             action="store_true", default=False,
+                             help="Interactive OS reinstall, lists available"
+                             " OS templates for selection"),
+                 SUBMIT_OPT,
+                 ],
                 "[-f] <instance>", "Reinstall a stopped instance"),
   'remove': (RemoveInstance, ARGS_ONE,
              [DEBUG_OPT, FORCE_OPT,
                 "[-f] <instance>", "Reinstall a stopped instance"),
   'remove': (RemoveInstance, ARGS_ONE,
              [DEBUG_OPT, FORCE_OPT,
@@ -814,6 +968,7 @@ commands = {
                           help=("Remove the instance from the cluster even"
                                 " if there are failures during the removal"
                                 " process (shutdown, disk removal, etc.)")),
                           help=("Remove the instance from the cluster even"
                                 " if there are failures during the removal"
                                 " process (shutdown, disk removal, etc.)")),
+              SUBMIT_OPT,
               ],
              "[-f] <instance>", "Shuts down the instance and removes it"),
   'rename': (RenameInstance, ARGS_FIXED(2),
               ],
              "[-f] <instance>", "Shuts down the instance and removes it"),
   'rename': (RenameInstance, ARGS_FIXED(2),
@@ -822,6 +977,7 @@ commands = {
                           help="Do not check that the IP of the new name"
                           " is alive",
                           default=False, action="store_true"),
                           help="Do not check that the IP of the new name"
                           " is alive",
                           default=False, action="store_true"),
+              SUBMIT_OPT,
               ],
              "<instance> <new_name>", "Rename the instance"),
   'replace-disks': (ReplaceDisks, ARGS_ONE,
               ],
              "<instance> <new_name>", "Rename the instance"),
   'replace-disks': (ReplaceDisks, ARGS_ONE,
@@ -841,6 +997,13 @@ commands = {
                                  help=("Comma-separated list of disks"
                                        " to replace (e.g. sda) (optional,"
                                        " defaults to all disks")),
                                  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"),
+                     SUBMIT_OPT,
                      ],
                     "[-s|-p|-n NODE] <instance>",
                     "Replaces all disks for the instance"),
                      ],
                     "[-s|-p|-n NODE] <instance>",
                     "Replaces all disks for the instance"),
@@ -861,23 +1024,17 @@ commands = {
               make_option("--mac", dest="mac",
                           help="MAC address", default=None,
                           type="string", metavar="<MACADDRESS>"),
               make_option("--mac", dest="mac",
                           help="MAC address", default=None,
                           type="string", metavar="<MACADDRESS>"),
-              make_option("--kernel", dest="kernel_path",
-                          help="Path to the instances' kernel (or"
-                          " 'default')", default=None,
-                          type="string", metavar="<FILENAME>"),
-              make_option("--initrd", dest="initrd_path",
-                          help="Path to the instances' initrd (or 'none', or"
-                          " 'default')", default=None,
-                          type="string", metavar="<FILENAME>"),
-              make_option("--hvm-boot-order", dest="hvm_boot_order",
-                          help="boot device order for HVM"
-                          "(either one or more of [acdn] or 'default')",
-                          default=None, type="string", metavar="<BOOTORDER>"),
+              keyval_option("-H", "--hypervisor", type="keyval",
+                            default={}, dest="hypervisor",
+                            help="Change hypervisor parameters"),
+              SUBMIT_OPT,
               ],
              "<instance>", "Alters the parameters of an instance"),
   'shutdown': (ShutdownInstance, ARGS_ANY,
                [DEBUG_OPT, m_node_opt, m_pri_node_opt, m_sec_node_opt,
               ],
              "<instance>", "Alters the parameters of an instance"),
   'shutdown': (ShutdownInstance, ARGS_ANY,
                [DEBUG_OPT, m_node_opt, m_pri_node_opt, m_sec_node_opt,
-                m_clust_opt, m_inst_opt, m_force_multi],
+                m_clust_opt, m_inst_opt, m_force_multi,
+                SUBMIT_OPT,
+                ],
                "<instance>", "Stops an instance"),
   'startup': (StartupInstance, ARGS_ANY,
               [DEBUG_OPT, FORCE_OPT, m_force_multi,
                "<instance>", "Stops an instance"),
   'startup': (StartupInstance, ARGS_ANY,
               [DEBUG_OPT, FORCE_OPT, m_force_multi,
@@ -886,6 +1043,7 @@ commands = {
                            default=None, type="string", metavar="<PARAMS>"),
                m_node_opt, m_pri_node_opt, m_sec_node_opt,
                m_clust_opt, m_inst_opt,
                            default=None, type="string", metavar="<PARAMS>"),
                m_node_opt, m_pri_node_opt, m_sec_node_opt,
                m_clust_opt, m_inst_opt,
+               SUBMIT_OPT,
                ],
             "<instance>", "Starts an instance"),
 
                ],
             "<instance>", "Starts an instance"),
 
@@ -896,27 +1054,36 @@ commands = {
                            default=None, type="string", metavar="<PARAMS>"),
                make_option("-t", "--type", dest="reboot_type",
                            help="Type of reboot: soft/hard/full",
                            default=None, type="string", metavar="<PARAMS>"),
                make_option("-t", "--type", dest="reboot_type",
                            help="Type of reboot: soft/hard/full",
-                           default=constants.INSTANCE_REBOOT_SOFT,
+                           default=constants.INSTANCE_REBOOT_HARD,
                            type="string", metavar="<REBOOT>"),
                make_option("--ignore-secondaries", dest="ignore_secondaries",
                            default=False, action="store_true",
                            help="Ignore errors from secondaries"),
                m_node_opt, m_pri_node_opt, m_sec_node_opt,
                m_clust_opt, m_inst_opt,
                            type="string", metavar="<REBOOT>"),
                make_option("--ignore-secondaries", dest="ignore_secondaries",
                            default=False, action="store_true",
                            help="Ignore errors from secondaries"),
                m_node_opt, m_pri_node_opt, m_sec_node_opt,
                m_clust_opt, m_inst_opt,
+               SUBMIT_OPT,
                ],
             "<instance>", "Reboots an instance"),
                ],
             "<instance>", "Reboots an instance"),
-  'activate-disks': (ActivateDisks, ARGS_ONE, [DEBUG_OPT],
+  'activate-disks': (ActivateDisks, ARGS_ONE, [DEBUG_OPT, SUBMIT_OPT],
                      "<instance>",
                      "Activate an instance's disks"),
                      "<instance>",
                      "Activate an instance's disks"),
-  'deactivate-disks': (DeactivateDisks, ARGS_ONE, [DEBUG_OPT],
+  'deactivate-disks': (DeactivateDisks, ARGS_ONE, [DEBUG_OPT, SUBMIT_OPT],
                        "<instance>",
                        "Deactivate an instance's disks"),
                        "<instance>",
                        "Deactivate an instance's disks"),
+  'grow-disk': (GrowDisk, ARGS_FIXED(3),
+                [DEBUG_OPT, SUBMIT_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],
   'list-tags': (ListTags, ARGS_ONE, [DEBUG_OPT],
-                "<node_name>", "List the tags of the given instance"),
+                "<instance_name>", "List the tags of the given instance"),
   'add-tags': (AddTags, ARGS_ATLEAST(1), [DEBUG_OPT, TAG_SRC_OPT],
   'add-tags': (AddTags, ARGS_ATLEAST(1), [DEBUG_OPT, TAG_SRC_OPT],
-               "<node_name> tag...", "Add tags to the given instance"),
+               "<instance_name> tag...", "Add tags to the given instance"),
   'remove-tags': (RemoveTags, ARGS_ATLEAST(1), [DEBUG_OPT, TAG_SRC_OPT],
   'remove-tags': (RemoveTags, ARGS_ATLEAST(1), [DEBUG_OPT, TAG_SRC_OPT],
-                  "<node_name> tag...", "Remove tags from given instance"),
+                  "<instance_name> tag...", "Remove tags from given instance"),
   }
 
 aliases = {
   }
 
 aliases = {