Esempio n. 1
0
  def _ExecFailover(self):
    """Failover an instance.

    The failover is done by shutting it down on its present node and
    starting it on the secondary.

    """
    if self.instance.forthcoming:
      self.feedback_fn("Instance is forthcoming, just updating the"
                       "  configuration")
      self.cfg.SetInstancePrimaryNode(self.instance.uuid,
                                      self.target_node_uuid)
      return

    primary_node = self.cfg.GetNodeInfo(self.instance.primary_node)

    source_node_uuid = self.instance.primary_node

    if self.instance.disks_active:
      self.feedback_fn("* checking disk consistency between source and target")
      inst_disks = self.cfg.GetInstanceDisks(self.instance.uuid)
      for (idx, dev) in enumerate(inst_disks):
        # for drbd, these are drbd over lvm
        if not CheckDiskConsistency(self.lu, self.instance, dev,
                                    self.target_node_uuid, False):
          if primary_node.offline:
            self.feedback_fn("Node %s is offline, ignoring degraded disk %s on"
                             " target node %s" %
                             (primary_node.name, idx,
                              self.cfg.GetNodeName(self.target_node_uuid)))
          elif not self.ignore_consistency:
            raise errors.OpExecError("Disk %s is degraded on target node,"
                                     " aborting failover" % idx)
    else:
      self.feedback_fn("* not checking disk consistency as instance is not"
                       " running")

    self.feedback_fn("* shutting down instance on source node")
    logging.info("Shutting down instance %s on node %s",
                 self.instance.name, self.cfg.GetNodeName(source_node_uuid))

    result = self.rpc.call_instance_shutdown(source_node_uuid, self.instance,
                                             self.shutdown_timeout,
                                             self.lu.op.reason)
    msg = result.fail_msg
    if msg:
      if self.ignore_consistency or primary_node.offline:
        self.lu.LogWarning("Could not shutdown instance %s on node %s,"
                           " proceeding anyway; please make sure node"
                           " %s is down; error details: %s",
                           self.instance.name,
                           self.cfg.GetNodeName(source_node_uuid),
                           self.cfg.GetNodeName(source_node_uuid), msg)
      else:
        raise errors.OpExecError("Could not shutdown instance %s on"
                                 " node %s: %s" %
                                 (self.instance.name,
                                  self.cfg.GetNodeName(source_node_uuid), msg))

    disk_template = self.cfg.GetInstanceDiskTemplate(self.instance.uuid)
    if disk_template in constants.DTS_EXT_MIRROR:
      self._CloseInstanceDisks(source_node_uuid)

    self.feedback_fn("* deactivating the instance's disks on source node")
    if not ShutdownInstanceDisks(self.lu, self.instance, ignore_primary=True):
      raise errors.OpExecError("Can't shut down the instance's disks")

    self.cfg.SetInstancePrimaryNode(self.instance.uuid, self.target_node_uuid)
    self.instance = self.cfg.GetInstanceInfo(self.instance_uuid)

    # Only start the instance if it's marked as up
    if self.instance.admin_state == constants.ADMINST_UP:
      self.feedback_fn("* activating the instance's disks on target node %s" %
                       self.cfg.GetNodeName(self.target_node_uuid))
      logging.info("Starting instance %s on node %s", self.instance.name,
                   self.cfg.GetNodeName(self.target_node_uuid))

      disks_ok, _, _ = AssembleInstanceDisks(self.lu, self.instance,
                                             ignore_secondaries=True)
      if not disks_ok:
        ShutdownInstanceDisks(self.lu, self.instance)
        raise errors.OpExecError("Can't activate the instance's disks")

      self.feedback_fn("* starting the instance on the target node %s" %
                       self.cfg.GetNodeName(self.target_node_uuid))
      result = self.rpc.call_instance_start(self.target_node_uuid,
                                            (self.instance, None, None), False,
                                            self.lu.op.reason)
      msg = result.fail_msg
      if msg:
        ShutdownInstanceDisks(self.lu, self.instance)
        raise errors.OpExecError("Could not start instance %s on node %s: %s" %
                                 (self.instance.name,
                                  self.cfg.GetNodeName(self.target_node_uuid),
                                  msg))
