class SSHExecuter(object): COPY_COMMAND_TEMPLATE = """ #!/bin/sh cp -p "{0}" "{1}" """ COPY_RECURSIVE_COMMAND_TEMPLATE = """ #!/bin/sh cp -rp "{0}" "{1}" """ SYMLINK_COMMAND_TEMPLATE = """ #!/bin/sh ln -s "{0}" "{1}" """ def __init__(self, uri, credential): self.executer = SSHExec(uri, credential) def local_copy(self, src, dest, recursive=False): logger.debug('SSH Local Copy %s => %s', src, dest) if recursive: cmd = self.COPY_RECURSIVE_COMMAND_TEMPLATE.format(src, dest) else: cmd = self.COPY_COMMAND_TEMPLATE.format(src, dest) exit_code, stdout, stderr = self.executer.exec_script(cmd) if exit_code > 0 or stderr: raise RuntimeError( "Couldn't (recursive=%s) copy %s to %s. Exit code: %s. STDERR:\n%s" % (recursive, src, dest, exit_code, stderr)) return True def local_symlink(self, src, dest): logger.debug('SSH Local Symlink %s => %s', src, dest) cmd = self.SYMLINK_COMMAND_TEMPLATE.format(src, dest) exit_code, stdout, stderr = self.executer.exec_script(cmd) if exit_code > 0 or stderr: raise RuntimeError( "Couldn't symlink %s to %s. Exit code: %s. STDERR:\n%s" % (src, dest, exit_code, stderr)) return True def download_dir_as_tarball(self, remotepath, outfile): parent_dir, target_dir = remotepath.rstrip('/').rsplit('/', 1) command = 'tar -cz -C "%s" "%s"' % (parent_dir, target_dir) logger.debug("execing command: %s" % command) with self.executer.sshclient() as client: try: stdin, stdout, stderr = client.exec_command(command) while not stdout.channel.exit_status_ready(): rl, wl, xl = select.select([stdout.channel], [], []) if len(rl) > 0: while stdout.channel.recv_ready(): data = stdout.channel.recv(BLOCK_SIZE) outfile.write(data) # Stdout might still have data, flush it all out data = stdout.channel.recv(BLOCK_SIZE) while data: outfile.write(data) data = stdout.channel.recv(BLOCK_SIZE) exit_status = stdout.channel.exit_status logger.debug("Exit status: %s", exit_status) if exit_status != 0: raise RetryException( "Exit status %s received why trying to tarball %s" % (exit_status, remotepath)) except paramiko.SSHException as sshe: raise RetryException(sshe, traceback.format_exc()) return exit_status == 0
class SSHExecuter(object): COPY_COMMAND_TEMPLATE = """ #!/bin/sh cp -p "{0}" "{1}" """ COPY_RECURSIVE_COMMAND_TEMPLATE = """ #!/bin/sh cp -rp "{0}" "{1}" """ SYMLINK_COMMAND_TEMPLATE = """ #!/bin/sh ln -s "{0}" "{1}" """ def __init__(self, uri, credential): self.executer = SSHExec(uri, credential) def local_copy(self, src, dest, recursive=False): logger.debug("SSH Local Copy %s => %s", src, dest) if recursive: cmd = self.COPY_RECURSIVE_COMMAND_TEMPLATE.format(src, dest) else: cmd = self.COPY_COMMAND_TEMPLATE.format(src, dest) exit_code, stdout, stderr = self.executer.exec_script(cmd) if exit_code > 0 or stderr: raise RuntimeError( "Couldn't (recursive=%s) copy %s to %s. Exit code: %s. STDERR:\n%s" % (recursive, src, dest, exit_code, stderr) ) return True def local_symlink(self, src, dest): logger.debug("SSH Local Symlink %s => %s", src, dest) cmd = self.SYMLINK_COMMAND_TEMPLATE.format(src, dest) exit_code, stdout, stderr = self.executer.exec_script(cmd) if exit_code > 0 or stderr: raise RuntimeError("Couldn't symlink %s to %s. Exit code: %s. STDERR:\n%s" % (src, dest, exit_code, stderr)) return True def download_dir_as_tarball(self, remotepath, outfile): parent_dir, target_dir = remotepath.rstrip("/").rsplit("/", 1) command = 'tar -cz -C "%s" "%s"' % (parent_dir, target_dir) logger.debug("execing command: %s" % command) with self.executer.sshclient() as client: try: stdin, stdout, stderr = client.exec_command(command) while not stdout.channel.exit_status_ready(): rl, wl, xl = select.select([stdout.channel], [], []) if len(rl) > 0: while stdout.channel.recv_ready(): data = stdout.channel.recv(BLOCK_SIZE) outfile.write(data) # Stdout might still have data, flush it all out data = stdout.channel.recv(BLOCK_SIZE) while data: outfile.write(data) data = stdout.channel.recv(BLOCK_SIZE) exit_status = stdout.channel.exit_status logger.debug("Exit status: %s", exit_status) if exit_status != 0: raise RetryException("Exit status %s received why trying to tarball %s" % (exit_status, remotepath)) except paramiko.SSHException as sshe: raise RetryException(sshe, traceback.format_exc()) return exit_status == 0