Verify: fix ERROR message indentation
[ganeti-local] / lib / cmdlib.py
index 96736b7..3d61d9d 100644 (file)
@@ -413,7 +413,7 @@ class LUInitCluster(LogicalUnit):
   """
   HPATH = "cluster-init"
   HTYPE = constants.HTYPE_CLUSTER
-  _OP_REQP = ["cluster_name", "hypervisor_type", "vg_name", "mac_prefix",
+  _OP_REQP = ["cluster_name", "hypervisor_type", "mac_prefix",
               "def_bridge", "master_netdev", "file_storage_dir"]
   REQ_CLUSTER = False
 
@@ -472,11 +472,14 @@ class LUInitCluster(LogicalUnit):
                                  secondary_ip)
     self.secondary_ip = secondary_ip
 
-    # checks presence of the volume group given
-    vgstatus = _HasValidVG(utils.ListVolumeGroups(), self.op.vg_name)
-
-    if vgstatus:
-      raise errors.OpPrereqError("Error: %s" % vgstatus)
+    if not hasattr(self.op, "vg_name"):
+      self.op.vg_name = None
+    # if vg_name not None, checks if volume group is valid
+    if self.op.vg_name:
+      vgstatus = _HasValidVG(utils.ListVolumeGroups(), self.op.vg_name)
+      if vgstatus:
+        raise errors.OpPrereqError("Error: %s\nspecify --no-lvm-storage if"
+                                   " you are not using lvm" % vgstatus)
 
     self.op.file_storage_dir = os.path.normpath(self.op.file_storage_dir)
 
@@ -621,7 +624,7 @@ class LUVerifyCluster(NoHooksLU):
     # compares ganeti version
     local_version = constants.PROTOCOL_VERSION
     if not remote_version:
-      feedback_fn(" - ERROR: connection to %s failed" % (node))
+      feedback_fn("  - ERROR: connection to %s failed" % (node))
       return True
 
     if local_version != remote_version:
@@ -996,6 +999,79 @@ class LURenameCluster(LogicalUnit):
                      " please restart manually.")
 
 
+def _RecursiveCheckIfLVMBased(disk):
+  """Check if the given disk or its children are lvm-based.
+
+  Args:
+    disk: ganeti.objects.Disk object
+
+  Returns:
+    boolean indicating whether a LD_LV dev_type was found or not
+
+  """
+  if disk.children:
+    for chdisk in disk.children:
+      if _RecursiveCheckIfLVMBased(chdisk):
+        return True
+  return disk.dev_type == constants.LD_LV
+
+
+class LUSetClusterParams(LogicalUnit):
+  """Change the parameters of the cluster.
+
+  """
+  HPATH = "cluster-modify"
+  HTYPE = constants.HTYPE_CLUSTER
+  _OP_REQP = []
+
+  def BuildHooksEnv(self):
+    """Build hooks env.
+
+    """
+    env = {
+      "OP_TARGET": self.sstore.GetClusterName(),
+      "NEW_VG_NAME": self.op.vg_name,
+      }
+    mn = self.sstore.GetMasterNode()
+    return env, [mn], [mn]
+
+  def CheckPrereq(self):
+    """Check prerequisites.
+
+    This checks whether the given params don't conflict and
+    if the given volume group is valid.
+
+    """
+    if not self.op.vg_name:
+      instances = [self.cfg.GetInstanceInfo(name)
+                   for name in self.cfg.GetInstanceList()]
+      for inst in instances:
+        for disk in inst.disks:
+          if _RecursiveCheckIfLVMBased(disk):
+            raise errors.OpPrereqError("Cannot disable lvm storage while"
+                                       " lvm-based instances exist")
+
+    # if vg_name not None, checks given volume group on all nodes
+    if self.op.vg_name:
+      node_list = self.cfg.GetNodeList()
+      vglist = rpc.call_vg_list(node_list)
+      for node in node_list:
+        vgstatus = _HasValidVG(vglist[node], self.op.vg_name)
+        if vgstatus:
+          raise errors.OpPrereqError("Error on node '%s': %s" %
+                                     (node, vgstatus))
+
+  def Exec(self, feedback_fn):
+    """Change the parameters of the cluster.
+
+    """
+    if self.op.vg_name != self.cfg.GetVGName():
+      self.cfg.SetVGName(self.op.vg_name)
+    else:
+      feedback_fn("Cluster LVM configuration already in desired"
+                  " state, not changing")
+
+
 def _WaitForSync(cfgw, instance, proc, oneshot=False, unlock=False):
   """Sleep and poll for an instance's disk to sync.
 
