Commit 827f753e authored by Guido Trotter's avatar Guido Trotter
Browse files

AddNode: move the initial setup to boostrap

From the master node we can't start ssh and connect to the remote node,
nor we can do it from ganeti-noded as this ssh section will possibly ask
for key confirmation and password. So the code to copy the ganeti-noded
password and SSL key has been moved to bootstrap.py, and it's called by
gnt-node before the AddNode opcode.

Reviewed-by: iustinp
parent 05ccd983
......@@ -227,3 +227,54 @@ def InitCluster(cluster_name, hypervisor_type, mac_prefix, def_bridge,
mac_prefix, vg_name, def_bridge)
ssh.WriteKnownHostsFile(cfg, ss, constants.SSH_KNOWN_HOSTS_FILE)
def SetupNodeDaemon(node):
"""Add a node to the cluster.
This function must be called before the actual opcode, and will ssh to the
remote node, copy the needed files, and start ganeti-noded, allowing the master
to do the rest via normal rpc calls.
Args:
node: fully qualified domain name for the new node
"""
ss = ssconf.SimpleStore()
sshrunner = ssh.SshRunner(ss)
gntpass = ss.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")
# set up inter-node password and certificate and restarts the node daemon
# 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
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 = sshrunner.Run(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))
return 0
......@@ -1529,46 +1529,7 @@ class LUAddNode(LogicalUnit):
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 = self.ssh.Run(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:
......
......@@ -28,6 +28,7 @@ from ganeti import logger
from ganeti import utils
from ganeti import constants
from ganeti import errors
from ganeti import bootstrap
_LIST_DEF_FIELDS = [
......@@ -59,6 +60,8 @@ def AddNode(opts, args):
"on the target machine (%s) with the ones of the current one\n"
"and grant full intra-cluster ssh root access to/from it\n" % node)
bootstrap.SetupNodeDaemon(node)
op = opcodes.OpAddNode(node_name=args[0], secondary_ip=opts.secondary_ip,
readd=opts.readd)
SubmitOpCode(op)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment