X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/652d66942d3bc99b831e18140c05e4ef81316232..da961187f97344fde390140ebb2f10d10d334d51:/lib/ssh.py diff --git a/lib/ssh.py b/lib/ssh.py index 7d314e2..40df999 100644 --- a/lib/ssh.py +++ b/lib/ssh.py @@ -25,12 +25,11 @@ import os +import logging -from ganeti import logger from ganeti import utils from ganeti import errors from ganeti import constants -from ganeti import ssconf def GetUserFiles(user, mkdir=False): @@ -72,14 +71,24 @@ class SshRunner: """Wrapper for SSH commands. """ - def __init__(self, sstore=None): - if sstore is None: - self.sstore = ssconf.SimpleStore() - else: - self.sstore = sstore + def __init__(self, cluster_name): + self.cluster_name = cluster_name def _BuildSshOptions(self, batch, ask_key, use_cluster_key, strict_host_check): + """Builds a list with needed SSH options. + + @param batch: same as ssh's batch option + @param ask_key: allows ssh to ask for key confirmation; this + parameter conflicts with the batch one + @param use_cluster_key: if True, use the cluster name as the + HostKeyAlias name + @param strict_host_check: this makes the host key checking strict + + @rtype: list + @return: the list of options ready to use in L{utils.RunCmd} + + """ options = [ "-oEscapeChar=none", "-oHashKnownHosts=no", @@ -88,7 +97,7 @@ class SshRunner: ] if use_cluster_key: - options.append("-oHostKeyAlias=%s" % self.sstore.GetClusterName()) + options.append("-oHostKeyAlias=%s" % self.cluster_name) # TODO: Too many boolean options, maybe convert them to more descriptive # constants. @@ -116,18 +125,18 @@ class SshRunner: tty=False, use_cluster_key=True, strict_host_check=True): """Build an ssh command to execute a command on a remote node. - Args: - 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) - use_cluster_key: Whether to expect and use the cluster-global SSH key - strict_host_check: Whether to check the host's SSH key at all + @param hostname: the target host, string + @param user: user to auth as + @param command: the command + @param batch: if true, ssh will run in batch mode with no prompting + @param ask_key: if true, ssh will run with + StrictHostKeyChecking=ask, so that we can connect to an + unknown host (not valid in batch mode) + @param use_cluster_key: whether to expect and use the + cluster-global SSH key + @param strict_host_check: whether to check the host's SSH key at all - Returns: - The ssh call to run 'command' on the remote host. + @return: the ssh call to run 'command' on the remote host. """ argv = [constants.SSH, "-q"] @@ -144,11 +153,10 @@ class SshRunner: This method has the same return value as `utils.RunCmd()`, which it uses to launch ssh. - Args: - See SshRunner.BuildCmd. + Args: see SshRunner.BuildCmd. - Returns: - `utils.RunResult` like `utils.RunCmd()` + @rtype: L{utils.RunResult} + @return: the result as from L{utils.RunCmd()} """ return utils.RunCmd(self.BuildCmd(*args, **kwargs)) @@ -156,20 +164,19 @@ class SshRunner: def CopyFileToNode(self, node, filename): """Copy a file to another node with scp. - Args: - node: node in the cluster - filename: absolute pathname of a local file + @param node: node in the cluster + @param filename: absolute pathname of a local file - Returns: - success: True/False + @rtype: boolean + @return: the success of the operation """ if not os.path.isabs(filename): - logger.Error("file %s must be an absolute path" % (filename)) + logging.error("File %s must be an absolute path", filename) return False if not os.path.isfile(filename): - logger.Error("file %s does not exist" % (filename)) + logging.error("File %s does not exist", filename) return False command = [constants.SCP, "-q", "-p"] @@ -180,9 +187,9 @@ class SshRunner: result = utils.RunCmd(command) if result.failed: - logger.Error("copy to node %s failed (%s) error %s," - " command was %s" % - (node, result.fail_reason, result.output, result.cmd)) + logging.error("Copy to node %s failed (%s) error %s," + " command was %s", + node, result.fail_reason, result.output, result.cmd) return not result.failed @@ -197,14 +204,12 @@ class SshRunner: (conflicting known hosts) and incosistencies between dns/hosts entries and local machine names - Args: - node: nodename of a host to check. can be short or full qualified hostname + @param node: nodename of a host to check; can be short or + full qualified hostname - Returns: - (success, detail) - where - success: True/False - detail: String with details + @return: (success, detail), where: + - success: True/False + - detail: string with details """ retval = self.Run(node, 'root', 'hostname') @@ -214,6 +219,9 @@ class SshRunner: output = retval.output if output: msg += ": %s" % output + else: + msg += ": %s (no output)" % retval.fail_reason + logging.error("Command %s failed: %s" % (retval.cmd, msg)) return False, msg remotehostname = retval.stdout.strip() @@ -224,10 +232,10 @@ class SshRunner: return True, "host matches" -def WriteKnownHostsFile(cfg, sstore, file_name): +def WriteKnownHostsFile(cfg, file_name): """Writes the cluster-wide equally known_hosts file. """ - utils.WriteFile(file_name, mode=0700, - data="%s ssh-rsa %s\n" % (sstore.GetClusterName(), + utils.WriteFile(file_name, mode=0600, + data="%s ssh-rsa %s\n" % (cfg.GetClusterName(), cfg.GetHostKey()))