@@ -1078,7 +1154,7 @@ def _CheckDiskConsistency(cfgw, dev, node, on_primary, ldisk=False):
   if on_primary or dev.AssembleOnSecondary():
     rstats = rpc.call_blockdev_find(node, dev)
     if not rstats:
-      logger.ToStderr("Can't get any data from node %s" % node)
+      logger.ToStderr("Node %s: Disk degraded, not found or node down" % node)
       result = False
     else:
       result = result and (not rstats[idx])
@@ -1756,6 +1832,12 @@ class LURunClusterCommand(NoHooksLU):
     """Run a command on some nodes.
 
     """
+    # put the master at the end of the nodes list
+    master_node = self.sstore.GetMasterNode()
+    if master_node in self.nodes:
+      self.nodes.remove(master_node)
+      self.nodes.append(master_node)
+
     data = []
     for node in self.nodes:
       result = self.ssh.Run(node, "root", self.op.command)
@@ -2011,6 +2093,8 @@ class LUStartupInstance(LogicalUnit):
     force = self.op.force
     extra_args = getattr(self.op, "extra_args", "")
 
+    self.cfg.MarkInstanceUp(instance.name)
+
     node_current = instance.primary_node
 
     _StartInstanceDisks(self.cfg, instance, force)
@@ -2019,8 +2103,6 @@ class LUStartupInstance(LogicalUnit):
       _ShutdownInstanceDisks(instance, self.cfg)
       raise errors.OpExecError("Could not start instance")
 
-    self.cfg.MarkInstanceUp(instance.name)
-
 
 class LURebootInstance(LogicalUnit):
   """Reboot an instance.
@@ -2136,10 +2218,10 @@ class LUShutdownInstance(LogicalUnit):
     """
     instance = self.instance
     node_current = instance.primary_node
+    self.cfg.MarkInstanceDown(instance.name)
     if not rpc.call_instance_shutdown(node_current, instance):
       logger.Error("could not shutdown instance")
 
-    self.cfg.MarkInstanceDown(instance.name)
     _ShutdownInstanceDisks(instance, self.cfg)
 
 
@@ -2287,11 +2369,33 @@ class LURenameInstance(LogicalUnit):
     inst = self.instance
     old_name = inst.name
 
+    if inst.disk_template == constants.DT_FILE:
+      old_file_storage_dir = os.path.dirname(inst.disks[0].logical_id[1])
+
     self.cfg.RenameInstance(inst.name, self.op.new_name)
 
     # re-read the instance from the configuration after rename
     inst = self.cfg.GetInstanceInfo(self.op.new_name)
 
