X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/1d544ba38373096575207fceef815e11dc0bc985..e310b019ad43467bc243d886d50597de5d81c27a:/lib/ssh.py diff --git a/lib/ssh.py b/lib/ssh.py index 6f32e56..7d314e2 100644 --- a/lib/ssh.py +++ b/lib/ssh.py @@ -33,25 +33,6 @@ from ganeti import constants from ganeti import ssconf -KNOWN_HOSTS_OPTS = [ - "-oGlobalKnownHostsFile=%s" % constants.SSH_KNOWN_HOSTS_FILE, - "-oUserKnownHostsFile=/dev/null", - ] - -# Note: BATCH_MODE conflicts with ASK_KEY -BATCH_MODE_OPTS = [ - "-oBatchMode=yes", - "-oEscapeChar=none", - "-oStrictHostKeyChecking=yes", - ] - -ASK_KEY_OPTS = [ - "-oEscapeChar=none", - "-oHashKnownHosts=no", - "-oStrictHostKeyChecking=ask", - ] - - def GetUserFiles(user, mkdir=False): """Return the paths of a user's ssh files. @@ -97,11 +78,42 @@ class SshRunner: else: self.sstore = sstore - def _GetHostKeyAliasOption(self): - return "-oHostKeyAlias=%s" % self.sstore.GetClusterName() + def _BuildSshOptions(self, batch, ask_key, use_cluster_key, + strict_host_check): + options = [ + "-oEscapeChar=none", + "-oHashKnownHosts=no", + "-oGlobalKnownHostsFile=%s" % constants.SSH_KNOWN_HOSTS_FILE, + "-oUserKnownHostsFile=/dev/null", + ] + + if use_cluster_key: + options.append("-oHostKeyAlias=%s" % self.sstore.GetClusterName()) + + # TODO: Too many boolean options, maybe convert them to more descriptive + # constants. + + # Note: ask_key conflicts with batch mode + if batch: + if ask_key: + raise errors.ProgrammerError("SSH call requested conflicting options") + + options.append("-oBatchMode=yes") + + if strict_host_check: + options.append("-oStrictHostKeyChecking=yes") + else: + options.append("-oStrictHostKeyChecking=no") + + elif ask_key: + options.extend([ + "-oStrictHostKeyChecking=ask", + ]) + + return options def BuildCmd(self, hostname, user, command, batch=True, ask_key=False, - tty=False): + tty=False, use_cluster_key=True, strict_host_check=True): """Build an ssh command to execute a command on a remote node. Args: @@ -111,46 +123,35 @@ class SshRunner: 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 Returns: The ssh call to run 'command' on the remote host. """ argv = [constants.SSH, "-q"] - argv.extend(KNOWN_HOSTS_OPTS) - argv.append(self._GetHostKeyAliasOption()) - if batch: - # if we are in batch mode, we can't ask the key - if ask_key: - raise errors.ProgrammerError("SSH call requested conflicting options") - argv.extend(BATCH_MODE_OPTS) - elif ask_key: - argv.extend(ASK_KEY_OPTS) + argv.extend(self._BuildSshOptions(batch, ask_key, use_cluster_key, + strict_host_check)) if tty: argv.append("-t") argv.extend(["%s@%s" % (user, hostname), command]) return argv - def Run(self, hostname, user, command, batch=True, ask_key=False): + def Run(self, *args, **kwargs): """Runs a command on a remote node. This method has the same return value as `utils.RunCmd()`, which it uses to launch ssh. 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) + See SshRunner.BuildCmd. Returns: `utils.RunResult` like `utils.RunCmd()` """ - return utils.RunCmd(self.BuildCmd(hostname, user, command, batch=batch, - ask_key=ask_key)) + return utils.RunCmd(self.BuildCmd(*args, **kwargs)) def CopyFileToNode(self, node, filename): """Copy a file to another node with scp. @@ -172,9 +173,7 @@ class SshRunner: return False command = [constants.SCP, "-q", "-p"] - command.extend(KNOWN_HOSTS_OPTS) - command.extend(BATCH_MODE_OPTS) - command.append(self._GetHostKeyAliasOption()) + command.extend(self._BuildSshOptions(True, False, True, True)) command.append(filename) command.append("%s:%s" % (node, filename))