Exemplo n.º 1
0
class SSHCollector(Thread):
    def __init__(self, hostname, username, password, proto,
            loggername, zapiport, sshport=22, keepalive=True, timeout=60):
        Thread.__init__(self)
        self.hostname = hostname
        self.username = username
        self.password = password
        self.keepalive = keepalive
        self.timeout = timeout
        self._conn = None
        self.success = False
        self.client = SSHClient()
        self.client.load_system_host_keys()
        self.client.set_missing_host_key_policy(AutoAddPolicy())
        self.client.set_log_channel(loggername)

    def _connect(self):
        if None is not self.client.get_transport() and \
            self.client.get_transport().is_active():
            return
        if None is self.username:
            self.client.connect(hostname=self.hostname,
                                timeout=self.timeout)
        elif None is self.password:
            self.client.connect(hostname=self.hostname,
                                username=self.username,
                                password=self.password,
                                timeout=self.timeout)
        else:
            self.client.connect(hostname=self.hostname,
                                username=self.username,
                                password=self.password,
                                look_for_keys=False,
                                timeout=self.timeout)
        trans = self.client.get_transport()
        trans.use_compression(True)
        trans.set_keepalive(1)

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

    __del__ = close

    def execute(self, lcmd, auto_close=False, timeout=300, read_max=10*1024*1024):
        output = r''
        err = r''
        self._error = ""
        read_max = int(read_max/2)
        exit_status = False

        self._connect()
        chan = self.client.get_transport().open_session()
        if not self.keepalive:
            self.client.get_transport().set_keepalive(0)
        chan.settimeout(timeout)
        chan.exec_command(lcmd)

        stdin = chan.makefile('wb', -1)
        stdout = chan.makefile('rb', -1)
        stderr = chan.makefile_stderr('rb', -1)

        start_time = time.time()

        while True:
            if stderr.channel.recv_stderr_ready():
                ret = stderr.read()
                if ret:
                    err += ret

            if stdout.channel.recv_ready():
                try:
                    ret = stdout.read(read_max)
                    if ret:
                        output += ret
                except socket.timeout:
                    pass

            exit_status = chan.exit_status_ready()
            if exit_status or ((int(start_time) + timeout) < int(time.time())):
                timeout = False
                if exit_status:
                    exit_status = str(stderr.channel.recv_exit_status())
                else:
                    self.signal(chan, 'KILL')
                    exit_status = str(stderr.channel.recv_exit_status())
                    timeout = True

            if stdin:
                stdin.channel.shutdown_write()
                stdin.close()

            if stdout.channel.recv_ready():
                ret = stdout.read(read_max)
                if ret:
                    output += ret
            stdout.close()

            if stderr.channel.recv_stderr_ready():
                ret = stderr.read()
                if ret:
                    err += ret
            err += "exit_status("+str(exit_status)+") to("+str(timeout)+")"
            stderr.close()
            break

        self.success = True
        if auto_close:
            self.client.close()

        return (output, err)

    def setCommand(self, cmd):
        self.cmd = cmd

    def runcmd(self, cmd):
        return self.execute(cmd, auto_close=True)

    def run(self):
        self.resultset = self.runcmd(self.cmd)