+    if inst.disk_template == constants.DT_FILE:
+      new_file_storage_dir = os.path.dirname(inst.disks[0].logical_id[1])
+      result = rpc.call_file_storage_dir_rename(inst.primary_node,
+                                                old_file_storage_dir,
+                                                new_file_storage_dir)
+
+      if not result:
+        raise errors.OpExecError("Could not connect to node '%s' to rename"
+                                 " directory '%s' to '%s' (but the instance"
+                                 " has been renamed in Ganeti)" % (
+                                 inst.primary_node, old_file_storage_dir,
+                                 new_file_storage_dir))
+
+      if not result[0]:
+        raise errors.OpExecError("Could not rename directory '%s' to '%s'"
+                                 " (but the instance has been renamed in"
+                                 " Ganeti)" % (old_file_storage_dir,
+                                               new_file_storage_dir))
+
     _StartInstanceDisks(self.cfg, inst, None)
     try:
       if not rpc.call_instance_run_rename(inst.primary_node, inst, old_name,
@@ -2552,7 +2656,7 @@ class LUFailoverInstance(LogicalUnit):
     for dev in instance.disks:
       # for remote_raid1, these are md over drbd
       if not _CheckDiskConsistency(self.cfg, dev, target_node, False):
-        if not self.op.ignore_consistency:
+        if instance.status == "up" and not self.op.ignore_consistency:
           raise errors.OpExecError("Disk %s is degraded on target node,"
                                    " aborting failover." % dev.iv_name)
 
@@ -2577,21 +2681,23 @@ class LUFailoverInstance(LogicalUnit):
     # distribute new instance config to the other nodes
     self.cfg.AddInstance(instance)
 
-    feedback_fn("* activating the instance's disks on target node")
-    logger.Info("Starting instance %s on node %s" %
-                (instance.name, target_node))
+    # Only start the instance if it's marked as up
+    if instance.status == "up":
+      feedback_fn("* activating the instance's disks on target node")
+      logger.Info("Starting instance %s on node %s" %
+                  (instance.name, target_node))
 
-    disks_ok, dummy = _AssembleInstanceDisks(instance, self.cfg,
-                                             ignore_secondaries=True)
-    if not disks_ok:
-      _ShutdownInstanceDisks(instance, self.cfg)
-      raise errors.OpExecError("Can't activate the instance's disks")
+      disks_ok, dummy = _AssembleInstanceDisks(instance, self.cfg,
+                                               ignore_secondaries=True)
+      if not disks_ok:
+        _ShutdownInstanceDisks(instance, self.cfg)
+        raise errors.OpExecError("Can't activate the instance's disks")
 
-    feedback_fn("* starting the instance on the target node")
-    if not rpc.call_instance_start(target_node, instance, None):
-      _ShutdownInstanceDisks(instance, self.cfg)
-      raise errors.OpExecError("Could not start instance %s on node %s." %
-                               (instance.name, target_node))
+      feedback_fn("* starting the instance on the target node")
+      if not rpc.call_instance_start(target_node, instance, None):
+        _ShutdownInstanceDisks(instance, self.cfg)
+        raise errors.OpExecError("Could not start instance %s on node %s." %
+                                 (instance.name, target_node))
 
 
 def _CreateBlockDevOnPrimary(cfg, node, instance, device, info):
@@ -2692,7 +2798,8 @@ def _GenerateDRBD8Branch(cfg, primary, secondary, size, names, iv_name):
 
 def _GenerateDiskTemplate(cfg, template_name,
                           instance_name, primary_node,
-                          secondary_nodes, disk_sz, swap_sz):
+                          secondary_nodes, disk_sz, swap_sz,
+                          file_storage_dir, file_driver):
   """Generate the entire disk layout for a given template type.
 
   """
@@ -2713,43 +2820,6 @@ def _GenerateDiskTemplate(cfg, template_name,
                            logical_id=(vgname, names[1]),
                            iv_name = "sdb")
     disks = [sda_dev, sdb_dev]