Esempio n. 2
0
    def Exec(self, feedback_fn):
        """Move an instance.

    The move is done by shutting it down on its present node, copying
    the data over (slow) and starting it on the new node.

    """
        source_node = self.cfg.GetNodeInfo(self.instance.primary_node)
        target_node = self.cfg.GetNodeInfo(self.target_node_uuid)

        self.LogInfo("Shutting down instance %s on source node %s",
                     self.instance.name, source_node.name)

        assert (self.owned_locks(locking.LEVEL_NODE) == self.owned_locks(
            locking.LEVEL_NODE_RES))

        result = self.rpc.call_instance_shutdown(source_node.uuid,
                                                 self.instance,
                                                 self.op.shutdown_timeout,
                                                 self.op.reason)
        if self.op.ignore_consistency:
            result.Warn(
                "Could not shutdown instance %s on node %s. Proceeding"
                " anyway. Please make sure node %s is down. Error details" %
                (self.instance.name, source_node.name, source_node.name),
                self.LogWarning)
        else:
            result.Raise("Could not shutdown instance %s on node %s" %
                         (self.instance.name, source_node.name))

        # create the target disks
        try:
            CreateDisks(self, self.instance, target_node_uuid=target_node.uuid)
        except errors.OpExecError:
            self.LogWarning("Device creation failed")
            for disk_uuid in self.instance.disks:
                self.cfg.ReleaseDRBDMinors(disk_uuid)
            raise

        errs = []
        transfers = []
        # activate, get path, create transfer jobs
        disks = self.cfg.GetInstanceDisks(self.instance.uuid)
        for idx, disk in enumerate(disks):
            # FIXME: pass debug option from opcode to backend
            dt = masterd.instance.DiskTransfer("disk/%s" % idx,
                                               constants.IEIO_RAW_DISK,
                                               (disk, self.instance),
                                               constants.IEIO_RAW_DISK,
                                               (disk, self.instance), None)
            transfers.append(dt)
            self.cfg.Update(disk, feedback_fn)

        import_result = \
          masterd.instance.TransferInstanceData(self, feedback_fn,
                                                source_node.uuid,
                                                target_node.uuid,
                                                target_node.secondary_ip,
                                                self.op.compress,
                                                self.instance, transfers)
        if not compat.all(import_result):
            errs.append("Failed to transfer instance data")

        if errs:
            self.LogWarning("Some disks failed to copy, aborting")
            try:
                RemoveDisks(self,
                            self.instance,
                            target_node_uuid=target_node.uuid)
            finally:
                for disk_uuid in self.instance.disks:
                    self.cfg.ReleaseDRBDMinors(disk_uuid)
                raise errors.OpExecError("Errors during disk copy: %s" %
                                         (",".join(errs), ))

        self.instance.primary_node = target_node.uuid
        self.cfg.Update(self.instance, feedback_fn)
        for disk in disks:
            self.cfg.SetDiskNodes(disk.uuid, [target_node.uuid])

        self.LogInfo("Removing the disks on the original node")
        RemoveDisks(self, self.instance, target_node_uuid=source_node.uuid)

        # Only start the instance if it's marked as up
        if self.instance.admin_state == constants.ADMINST_UP:
            self.LogInfo("Starting instance %s on node %s", self.instance.name,
                         target_node.name)

            disks_ok, _, _ = AssembleInstanceDisks(self,
                                                   self.instance,
                                                   ignore_secondaries=True)
            if not disks_ok:
                ShutdownInstanceDisks(self, self.instance)
                raise errors.OpExecError("Can't activate the instance's disks")

            result = self.rpc.call_instance_start(target_node.uuid,
                                                  (self.instance, None, None),
                                                  False, self.op.reason)
            msg = result.fail_msg
            if msg:
                ShutdownInstanceDisks(self, self.instance)
                raise errors.OpExecError(
                    "Could not start instance %s on node %s: %s" %
                    (self.instance.name, target_node.name, msg))