diff --git a/lib/backend.py b/lib/backend.py
index 7b362d59aa8f2f66f06a05a0291b5f99035f5f87..fea9da9755b9ca6eb029175ce23dc70fda7873b3 100644
--- a/lib/backend.py
+++ b/lib/backend.py
@@ -122,7 +122,6 @@ def AddNode(dsa, dsapub, rsa, rsapub, ssh, sshpub):
 
   utils.RunCmd(["/etc/init.d/ssh", "restart"])
 
-  utils.RemoveFile("/root/.ssh/known_hosts")
   return True
 
 
@@ -790,7 +789,7 @@ def UploadFile(file_name, data, mode, uid, gid, atime, mtime):
     return False
 
   allowed_files = [constants.CLUSTER_CONF_FILE, "/etc/hosts",
-                   "/etc/ssh/ssh_known_hosts"]
+                   constants.SSH_KNOWN_HOSTS_FILE]
   allowed_files.extend(ssconf.SimpleStore().GetFileList())
   if file_name not in allowed_files:
     logger.Error("Filename passed to UploadFile not in allowed"
diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index 04122f4d136669219ffc32d57bd984be2943728c..26057f38dd41ed787805b8bc6528ff13cc0e22c6 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -350,10 +350,10 @@ def _UpdateKnownHosts(fullnode, ip, pubkey):
     pubkey   - the public key of the cluster
 
   """
-  if os.path.exists('/etc/ssh/ssh_known_hosts'):
-    f = open('/etc/ssh/ssh_known_hosts', 'r+')
+  if os.path.exists(constants.SSH_KNOWN_HOSTS_FILE):
+    f = open(constants.SSH_KNOWN_HOSTS_FILE, 'r+')
   else:
-    f = open('/etc/ssh/ssh_known_hosts', 'w+')
+    f = open(constants.SSH_KNOWN_HOSTS_FILE, 'w+')
 
   inthere = False
 
@@ -405,12 +405,15 @@ def _UpdateKnownHosts(fullnode, ip, pubkey):
     save_lines = save_lines + add_lines
 
     # Write a new file and replace old.
-    fd, tmpname = tempfile.mkstemp('tmp', 'ssh_known_hosts_', '/etc/ssh')
+    fd, tmpname = tempfile.mkstemp('.tmp', 'known_hosts.',
+                                   constants.DATA_DIR)
     newfile = os.fdopen(fd, 'w')
-    newfile.write(''.join(save_lines))
-    newfile.close()
+    try:
+      newfile.write(''.join(save_lines))
+    finally:
+      newfile.close()
     logger.Debug("Wrote new known_hosts.")
-    os.rename(tmpname, '/etc/ssh/ssh_known_hosts')
+    os.rename(tmpname, constants.SSH_KNOWN_HOSTS_FILE)
 
   elif add_lines:
     # Simply appending a new line will do the trick.
@@ -448,8 +451,6 @@ def _InitSSHSetup(node):
     node: the name of this host as a fqdn
 
   """
-  utils.RemoveFile('/root/.ssh/known_hosts')
-
   if os.path.exists('/root/.ssh/id_dsa'):
     utils.CreateBackup('/root/.ssh/id_dsa')
   if os.path.exists('/root/.ssh/id_dsa.pub'):
@@ -1365,8 +1366,6 @@ class LUAddNode(LogicalUnit):
       raise errors.OpExecError("PEM must end with newline")
     logger.Info("copy cluster pass to %s and starting the node daemon" % node)
 
-    # remove first the root's known_hosts file
-    utils.RemoveFile("/root/.ssh/known_hosts")
     # 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
@@ -1442,7 +1441,7 @@ class LUAddNode(LogicalUnit):
       dist_nodes.remove(myself.name)
 
     logger.Debug("Copying hosts and known_hosts to all nodes")
-    for fname in ("/etc/hosts", "/etc/ssh/ssh_known_hosts"):
+    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]:
@@ -2798,7 +2797,13 @@ class LUConnectConsole(NoHooksLU):
 
     hyper = hypervisor.GetHypervisor()
     console_cmd = hyper.GetShellCommandForConsole(instance.name)
-    return node, console_cmd
+    # build ssh cmdline
+    argv = ["ssh", "-q", "-t"]
+    argv.extend(ssh.KNOWN_HOSTS_OPTS)
+    argv.extend(ssh.BATCH_MODE_OPTS)
+    argv.append(node)
+    argv.append(console_cmd)
+    return "ssh", argv
 
 
 class LUAddMDDRBDComponent(LogicalUnit):
diff --git a/lib/constants.py b/lib/constants.py
index 09dd712d71c471879a5cbe459db4a47de2f9408e..856f39c664bec3ba55efe239e6e6ce8f7a68376f 100644
--- a/lib/constants.py
+++ b/lib/constants.py
@@ -34,6 +34,7 @@ DATA_DIR = "/var/lib/ganeti"
 CLUSTER_CONF_FILE = DATA_DIR + "/config.data"
 SSL_CERT_FILE = DATA_DIR + "/server.pem"
 WATCHER_STATEFILE = DATA_DIR + "/restart_state"