-  elif template_name == constants.DT_LOCAL_RAID1:
-    if len(secondary_nodes) != 0:
-      raise errors.ProgrammerError("Wrong template configuration")
-
-
-    names = _GenerateUniqueNames(cfg, [".sda_m1", ".sda_m2",
-                                       ".sdb_m1", ".sdb_m2"])
-    sda_dev_m1 = objects.Disk(dev_type=constants.LD_LV, size=disk_sz,
-                              logical_id=(vgname, names[0]))
-    sda_dev_m2 = objects.Disk(dev_type=constants.LD_LV, size=disk_sz,
-                              logical_id=(vgname, names[1]))
-    md_sda_dev = objects.Disk(dev_type=constants.LD_MD_R1, iv_name = "sda",
-                              size=disk_sz,
-                              children = [sda_dev_m1, sda_dev_m2])
-    sdb_dev_m1 = objects.Disk(dev_type=constants.LD_LV, size=swap_sz,
-                              logical_id=(vgname, names[2]))
-    sdb_dev_m2 = objects.Disk(dev_type=constants.LD_LV, size=swap_sz,
-                              logical_id=(vgname, names[3]))
-    md_sdb_dev = objects.Disk(dev_type=constants.LD_MD_R1, iv_name = "sdb",
-                              size=swap_sz,
-                              children = [sdb_dev_m1, sdb_dev_m2])
-    disks = [md_sda_dev, md_sdb_dev]
-  elif template_name == constants.DT_REMOTE_RAID1:
-    if len(secondary_nodes) != 1:
-      raise errors.ProgrammerError("Wrong template configuration")
-    remote_node = secondary_nodes[0]
-    names = _GenerateUniqueNames(cfg, [".sda_data", ".sda_meta",
-                                       ".sdb_data", ".sdb_meta"])
-    drbd_sda_dev = _GenerateMDDRBDBranch(cfg, primary_node, remote_node,
-                                         disk_sz, names[0:2])
-    md_sda_dev = objects.Disk(dev_type=constants.LD_MD_R1, iv_name="sda",
-                              children = [drbd_sda_dev], size=disk_sz)
-    drbd_sdb_dev = _GenerateMDDRBDBranch(cfg, primary_node, remote_node,
-                                         swap_sz, names[2:4])
-    md_sdb_dev = objects.Disk(dev_type=constants.LD_MD_R1, iv_name="sdb",
-                              children = [drbd_sdb_dev], size=swap_sz)
-    disks = [md_sda_dev, md_sdb_dev]
   elif template_name == constants.DT_DRBD8:
     if len(secondary_nodes) != 1:
       raise errors.ProgrammerError("Wrong template configuration")
