commit 70d9e3d8aa9a7ec1da6c0fe0e345cfb1cfeeb0c2
Author: Iustin Pop <iustin@google.com>
Date:   Tue Oct 16 08:28:26 2007 +0000

    Replace more ssh paths with proper constants
    
    The node's ssh keys filenames are now provided as constants; this should
    allow easier customization.
    
    Also, the user's ssh key computing has been abstracted into ssh.py
    
    Reviewed-by: imsnah

diff --git a/lib/backend.py b/lib/backend.py
index 215be6c..5df65a5 100644
--- a/lib/backend.py
+++ b/lib/backend.py
@@ -88,28 +88,24 @@ def AddNode(dsa, dsapub, rsa, rsapub, sshkey, sshpub):
       - adds the ssh public key to the users' authorized_keys file
 
   """
-  user_dir = utils.GetHomeDir(constants.GANETI_RUNAS)
-  if not user_dir:
-    logger.Error("Cannot find home of run-as user %s" % constants.GANETI_RUNAS)
-    return False
-
-  sshd_keys =  [("ssh_host_rsa_key", rsa, 0600),
-                ("ssh_host_rsa_key.pub", rsapub, 0644),
-                ("ssh_host_dsa_key", dsa, 0600),
-                ("ssh_host_dsa_key.pub",  dsapub, 0644)]
+  sshd_keys =  [(constants.SSH_HOST_RSA_PRIV, rsa, 0600),
+                (constants.SSH_HOST_RSA_PUB, rsapub, 0644),
+                (constants.SSH_HOST_DSA_PRIV, dsa, 0600),
+                (constants.SSH_HOST_DSA_PUB, dsapub, 0644)]
   for name, content, mode in sshd_keys:
-    utils.WriteFile(os.path.join(constants.SSH_CONFIG_DIR, name),
-                    data=content, mode=mode)
-
-  user_ssh_dir = os.path.join(user_dir, ".ssh")
+    utils.WriteFile(name, data=content, mode=mode)
 
-  if not os.path.isdir(user_ssh_dir):
-    os.mkdir(user_ssh_dir)
+  try:
+    priv_key, pub_key, auth_keys = ssh.GetUserFiles(constants.GANETI_RUNAS,
+                                                    mkdir=True)
+  except errors.OpExecError, err:
+    logger.Error("Error while processing user ssh files: %s" % err)
+    return False
 
-  for name, content in [("id_dsa", sshkey), ("id_dsa.pub", sshpub)]:
-    utils.WriteFile(os.path.join(user_ssh_dir, name), data=content, mode=0600)
+  for name, content in [(priv_key, sshkey), (pub_key, sshpub)]:
+    utils.WriteFile(name, data=content, mode=0600)
 
-  utils.AddAuthorizedKey(os.path.join(user_ssh_dir, "authorized_keys"), sshpub)
+  utils.AddAuthorizedKey(auth_keys, sshpub)
 
   utils.RunCmd([constants.SSH_INITD_SCRIPT, "restart"])
 
@@ -126,27 +122,21 @@ def LeaveCluster():
       if os.path.isfile(full_name) and not os.path.islink(full_name):
         utils.RemoveFile(full_name)
 
-  user_dir = utils.GetHomeDir(constants.GANETI_RUNAS)
-  if not user_dir:
-    logger.Error("Cannot find home of run-as user %s" % constants.GANETI_RUNAS)
-    return
-
-  user_ssh_dir = os.path.join(user_dir, ".ssh")
 
-  if not os.path.isdir(user_ssh_dir):
-    logger.Error("User's ssh dir '%s' does not exist?!" % user_ssh_dir)
+  try:
+    priv_key, pub_key, auth_keys = ssh.GetUserFiles(constants.GANETI_RUNAS)
+  except errors.OpExecError, err:
+    logger.Error("Error while processing ssh files: %s" % err)
     return
 
-  f = open(os.path.join(user_ssh_dir, "id_dsa.pub"), 'r')
+  f = open(pub_key, 'r')
   try:
-    utils.RemoveAuthorizedKey(os.path.join(user_ssh_dir, "authorized_keys"),
-                              f.read(8192))
+    utils.RemoveAuthorizedKey(auth_keys, f.read(8192))
   finally:
     f.close()
 
-
-  utils.RemoveFile(os.path.join(user_ssh_dir, "id_dsa"))
-  utils.RemoveFile(os.path.join(user_ssh_dir, "id_dsa.pub"))
+  utils.RemoveFile(priv_key)
+  utils.RemoveFile(pub_key)
 
 
 def GetNodeInfo(vgname):
diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index 46c5c6e..ea56345 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -476,24 +476,23 @@ def _InitSSHSetup(node):
     node: the name of this host as a fqdn
 
   """
-  if os.path.exists('/root/.ssh/id_dsa'):
-    utils.CreateBackup('/root/.ssh/id_dsa')
-  if os.path.exists('/root/.ssh/id_dsa.pub'):
-    utils.CreateBackup('/root/.ssh/id_dsa.pub')
+  priv_key, pub_key, auth_keys = ssh.GetUserFiles(constants.GANETI_RUNAS)
 
