Logo Search packages:      
Sourcecode: ganeti version File versions  Download package

def lib::cmdlib::LUAddNode::Exec (   self,
  feedback_fn 
)

Adds the new node to the cluster.

Reimplemented from lib::cmdlib::LogicalUnit.

Definition at line 1411 of file cmdlib.py.

01411                              :
    """Adds the new node to the cluster.

    """
    new_node = self.new_node
    node = new_node.name

    # set up inter-node password and certificate and restarts the node daemon
    gntpass = self.sstore.GetNodeDaemonPassword()
    if not re.match('^[a-zA-Z0-9.]{1,64}$', gntpass):
      raise errors.OpExecError("ganeti password corruption detected")
    f = open(constants.SSL_CERT_FILE)
    try:
      gntpem = f.read(8192)
    finally:
      f.close()
    # in the base64 pem encoding, neither '!' nor '.' are valid chars,
    # so we use this to detect an invalid certificate; as long as the
    # cert doesn't contain this, the here-document will be correctly
    # parsed by the shell sequence below
    if re.search('^!EOF\.', gntpem, re.MULTILINE):
      raise errors.OpExecError("invalid PEM encoding in the SSL certificate")
    if not gntpem.endswith("\n"):
      raise errors.OpExecError("PEM must end with newline")
    logger.Info("copy cluster pass to %s and starting the node daemon" % node)

    # and then connect with ssh to set password and start ganeti-noded
    # note that all the below variables are sanitized at this point,
    # either by being constants or by the checks above
    ss = self.sstore
    mycommand = ("umask 077 && "
                 "echo '%s' > '%s' && "
                 "cat > '%s' << '!EOF.' && \n"
                 "%s!EOF.\n%s restart" %
                 (gntpass, ss.KeyToFilename(ss.SS_NODED_PASS),
                  constants.SSL_CERT_FILE, gntpem,
                  constants.NODE_INITD_SCRIPT))

    result = ssh.SSHCall(node, 'root', mycommand, batch=False, ask_key=True)
    if result.failed:
      raise errors.OpExecError("Remote command on node %s, error: %s,"
                               " output: %s" %
                               (node, result.fail_reason, result.output))

    # check connectivity
    time.sleep(4)

    result = rpc.call_version([node])[node]
    if result:
      if constants.PROTOCOL_VERSION == result:
        logger.Info("communication to node %s fine, sw version %s match" %
                    (node, result))
      else:
        raise errors.OpExecError("Version mismatch master version %s,"
                                 " node version %s" %
                                 (constants.PROTOCOL_VERSION, result))
    else:
      raise errors.OpExecError("Cannot get version from the new node")

    # setup ssh on node
    logger.Info("copy ssh key to node %s" % node)
    priv_key, pub_key, _ = ssh.GetUserFiles(constants.GANETI_RUNAS)
    keyarray = []
    keyfiles = [constants.SSH_HOST_DSA_PRIV, constants.SSH_HOST_DSA_PUB,
                constants.SSH_HOST_RSA_PRIV, constants.SSH_HOST_RSA_PUB,
                priv_key, pub_key]

    for i in keyfiles:
      f = open(i, 'r')
      try:
        keyarray.append(f.read())
      finally:
        f.close()

    result = rpc.call_node_add(node, keyarray[0], keyarray[1], keyarray[2],
                               keyarray[3], keyarray[4], keyarray[5])

    if not result:
      raise errors.OpExecError("Cannot transfer ssh keys to the new node")

    # Add node to our /etc/hosts, and add key to known_hosts
    _AddHostToEtcHosts(new_node.name)

    _UpdateKnownHosts(new_node.name, new_node.primary_ip,
                      self.cfg.GetHostKey())

    if new_node.secondary_ip != new_node.primary_ip:
      if not rpc.call_node_tcp_ping(new_node.name,
                                    constants.LOCALHOST_IP_ADDRESS,
                                    new_node.secondary_ip,
                                    constants.DEFAULT_NODED_PORT,
                                    10, False):
        raise errors.OpExecError("Node claims it doesn't have the secondary ip"
                                 " you gave (%s). Please fix and re-run this"
                                 " command." % new_node.secondary_ip)

    success, msg = ssh.VerifyNodeHostname(node)
    if not success:
      raise errors.OpExecError("Node '%s' claims it has a different hostname"
                               " than the one the resolver gives: %s."
                               " Please fix and re-run this command." %
                               (node, msg))

    # Distribute updated /etc/hosts and known_hosts to all nodes,
    # including the node just added
    myself = self.cfg.GetNodeInfo(self.sstore.GetMasterNode())
    dist_nodes = self.cfg.GetNodeList() + [node]
    if myself.name in dist_nodes:
      dist_nodes.remove(myself.name)

    logger.Debug("Copying hosts and known_hosts to all nodes")
    for fname in ("/etc/hosts", constants.SSH_KNOWN_HOSTS_FILE):
      result = rpc.call_upload_file(dist_nodes, fname)
      for to_node in dist_nodes:
        if not result[to_node]:
          logger.Error("copy of file %s to node %s failed" %
                       (fname, to_node))

    to_copy = ss.GetFileList()
    for fname in to_copy:
      if not ssh.CopyFileToNode(node, fname):
        logger.Error("could not copy file %s to node %s" % (fname, node))

    logger.Info("adding node %s to cluster.conf" % node)
    self.cfg.AddNode(new_node)


class LUMasterFailover(LogicalUnit):


Generated by  Doxygen 1.6.0   Back to index