@@ -2761,6 +2831,17 @@ def _GenerateDiskTemplate(cfg, template_name,
     drbd_sdb_dev = _GenerateDRBD8Branch(cfg, primary_node, remote_node,
                                          swap_sz, names[2:4], "sdb")
     disks = [drbd_sda_dev, drbd_sdb_dev]
+  elif template_name == constants.DT_FILE:
+    if len(secondary_nodes) != 0:
+      raise errors.ProgrammerError("Wrong template configuration")
+
+    file_sda_dev = objects.Disk(dev_type=constants.LD_FILE, size=disk_sz,
+                                iv_name="sda", logical_id=(file_driver,
+                                "%s/sda" % file_storage_dir))
+    file_sdb_dev = objects.Disk(dev_type=constants.LD_FILE, size=swap_sz,
+                                iv_name="sdb", logical_id=(file_driver,
+                                "%s/sdb" % file_storage_dir))
+    disks = [file_sda_dev, file_sdb_dev]
   else:
     raise errors.ProgrammerError("Invalid disk template '%s'" % template_name)
   return disks
@@ -2787,9 +2868,22 @@ def _CreateDisks(cfg, instance):
   """
   info = _GetInstanceInfoText(instance)
 
+  if instance.disk_template == constants.DT_FILE:
+    file_storage_dir = os.path.dirname(instance.disks[0].logical_id[1])
+    result = rpc.call_file_storage_dir_create(instance.primary_node,
+                                              file_storage_dir)
+
+    if not result:
+      logger.Error("Could not connect to node '%s'" % inst.primary_node)
+      return False
+
+    if not result[0]:
+      logger.Error("failed to create directory '%s'" % file_storage_dir)
+      return False
+
   for device in instance.disks:
     logger.Info("creating volume %s for instance %s" %
-              (device.iv_name, instance.name))
+                (device.iv_name, instance.name))
     #HARDCODE
     for secondary_node in instance.secondary_nodes:
       if not _CreateBlockDevOnSecondary(cfg, secondary_node, instance,
@@ -2803,6 +2897,7 @@ def _CreateDisks(cfg, instance):
       logger.Error("failed to create volume %s on primary!" %
                    device.iv_name)
       return False
+
   return True
 
 
@@ -2832,6 +2927,14 @@ def _RemoveDisks(instance, cfg):
                      " continuing anyway" %
                      (device.iv_name, node))
         result = False
+
+  if instance.disk_template == constants.DT_FILE:
+    file_storage_dir = os.path.dirname(instance.disks[0].logical_id[1])
+    if not rpc.call_file_storage_dir_remove(instance.primary_node,
+                                            file_storage_dir):
+      logger.Error("could not remove directory '%s'" % file_storage_dir)
+      result = False
+
   return result
 
 
@@ -2890,6 +2993,11 @@ class LUCreateInstance(LogicalUnit):
       raise errors.OpPrereqError("Invalid instance creation mode '%s'" %
                                  self.op.mode)
 
+    if (not self.cfg.GetVGName() and
+        self.op.disk_template not in constants.DTS_NOT_LVM):
+      raise errors.OpPrereqError("Cluster does not support lvm-based"
+                                 " instances")
+
     if self.op.mode == constants.INSTANCE_IMPORT:
       src_node = getattr(self.op, "src_node", None)
       src_path = getattr(self.op, "src_path", None)
@@ -2942,6 +3050,15 @@ class LUCreateInstance(LogicalUnit):
     if self.op.disk_template not in constants.DISK_TEMPLATES:
       raise errors.OpPrereqError("Invalid disk template name")
 
+    if (self.op.file_driver and
+        not self.op.file_driver in constants.FILE_DRIVER):
+      raise errors.OpPrereqError("Invalid file driver name '%s'" %
+                                 self.op.file_driver)
+
+    if self.op.file_storage_dir and os.path.isabs(self.op.file_storage_dir):
+        raise errors.OpPrereqError("File storage directory not a relative"
+                                   " path")
+
     if self.op.disk_template in constants.DTS_NET_MIRROR:
       if getattr(self.op, "snode", None) is None:
         raise errors.OpPrereqError("The networked disk templates need"
@@ -2960,10 +3077,9 @@ class LUCreateInstance(LogicalUnit):
     req_size_dict = {
       constants.DT_DISKLESS: None,
       constants.DT_PLAIN: self.op.disk_size + self.op.swap_size,
-      constants.DT_LOCAL_RAID1: (self.op.disk_size + self.op.swap_size) * 2,
       # 256 MB are added for drbd metadata, 128MB for each drbd device
-      constants.DT_REMOTE_RAID1: self.op.disk_size + self.op.swap_size + 256,
       constants.DT_DRBD8: self.op.disk_size + self.op.swap_size + 256,
+      constants.DT_FILE: None,
     }
 
     if self.op.disk_template not in req_size_dict:
@@ -3080,11 +3196,25 @@ class LUCreateInstance(LogicalUnit):
     else:
       network_port = None
 
+    # this is needed because os.path.join does not accept None arguments
+    if self.op.file_storage_dir is None:
+      string_file_storage_dir = ""
+    else:
+      string_file_storage_dir = self.op.file_storage_dir
+
+    # build the full file storage dir path
+    file_storage_dir = os.path.normpath(os.path.join(
+                                        self.sstore.GetFileStorageDir(),
+                                        string_file_storage_dir, instance))
+
+
     disks = _GenerateDiskTemplate(self.cfg,
                                   self.op.disk_template,
                                   instance, pnode_name,
                                   self.secondaries, self.op.disk_size,
-                                  self.op.swap_size)
+                                  self.op.swap_size,
+                                  file_storage_dir,
+                                  self.op.file_driver)
 
     iobj = objects.Instance(name=instance, os=self.op.os_type,
                             primary_node=pnode_name,
@@ -3199,209 +3329,7 @@ class LUConnectConsole(NoHooksLU):
     console_cmd = hyper.GetShellCommandForConsole(instance)
 
     # build ssh cmdline
-    cmd = self.ssh.BuildCmd(node, "root", console_cmd, batch=True, tty=True)
-    return cmd[0], cmd
-
-
-class LUAddMDDRBDComponent(LogicalUnit):
-  """Adda new mirror member to an instance's disk.
-
-  """
-  HPATH = "mirror-add"
-  HTYPE = constants.HTYPE_INSTANCE
-  _OP_REQP = ["instance_name", "remote_node", "disk_name"]
-
-  def BuildHooksEnv(self):
-    """Build hooks env.
-
-    This runs on the master, the primary and all the secondaries.
-
-    """
-    env = {
-      "NEW_SECONDARY": self.op.remote_node,
-      "DISK_NAME": self.op.disk_name,
-      }
-    env.update(_BuildInstanceHookEnvByObject(self.instance))
-    nl = [self.sstore.GetMasterNode(), self.instance.primary_node,
-          self.op.remote_node,] + list(self.instance.secondary_nodes)
-    return env, nl, nl
-
-  def CheckPrereq(self):
-    """Check prerequisites.
-
-    This checks that the instance is in the cluster.
-
-    """
-    instance = self.cfg.GetInstanceInfo(
-      self.cfg.ExpandInstanceName(self.op.instance_name))
-    if instance is None:
-      raise errors.OpPrereqError("Instance '%s' not known" %
-                                 self.op.instance_name)
-    self.instance = instance
-
-    remote_node = self.cfg.ExpandNodeName(self.op.remote_node)
-    if remote_node is None:
-      raise errors.OpPrereqError("Node '%s' not known" % self.op.remote_node)
-    self.remote_node = remote_node
-
-    if remote_node == instance.primary_node:
-      raise errors.OpPrereqError("The specified node is the primary node of"
-                                 " the instance.")
-
-    if instance.disk_template != constants.DT_REMOTE_RAID1:
-      raise errors.OpPrereqError("Instance's disk layout is not"
-                                 " remote_raid1.")
-    for disk in instance.disks:
-      if disk.iv_name == self.op.disk_name:
-        break
-    else:
-      raise errors.OpPrereqError("Can't find this device ('%s') in the"
-                                 " instance." % self.op.disk_name)
-    if len(disk.children) > 1:
-      raise errors.OpPrereqError("The device already has two slave devices."
-                                 " This would create a 3-disk raid1 which we"
-                                 " don't allow.")
-    self.disk = disk
-
-  def Exec(self, feedback_fn):
-    """Add the mirror component
-
-    """
-    disk = self.disk
-    instance = self.instance
-
-    remote_node = self.remote_node
-    lv_names = [".%s_%s" % (disk.iv_name, suf) for suf in ["data", "meta"]]
-    names = _GenerateUniqueNames(self.cfg, lv_names)
-    new_drbd = _GenerateMDDRBDBranch(self.cfg, instance.primary_node,
-                                     remote_node, disk.size, names)
-
-    logger.Info("adding new mirror component on secondary")
-    #HARDCODE
-    if not _CreateBlockDevOnSecondary(self.cfg, remote_node, instance,
-                                      new_drbd, False,
-                                      _GetInstanceInfoText(instance)):
-      raise errors.OpExecError("Failed to create new component on secondary"
-                               " node %s" % remote_node)
-
-    logger.Info("adding new mirror component on primary")
-    #HARDCODE
-    if not _CreateBlockDevOnPrimary(self.cfg, instance.primary_node,
-                                    instance, new_drbd,
-                                    _GetInstanceInfoText(instance)):
-      # remove secondary dev
-      self.cfg.SetDiskID(new_drbd, remote_node)
-      rpc.call_blockdev_remove(remote_node, new_drbd)
-      raise errors.OpExecError("Failed to create volume on primary")
-
-    # the device exists now
-    # call the primary node to add the mirror to md
-    logger.Info("adding new mirror component to md")
-    if not rpc.call_blockdev_addchildren(instance.primary_node,
-                                         disk, [new_drbd]):
-      logger.Error("Can't add mirror compoment to md!")
-      self.cfg.SetDiskID(new_drbd, remote_node)
-      if not rpc.call_blockdev_remove(remote_node, new_drbd):
-        logger.Error("Can't rollback on secondary")
-      self.cfg.SetDiskID(new_drbd, instance.primary_node)
-      if not rpc.call_blockdev_remove(instance.primary_node, new_drbd):
-        logger.Error("Can't rollback on primary")
-      raise errors.OpExecError("Can't add mirror component to md array")
-
-    disk.children.append(new_drbd)
-
-    self.cfg.AddInstance(instance)
-
-    _WaitForSync(self.cfg, instance, self.proc)
-
-    return 0
-
-
-class LURemoveMDDRBDComponent(LogicalUnit):
-  """Remove a component from a remote_raid1 disk.
-
-  """
-  HPATH = "mirror-remove"
-  HTYPE = constants.HTYPE_INSTANCE
-  _OP_REQP = ["instance_name", "disk_name", "disk_id"]
-
-  def BuildHooksEnv(self):
-    """Build hooks env.
-
-    This runs on the master, the primary and all the secondaries.
-
-    """
-    env = {
-      "DISK_NAME": self.op.disk_name,
-      "DISK_ID": self.op.disk_id,
-      "OLD_SECONDARY": self.old_secondary,
-      }
-    env.update(_BuildInstanceHookEnvByObject(self.instance))
-    nl = [self.sstore.GetMasterNode(),
-          self.instance.primary_node] + list(self.instance.secondary_nodes)
-    return env, nl, nl
-
-  def CheckPrereq(self):
-    """Check prerequisites.
-
-    This checks that the instance is in the cluster.
-
-    """
-    instance = self.cfg.GetInstanceInfo(
-      self.cfg.ExpandInstanceName(self.op.instance_name))
-    if instance is None:
-      raise errors.OpPrereqError("Instance '%s' not known" %
-                                 self.op.instance_name)
-    self.instance = instance
-
-    if instance.disk_template != constants.DT_REMOTE_RAID1:
-      raise errors.OpPrereqError("Instance's disk layout is not"
-                                 " remote_raid1.")
-    for disk in instance.disks:
-      if disk.iv_name == self.op.disk_name:
-        break
-    else:
-      raise errors.OpPrereqError("Can't find this device ('%s') in the"
-                                 " instance." % self.op.disk_name)
-    for child in disk.children:
-      if (child.dev_type == constants.LD_DRBD7 and
-          child.logical_id[2] == self.op.disk_id):
-        break
-    else:
-      raise errors.OpPrereqError("Can't find the device with this port.")
-
-    if len(disk.children) < 2:
-      raise errors.OpPrereqError("Cannot remove the last component from"
-                                 " a mirror.")
-    self.disk = disk
-    self.child = child
-    if self.child.logical_id[0] == instance.primary_node:
-      oid = 1
-    else:
-      oid = 0
-    self.old_secondary = self.child.logical_id[oid]
-
-  def Exec(self, feedback_fn):
-    """Remove the mirror component
-
-    """
-    instance = self.instance
-    disk = self.disk
-    child = self.child
-    logger.Info("remove mirror component")
-    self.cfg.SetDiskID(disk, instance.primary_node)
-    if not rpc.call_blockdev_removechildren(instance.primary_node,
-                                            disk, [child]):
-      raise errors.OpExecError("Can't remove child from mirror.")
-
-    for node in child.logical_id[:2]:
-      self.cfg.SetDiskID(child, node)
-      if not rpc.call_blockdev_remove(node, child):
-        logger.Error("Warning: failed to remove device from node %s,"
-                     " continuing operation." % node)
-
-    disk.children.remove(child)
-    self.cfg.AddInstance(instance)
+    return self.ssh.BuildCmd(node, "root", console_cmd, batch=True, tty=True)
 
 
 class LUReplaceDisks(LogicalUnit):
@@ -4066,7 +3994,7 @@ class LUQueryInstanceData(NoHooksLU):
     return result
 
 
-class LUSetInstanceParms(LogicalUnit):
+class LUSetInstanceParams(LogicalUnit):
   """Modifies an instances's parameters.
 
   """
@@ -4118,9 +4046,9 @@ class LUSetInstanceParms(LogicalUnit):
     self.kernel_path = getattr(self.op, "kernel_path", None)
     self.initrd_path = getattr(self.op, "initrd_path", None)
     self.hvm_boot_order = getattr(self.op, "hvm_boot_order", None)
-    all_parms = [self.mem, self.vcpus, self.ip, self.bridge, self.mac,
-                 self.kernel_path, self.initrd_path, self.hvm_boot_order]
-    if all_parms.count(None) == len(all_parms):
+    all_params = [self.mem, self.vcpus, self.ip, self.bridge, self.mac,
+                  self.kernel_path, self.initrd_path, self.hvm_boot_order]
+    if all_params.count(None) == len(all_params):
       raise errors.OpPrereqError("No changes submitted")
     if self.mem is not None:
       try:
@@ -4303,10 +4231,11 @@ class LUExportInstance(LogicalUnit):
     instance = self.instance
     dst_node = self.dst_node
     src_node = instance.primary_node
-    # shutdown the instance, unless requested not to do so
     if self.op.shutdown:
-      op = opcodes.OpShutdownInstance(instance_name=instance.name)
-      self.proc.ChainOpCode(op)
+      # shutdown the instance, but not the disks
+      if not rpc.call_instance_shutdown(src_node, instance):
+         raise errors.OpExecError("Could not shutdown instance %s on node %s" %
+                                 (instance.name, source_node))
 
     vgname = self.cfg.GetVGName()
 
@@ -4329,22 +4258,20 @@ class LUExportInstance(LogicalUnit):
             snap_disks.append(new_dev)
 
     finally:
-      if self.op.shutdown:
-        op = opcodes.OpStartupInstance(instance_name=instance.name,
-                                       force=False)
-        self.proc.ChainOpCode(op)
+      if self.op.shutdown and instance.status == "up":
+        if not rpc.call_instance_start(src_node, instance, None):
+          _ShutdownInstanceDisks(instance, self.cfg)
+          raise errors.OpExecError("Could not start instance")
 
     # TODO: check for size
 
     for dev in snap_disks:
-      if not rpc.call_snapshot_export(src_node, dev, dst_node.name,
-                                           instance):
-        logger.Error("could not export block device %s from node"
-                     " %s to node %s" %
-                     (dev.logical_id[1], src_node, dst_node.name))
+      if not rpc.call_snapshot_export(src_node, dev, dst_node.name, instance):
+        logger.Error("could not export block device %s from node %s to node %s"
+                     % (dev.logical_id[1], src_node, dst_node.name))
       if not rpc.call_blockdev_remove(src_node, dev):
-        logger.Error("could not remove snapshot block device %s from"
-                     " node %s" % (dev.logical_id[1], src_node))
+        logger.Error("could not remove snapshot block device %s from node %s" %
+                     (dev.logical_id[1], src_node))
 
     if not rpc.call_finalize_export(dst_node.name, instance, snap_disks):
       logger.Error("could not finalize export for instance %s on node %s" %