示例#1
0
 def _create_client(self):
     client = Connection(self.host, self.port)
     client.connect()
     return client
示例#2
0
 def _get_client(self):
     client = Connection(self.config.host, self.config.port)
     timeout = int(float(self.config.timeout) * 1000)
     client.connect(None, timeout, timeout)
     return client
示例#3
0
 def open_connection(self, host, port, timeout):
     self.client = Connection(host, int(port))
     timeout = int(timeout) * 1000
     self.client.connect(None, timeout, timeout)
示例#4
0
 def _get_client(self):
     client = Connection(self.config.host, self.config.port)
     timeout = int(float(self.config.timeout)*1000)
     client.connect(None, timeout, timeout)
     return client
示例#5
0
class SSHClient(object):

    BUFFER_SIZE = 32768

    def __init__(self):
        self.client = None
        self.su_username = None
        self.su_password = None

    def open_connection(self, host, port, timeout):
        self.client = Connection(host, int(port))
        timeout = int(timeout) * 1000
        self.client.connect(None, timeout, timeout)

    def login(self, username, password):
        if not self.client.authenticateWithPassword(username, password):
            raise SSHException('Login failed with username "%s"' % username)

    def set_su_user(self, username, password=None):
        self.su_username = username
        self.su_password = password

    def get_su_username(self):
        return self.su_username

    def get_su_command(self, command):
        if self.su_username:
            if re.search("'", command):
                raise SSHException(
                    'Su command may not contain single quotes. Consider using double quotes: "'
                    + command + '"')
            return "su - %s -c '%s'" % (self.su_username, command)
        return command

    def close_connection(self):
        self.client.close()

    def get_scp_client(self):
        return SCPClient(self.client)

    def execute_command(self, command):
        chan = self.client.openSession()
        try:
            if self.su_username and self.su_password:
                chan.requestPTY('vt100', 80, 24, 0, 0, None)
            chan.execCommand(command)
            stdin = chan.getStdin()
            stdout = BufferedReader(
                InputStreamReader(StreamGobbler(chan.getStdout())))
            stderr = BufferedReader(
                InputStreamReader(StreamGobbler(chan.getStderr())))

            out = ""
            data = jarray.zeros(SSHClient.BUFFER_SIZE, 'c')
            password_sent = False
            endcond = ChannelCondition.CLOSED | ChannelCondition.EOF | \
                ChannelCondition.EXIT_SIGNAL | ChannelCondition.EXIT_STATUS
            if self.su_username and self.su_password:
                for _ in range(100):
                    cond = chan.waitForCondition(endcond,
                                                 10)  # arg2 timeout in ms
                    if (cond & ChannelCondition.TIMEOUT) == 0:
                        break  # not timeout, must be some of the expected conds
                    if not stdout.ready():
                        time.sleep(0.1)
                    else:
                        datalen = stdout.read(data, 0, SSHClient.BUFFER_SIZE)
                        if datalen == -1:
                            break
                        if datalen > 0:
                            out += ''.join([str(c) for c in data[0:datalen]])
                        outmatch = re.match(".*[P|p]assword:\s*$", out,
                                            re.DOTALL)
                        if outmatch:
                            stdin.write('%s\n' % self.su_password)
                            stdin.flush()
                            password_sent = True
                            break

            if password_sent:
                out = ""

            counter = 0
            while True:
                cond = chan.waitForCondition(endcond, 10)  # arg2 timeout in ms
                if (cond & ChannelCondition.TIMEOUT) == 0:
                    break  # not timeout, must be some of the expected conds
                counter = (counter + 1) % 10
                if counter == 0:
                    try:
                        self.client.sendIgnorePacket()
                    except IOException:
                        break
                time.sleep(0.1)

            out += self._read_output(stdout)
            err = self._read_output(stderr)
            stat = chan.getExitStatus()
            if stat is None:
                stat = Result.UNKNOWN_STATUS
            else:
                stat = str(stat)
            return stat, out, err
        finally:
            chan.close()

    @staticmethod
    def _read_output(reader):
        lines = ''
        line = reader.readLine()
        while line is not None:
            lines += line + '\n'
            line = reader.readLine()
        return lines

    def put_file(self, src_file, dst_dir, mode):
        src_file.replace('/', os.sep)
        mode = int(mode, 8)
        sftp = SFTPv3Client(self.client)
        src_fd = None
        dst_fd = None
        try:
            dst_dir = self._resolve_dir(sftp, dst_dir)
            self._create_missing_dirs(sftp, dst_dir)
            dst_file = posixpath.join(dst_dir, os.path.basename(src_file))
            src_fd = open(src_file, 'rb')
            dst_fd = sftp.createFile(dst_file)
            stats = sftp.fstat(dst_fd)
            stats.permissions = mode
            sftp.fsetstat(dst_fd, stats)
            size = 0
            while True:
                data = src_fd.read(SSHClient.BUFFER_SIZE)
                datalen = len(data)
                if datalen == 0:
                    break
                sftp.write(dst_fd, size, data, 0, datalen)
                size += datalen
        finally:
            if dst_fd:
                sftp.closeFile(dst_fd)
            if src_fd:
                src_fd.close()
            sftp.close()

    @staticmethod
    def _resolve_dir(sftp, dst_dir):
        dst_home = sftp.canonicalPath('.')
        dst_dir = dst_dir.split(':')[-1].replace('\\', '/')
        if dst_dir == '.':
            dst_dir = dst_home + '/'
        if not posixpath.isabs(dst_dir):
            dst_dir = posixpath.join(dst_home, dst_dir)
        return dst_dir

    @staticmethod
    def _create_missing_dirs(sftp, dst_dir):
        curdir = '/'
        for dir in dst_dir.split('/'):
            if dir:
                curdir = '%s/%s' % (curdir, dir)
            try:
                sftp.stat(curdir)
            except IOException:
                sftp.mkdir(curdir, 0744)

    def get_file(self, src_file, dst_file):
        sftp = SFTPv3Client(self.client)
        dst_fd = None
        src_fd = None
        try:
            dst_file = os.path.abspath(dst_file.replace('/', os.sep))
            dst_dir = os.path.dirname(dst_file)
            if not os.path.exists(dst_dir):
                os.makedirs(dst_dir)
            dst_fd = FileOutputStream(dst_file)
            stats = sftp.stat(src_file)
            src_size = stats.size
            src_fd = sftp.openFileRO(src_file)
            size = 0
            arraysize = SSHClient.BUFFER_SIZE
            data = jarray.zeros(arraysize, 'b')
            while True:
                moredata = sftp.read(src_fd, size, data, 0, arraysize)
                datalen = len(data)
                if moredata == -1:
                    break
                if src_size - size < arraysize:
                    datalen = src_size - size
                dst_fd.write(data, 0, datalen)
                size += datalen
        finally:
            if src_fd:
                sftp.closeFile(src_fd)
            if dst_fd:
                dst_fd.flush()
                dst_fd.close()
            sftp.close()

    def copy_file(self, src_file, to_fd):
        sftp = SFTPv3Client(self.client)
        from_fd = None
        try:
            stats = sftp.stat(src_file)
            src_size = stats.size
            from_fd = sftp.openFileRO(src_file)
            file_to_size = 0
            arraysize = SSHClient.BUFFER_SIZE
            data = jarray.zeros(arraysize, 'b')
            while True:
                moredata = sftp.read(from_fd, file_to_size, data, 0, arraysize)
                datalen = len(data)
                if moredata == -1:
                    break
                if src_size - file_to_size < arraysize:
                    datalen = src_size - file_to_size
                to_fd.write(data)
                file_to_size += datalen
        finally:
            if from_fd:
                sftp.closeFile(from_fd)
            sftp.close()
        if src_size != file_to_size:
            raise IOError('Size mismatch in copying:  %d != %d' %
                          (src_size, file_to_size))

    def get_remote_fd(self, dir, filename):
        sftp = SFTPv3Client(self.client)
        dir = self._resolve_dir(sftp, dir)
        self._create_missing_dirs(sftp, dir)
        file_path = posixpath.join(dir, filename)
        fd = sftp.createFile(file_path)
        return SFTPRemoteFile(sftp, fd)