-  utils.RemoveFile('/root/.ssh/id_dsa')
-  utils.RemoveFile('/root/.ssh/id_dsa.pub')
+  for name in priv_key, pub_key:
+    if os.path.exists(name):
+      utils.CreateBackup(name)
+    utils.RemoveFile(name)
 
   result = utils.RunCmd(["ssh-keygen", "-t", "dsa",
-                         "-f", "/root/.ssh/id_dsa",
+                         "-f", priv_key,
                          "-q", "-N", ""])
   if result.failed:
     raise errors.OpExecError("Could not generate ssh keypair, error %s" %
                              result.output)
 
-  f = open('/root/.ssh/id_dsa.pub', 'r')
+  f = open(pub_key, 'r')
   try:
-    utils.AddAuthorizedKey('/root/.ssh/authorized_keys', f.read(8192))
+    utils.AddAuthorizedKey(auth_keys, f.read(8192))
   finally:
     f.close()
 
@@ -627,7 +626,7 @@ class LUInitCluster(LogicalUnit):
     rpc.call_node_start_master(hostname.name)
 
     # set up ssh config and /etc/hosts
-    f = open('/etc/ssh/ssh_host_rsa_key.pub', 'r')
+    f = open(constants.SSH_HOST_RSA_PUB, 'r')
     try:
       sshline = f.read()
     finally:
@@ -676,8 +675,9 @@ class LUDestroyCluster(NoHooksLU):
     """Destroys the cluster.
 
     """
-    utils.CreateBackup('/root/.ssh/id_dsa')
-    utils.CreateBackup('/root/.ssh/id_dsa.pub')
+    priv_key, pub_key, _ = ssh.GetUserFiles(constants.GANETI_RUNAS)
+    utils.CreateBackup(priv_key)
+    utils.CreateBackup(pub_key)
     rpc.call_node_leave_cluster(self.sstore.GetMasterNode())
 
 
@@ -1508,10 +1508,11 @@ class LUAddNode(LogicalUnit):
 
     # setup ssh on node
     logger.Info("copy ssh key to node %s" % node)
+    priv_key, pub_key, _ = ssh.GetUserFiles(constants.GANETI_RUNAS)
     keyarray = []
-    keyfiles = ["/etc/ssh/ssh_host_dsa_key", "/etc/ssh/ssh_host_dsa_key.pub",
-                "/etc/ssh/ssh_host_rsa_key", "/etc/ssh/ssh_host_rsa_key.pub",
-                "/root/.ssh/id_dsa", "/root/.ssh/id_dsa.pub"]
+    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')
diff --git a/lib/constants.py b/lib/constants.py
index 60dbb18..e7b33d5 100644
--- a/lib/constants.py
+++ b/lib/constants.py
@@ -110,6 +110,10 @@ LOCALHOST_IP_ADDRESS="127.0.0.1"
 TCP_PING_TIMEOUT = 10
 GANETI_RUNAS = "root"
 
-# external utilities
+# ssh constants
 SSH_INITD_SCRIPT = _autoconf.SSH_INITD_SCRIPT
-SSH_CONFIG_DIR = "/etc/ssh"
+SSH_CONFIG_DIR = "/etc/ssh/"
+SSH_HOST_DSA_PRIV = SSH_CONFIG_DIR + "ssh_host_dsa_key"
+SSH_HOST_DSA_PUB = SSH_HOST_DSA_PRIV + ".pub"
+SSH_HOST_RSA_PRIV = SSH_CONFIG_DIR + "ssh_host_rsa_key"
+SSH_HOST_RSA_PUB = SSH_HOST_RSA_PRIV + ".pub"
diff --git a/lib/ssh.py b/lib/ssh.py
index d82319d..2caab46 100644
--- a/lib/ssh.py
+++ b/lib/ssh.py
@@ -55,6 +55,41 @@ ASK_KEY_OPTS = [
   ]
 
 
+def GetUserFiles(user, mkdir=False):
+  """Return the paths of a user's ssh files.
+
+  The function will return a triplet (priv_key_path, pub_key_path,
+  auth_key_path) that are used for ssh authentication. Currently, the
+  keys used are DSA keys, so this function will return:
+  (~user/.ssh/id_dsa, ~user/.ssh/id_dsa.pub,
+  ~user/.ssh/authorized_keys).
+
+  If the optional parameter mkdir is True, the ssh directory will be
+  created if it doesn't exist.
+
+  Regardless of the mkdir parameters, the script will raise an error
+  if ~user/.ssh is not a directory.
+
+  """
+  user_dir = utils.GetHomeDir(user)
+  if not user_dir:
+    raise errors.OpExecError("Cannot resolve home of user %s" % user)
+
+  ssh_dir = os.path.join(user_dir, ".ssh")
+  if not os.path.lexists(ssh_dir):
+    if mkdir:
+      try:
+        os.mkdir(ssh_dir, 0700)
+      except EnvironmentError, err:
+        raise errors.OpExecError("Can't create .ssh dir for user %s: %s" %
+                                 (user, str(err)))
+  elif not os.path.isdir(ssh_dir):
+    raise errors.OpExecError("path ~%s/.ssh is not a directory" % user)
+
+  return [os.path.join(ssh_dir, base)
+          for base in ["id_dsa", "id_dsa.pub", "authorized_keys"]]
+
+
 def BuildSSHCmd(hostname, user, command, batch=True, ask_key=False):
   """Build an ssh string to execute a command on a remote node.
 