+SSH_KNOWN_HOSTS_FILE = DATA_DIR + "/known_hosts"
 
 NODE_INITD_SCRIPT = "/etc/init.d/ganeti"
 DEFAULT_NODED_PORT = 1811
diff --git a/lib/ssh.py b/lib/ssh.py
index bd084870de8da456f01e4a8c3805e4c5a9dfd24a..7cf772a98f8e7b58cf381dd6117763b5c1c95cf5 100644
--- a/lib/ssh.py
+++ b/lib/ssh.py
@@ -29,6 +29,31 @@ import os
 from ganeti import logger
 from ganeti import utils
 from ganeti import errors
+from ganeti import constants
+
+
+__all__ = ["SSHCall", "CopyFileToNode", "VerifyNodeHostname",
+           "KNOWN_HOSTS_OPTS", "BATCH_MODE_OPTS", "ASK_KEY_OPTS"]
+
+
+KNOWN_HOSTS_OPTS = [
+  "-oGlobalKnownHostsFile=%s" % constants.SSH_KNOWN_HOSTS_FILE,
+  "-oUserKnownHostsFile=/dev/null",
+  ]
+
+# Note: BATCH_MODE conflicts with ASK_KEY
+BATCH_MODE_OPTS = [
+  "-oEscapeChar=none",
+  "-oBatchMode=yes",
+  "-oStrictHostKeyChecking=yes",
+  ]
+
+ASK_KEY_OPTS = [
+  "-oStrictHostKeyChecking=ask",
+  "-oEscapeChar=none",
+  "-oHashKnownHosts=no",
+  ]
+
 
 def SSHCall(hostname, user, command, batch=True, ask_key=False):
   """Execute a command on a remote node.
@@ -40,22 +65,23 @@ def SSHCall(hostname, user, command, batch=True, ask_key=False):
     hostname: the target host, string
     user: user to auth as
     command: the command
+    batch: if true, ssh will run in batch mode with no prompting
+    ask_key: if true, ssh will run with StrictHostKeyChecking=ask, so that
+             we can connect to an unknown host (not valid in batch mode)
 
   Returns:
     `utils.RunResult` as for `utils.RunCmd()`
 
   """
-  argv = ["ssh", "-q", "-oEscapeChar=none"]
+  argv = ["ssh", "-q"]
+  argv.extend(KNOWN_HOSTS_OPTS)
   if batch:
-    argv.append("-oBatchMode=yes")
     # if we are in batch mode, we can't ask the key
     if ask_key:
       raise errors.ProgrammerError("SSH call requested conflicting options")
-  if ask_key:
-    argv.append("-oStrictHostKeyChecking=ask")
-    argv.append("-oHashKnownHosts=no")
-  else:
-    argv.append("-oStrictHostKeyChecking=yes")
+    argv.extend(BATCH_MODE_OPTS)
+  elif ask_key:
+    argv.extend(ASK_KEY_OPTS)
   argv.extend(["%s@%s" % (user, hostname), command])
   return utils.RunCmd(argv)
 
@@ -79,8 +105,11 @@ def CopyFileToNode(node, filename):
     logger.Error("file %s must be an absolute path" % (filename))
     return False
 
-  command = ["scp", "-q", "-p", "-oStrictHostKeyChecking=yes",
-             "-oBatchMode=yes", filename, "%s:%s" % (node, filename)]
+  command = ["scp", "-q", "-p"]
+  command.extend(KNOWN_HOSTS_OPTS)
+  command.extend(BATCH_MODE_OPTS)
+  command.append(filename)
+  command.append("%s:%s" % (node, filename))
 
   result = utils.RunCmd(command)
 
diff --git a/scripts/gnt-instance b/scripts/gnt-instance
index d0dc22c55d25b195a9ca7f220396b4de90681fa2..a4f173ab5e57385a6239a5d65d61314a6e1569a4 100755
--- a/scripts/gnt-instance
+++ b/scripts/gnt-instance
@@ -290,14 +290,14 @@ def ConnectToInstanceConsole(opts, args):
   instance_name = args[0]
 
   op = opcodes.OpConnectConsole(instance_name=instance_name)
-  node, console_cmd = SubmitOpCode(op)
+  cmd, argv = SubmitOpCode(op)
   # drop lock and exec so other commands can run while we have console
   utils.Unlock("cmd")
   try:
-    os.execv("/usr/bin/ssh", ["ssh", "-qt", node, console_cmd])
+    os.execvp(cmd, argv)
   finally:
-    sys.stderr.write("Can't run console command %s on node %s" %
-                     (console_cmd, node))
+    sys.stderr.write("Can't run console command %s with arguments:\n'%s'" %
+                     (cmd, " ".join(argv)))
     os._exit(1)