def SSHClient(host_tuple, cmdlist): """ Perform SSH client logic """ host, ip = host_tuple # Link-local IPv6 support if ip.startswith('fe80'): # Try to assume eth0 as the interface as a fallback ip = ip+'%'+args.interface if args.interface else ip+"%eth0" try: # Wait at most CONNECT_TIMEOUT seconds for asyncssh.connect() to return with (yield from wait_for(asyncssh.connect(ip, **_SSH_OPTS), CONNECT_TIMEOUT)) as conn: conn.usr = conn.get_extra_info("username") log.warning('[%s:%s] SSH connection initiated', host, conn.usr) for cmd in cmdlist: conn.cmd = cmd.strip() try: # Initiate command execution session = SSHClientSession # Wait at most SESSION_TIMEOUT seconds for session to complete chan, session = yield from wait_for( conn.create_session(session, conn.cmd), SESSION_TIMEOUT) yield from wait_for(chan.wait_closed(), SESSION_TIMEOUT) except AIOTimeout: session.error = "Timeout" finally: if session.error: log.critical('[%s:%s] %s (%s)', host, conn.usr, conn.cmd, session.error) log.critical('[%s:%s] Failure detected, breaking...', host, conn.usr) sessionfailures[host] = (cmd, session.error) break # pylint: disable=lost-exception except (OSError, asyncssh.Error, AIOTimeout) as e: log.error('[%s] SSH connection failed: %s', host, repr(e)) connectfailures[host] = repr(e)
finally: _end = loop.time() log.debug(_delimiter*40) _fail_count = 0 for _host_tuple in _hosts: _host = _host_tuple[0] if _host in sessionfailures or _host in connectfailures: _fail_count += 1 log.info('Successfully ran on %d hosts in %.03fs', (_host_count-_fail_count), (_end-_start)) if sessionfailures or connectfailures: # Only report unique failures (_hosts set iterable) for _host_tuple in sorted(_hosts): _host = _host_tuple[0] if _host in sessionfailures: log.warning('%s command failed: %s (%s)', _host, sessionfailures[_host][_CMD], sessionfailures[_host][_STATUS]) if _host in connectfailures: log.warning('%s connection failed: %s', _host, connectfailures[_host]) else: log.info('No errors reported.') log.debug(_delimiter*40) log.info('Saved output script to %s', args.output) output.close() log_queue.stop()