Commit c92b310a authored by Michael Hanselmann's avatar Michael Hanselmann
Browse files

Move SSH functions into a class

This renames some functions and does some minor codestyle cleanup.

Reviewed-by: ultrotter
parent 75a5f456
...@@ -42,6 +42,10 @@ from ganeti import objects ...@@ -42,6 +42,10 @@ from ganeti import objects
from ganeti import ssconf from ganeti import ssconf
def _GetSshRunner():
return ssh.SshRunner()
def StartMaster(): def StartMaster():
"""Activate local node as master node. """Activate local node as master node.
...@@ -197,7 +201,7 @@ def VerifyNode(what): ...@@ -197,7 +201,7 @@ def VerifyNode(what):
if 'nodelist' in what: if 'nodelist' in what:
result['nodelist'] = {} result['nodelist'] = {}
for node in what['nodelist']: for node in what['nodelist']:
success, message = ssh.VerifyNodeHostname(node) success, message = _GetSshRunner().VerifyNodeHostname(node)
if not success: if not success:
result['nodelist'][node] = message result['nodelist'][node] = message
return result return result
...@@ -1188,9 +1192,8 @@ def ExportSnapshot(disk, dest_node, instance): ...@@ -1188,9 +1192,8 @@ def ExportSnapshot(disk, dest_node, instance):
destcmd = utils.BuildShellCmd("mkdir -p %s && cat > %s/%s", destcmd = utils.BuildShellCmd("mkdir -p %s && cat > %s/%s",
destdir, destdir, destfile) destdir, destdir, destfile)
remotecmd = ssh.BuildSSHCmd(dest_node, constants.GANETI_RUNAS, destcmd) remotecmd = _GetSshRunner().BuildCmd(dest_node, constants.GANETI_RUNAS,
destcmd)
# all commands have been checked, so we're safe to combine them # all commands have been checked, so we're safe to combine them
command = '|'.join([expcmd, comprcmd, utils.ShellQuoteArgs(remotecmd)]) command = '|'.join([expcmd, comprcmd, utils.ShellQuoteArgs(remotecmd)])
...@@ -1331,7 +1334,8 @@ def ImportOSIntoInstance(instance, os_disk, swap_disk, src_node, src_image): ...@@ -1331,7 +1334,8 @@ def ImportOSIntoInstance(instance, os_disk, swap_disk, src_node, src_image):
os.mkdir(constants.LOG_OS_DIR, 0750) os.mkdir(constants.LOG_OS_DIR, 0750)
destcmd = utils.BuildShellCmd('cat %s', src_image) destcmd = utils.BuildShellCmd('cat %s', src_image)
remotecmd = ssh.BuildSSHCmd(src_node, constants.GANETI_RUNAS, destcmd) remotecmd = _GetSshRunner().BuildCmd(src_node, constants.GANETI_RUNAS,
destcmd)
comprcmd = "gunzip" comprcmd = "gunzip"
impcmd = utils.BuildShellCmd("(cd %s; %s -i %s -b %s -s %s &>%s)", impcmd = utils.BuildShellCmd("(cd %s; %s -i %s -b %s -s %s &>%s)",
......
...@@ -74,6 +74,8 @@ class LogicalUnit(object): ...@@ -74,6 +74,8 @@ class LogicalUnit(object):
self.op = op self.op = op
self.cfg = cfg self.cfg = cfg
self.sstore = sstore self.sstore = sstore
self.__ssh = None
for attr_name in self._OP_REQP: for attr_name in self._OP_REQP:
attr_val = getattr(op, attr_name, None) attr_val = getattr(op, attr_name, None)
if attr_val is None: if attr_val is None:
...@@ -89,6 +91,16 @@ class LogicalUnit(object): ...@@ -89,6 +91,16 @@ class LogicalUnit(object):
raise errors.OpPrereqError("Commands must be run on the master" raise errors.OpPrereqError("Commands must be run on the master"
" node %s" % master) " node %s" % master)
def __GetSSH(self):
"""Returns the SshRunner object
"""
if not self.__ssh:
self.__ssh = ssh.SshRunner()
return self.__ssh
ssh = property(fget=__GetSSH)
def CheckPrereq(self): def CheckPrereq(self):
"""Check prerequisites for this LU. """Check prerequisites for this LU.
...@@ -1229,7 +1241,7 @@ class LURemoveNode(LogicalUnit): ...@@ -1229,7 +1241,7 @@ class LURemoveNode(LogicalUnit):
rpc.call_node_leave_cluster(node.name) rpc.call_node_leave_cluster(node.name)
ssh.SSHCall(node.name, 'root', "%s stop" % constants.NODE_INITD_SCRIPT) self.ssh.Run(node.name, 'root', "%s stop" % constants.NODE_INITD_SCRIPT)
logger.Info("Removing node %s from config" % node.name) logger.Info("Removing node %s from config" % node.name)
...@@ -1539,7 +1551,7 @@ class LUAddNode(LogicalUnit): ...@@ -1539,7 +1551,7 @@ class LUAddNode(LogicalUnit):
constants.SSL_CERT_FILE, gntpem, constants.SSL_CERT_FILE, gntpem,
constants.NODE_INITD_SCRIPT)) constants.NODE_INITD_SCRIPT))
result = ssh.SSHCall(node, 'root', mycommand, batch=False, ask_key=True) result = self.ssh.Run(node, 'root', mycommand, batch=False, ask_key=True)
if result.failed: if result.failed:
raise errors.OpExecError("Remote command on node %s, error: %s," raise errors.OpExecError("Remote command on node %s, error: %s,"
" output: %s" % " output: %s" %
...@@ -1597,7 +1609,7 @@ class LUAddNode(LogicalUnit): ...@@ -1597,7 +1609,7 @@ class LUAddNode(LogicalUnit):
" you gave (%s). Please fix and re-run this" " you gave (%s). Please fix and re-run this"
" command." % new_node.secondary_ip) " command." % new_node.secondary_ip)
success, msg = ssh.VerifyNodeHostname(node) success, msg = self.ssh.VerifyNodeHostname(node)
if not success: if not success:
raise errors.OpExecError("Node '%s' claims it has a different hostname" raise errors.OpExecError("Node '%s' claims it has a different hostname"
" than the one the resolver gives: %s." " than the one the resolver gives: %s."
...@@ -1623,7 +1635,7 @@ class LUAddNode(LogicalUnit): ...@@ -1623,7 +1635,7 @@ class LUAddNode(LogicalUnit):
if self.sstore.GetHypervisorType() == constants.HT_XEN_HVM31: if self.sstore.GetHypervisorType() == constants.HT_XEN_HVM31:
to_copy.append(constants.VNC_PASSWORD_FILE) to_copy.append(constants.VNC_PASSWORD_FILE)
for fname in to_copy: for fname in to_copy:
if not ssh.CopyFileToNode(node, fname): if not self.ssh.CopyFileToNode(node, fname):
logger.Error("could not copy file %s to node %s" % (fname, node)) logger.Error("could not copy file %s to node %s" % (fname, node))
logger.Info("adding node %s to cluster.conf" % node) logger.Info("adding node %s to cluster.conf" % node)
...@@ -1767,7 +1779,7 @@ class LUClusterCopyFile(NoHooksLU): ...@@ -1767,7 +1779,7 @@ class LUClusterCopyFile(NoHooksLU):
for node in self.nodes: for node in self.nodes:
if node == myname: if node == myname:
continue continue
if not ssh.CopyFileToNode(node, filename): if not self.ssh.CopyFileToNode(node, filename):
logger.Error("Copy of file %s to node %s failed" % (filename, node)) logger.Error("Copy of file %s to node %s failed" % (filename, node))
...@@ -1810,7 +1822,7 @@ class LURunClusterCommand(NoHooksLU): ...@@ -1810,7 +1822,7 @@ class LURunClusterCommand(NoHooksLU):
""" """
data = [] data = []
for node in self.nodes: for node in self.nodes:
result = ssh.SSHCall(node, "root", self.op.command) result = self.ssh.Run(node, "root", self.op.command)
data.append((node, result.output, result.exit_code)) data.append((node, result.output, result.exit_code))
return data return data
......
...@@ -32,10 +32,6 @@ from ganeti import errors ...@@ -32,10 +32,6 @@ from ganeti import errors
from ganeti import constants from ganeti import constants
__all__ = ["SSHCall", "CopyFileToNode", "VerifyNodeHostname",
"KNOWN_HOSTS_OPTS", "BATCH_MODE_OPTS", "ASK_KEY_OPTS"]
KNOWN_HOSTS_OPTS = [ KNOWN_HOSTS_OPTS = [
"-oGlobalKnownHostsFile=%s" % constants.SSH_KNOWN_HOSTS_FILE, "-oGlobalKnownHostsFile=%s" % constants.SSH_KNOWN_HOSTS_FILE,
"-oUserKnownHostsFile=/dev/null", "-oUserKnownHostsFile=/dev/null",
...@@ -90,8 +86,12 @@ def GetUserFiles(user, mkdir=False): ...@@ -90,8 +86,12 @@ def GetUserFiles(user, mkdir=False):
for base in ["id_dsa", "id_dsa.pub", "authorized_keys"]] for base in ["id_dsa", "id_dsa.pub", "authorized_keys"]]
def BuildSSHCmd(hostname, user, command, batch=True, ask_key=False): class SshRunner:
"""Build an ssh string to execute a command on a remote node. """Wrapper for SSH commands.
"""
def BuildCmd(self, hostname, user, command, batch=True, ask_key=False):
"""Build an ssh command to execute a command on a remote node.
Args: Args:
hostname: the target host, string hostname: the target host, string
...@@ -117,9 +117,8 @@ def BuildSSHCmd(hostname, user, command, batch=True, ask_key=False): ...@@ -117,9 +117,8 @@ def BuildSSHCmd(hostname, user, command, batch=True, ask_key=False):
argv.extend(["%s@%s" % (user, hostname), command]) argv.extend(["%s@%s" % (user, hostname), command])
return argv return argv
def Run(self, hostname, user, command, batch=True, ask_key=False):
def SSHCall(hostname, user, command, batch=True, ask_key=False): """Runs a command on a remote node.
"""Execute a command on a remote node.
This method has the same return value as `utils.RunCmd()`, which it This method has the same return value as `utils.RunCmd()`, which it
uses to launch ssh. uses to launch ssh.
...@@ -133,14 +132,13 @@ def SSHCall(hostname, user, command, batch=True, ask_key=False): ...@@ -133,14 +132,13 @@ def SSHCall(hostname, user, command, batch=True, ask_key=False):
we can connect to an unknown host (not valid in batch mode) we can connect to an unknown host (not valid in batch mode)
Returns: Returns:
`utils.RunResult` as for `utils.RunCmd()` `utils.RunResult` like `utils.RunCmd()`
""" """
return utils.RunCmd(BuildSSHCmd(hostname, user, command, return utils.RunCmd(self.BuildCmd(hostname, user, command, batch=batch,
batch=batch, ask_key=ask_key)) ask_key=ask_key))
def CopyFileToNode(node, filename): def CopyFileToNode(self, node, filename):
"""Copy a file to another node with scp. """Copy a file to another node with scp.
Args: Args:
...@@ -174,11 +172,9 @@ def CopyFileToNode(node, filename): ...@@ -174,11 +172,9 @@ def CopyFileToNode(node, filename):
return not result.failed return not result.failed
def VerifyNodeHostname(self, node):
def VerifyNodeHostname(node):
"""Verify hostname consistency via SSH. """Verify hostname consistency via SSH.
This functions connects via ssh to a node and compares the hostname This functions connects via ssh to a node and compares the hostname
reported by the node to the name with have (the one that we reported by the node to the name with have (the one that we
connected to). connected to).
...@@ -197,7 +193,7 @@ def VerifyNodeHostname(node): ...@@ -197,7 +193,7 @@ def VerifyNodeHostname(node):
detail: String with details detail: String with details
""" """
retval = SSHCall(node, 'root', 'hostname') retval = self.Run(node, 'root', 'hostname')
if retval.failed: if retval.failed:
msg = "ssh problem" msg = "ssh problem"
......
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