def test_authentication_exception(self): """Test that we get authentication exception in output with correct arguments""" self.server.kill() _socket = make_socket(self.host) port = _socket.getsockname()[1] server = start_server(_socket, fail_auth=True) hosts = [self.host] client = ParallelSSHClient(hosts, port=port, pkey=self.user_key, agent=self.agent) output = client.run_command(self.fake_cmd, stop_on_errors=False) client.pool.join() self.assertTrue( 'exception' in output[self.host], msg="Got no exception for host %s - expected connection error" % (self.host, )) try: raise output[self.host]['exception'] except AuthenticationException, ex: self.assertEqual( ex.args[1], self.host, msg="Exception host argument is %s, should be %s" % ( ex.args[1], self.host, )) self.assertEqual( ex.args[2], port, msg="Exception port argument is %s, should be %s" % ( ex.args[2], port, ))
def test_pssh_client_exec_command_get_buffers(self): server = start_server({self.fake_cmd: self.fake_resp}, self.listen_socket) client = ParallelSSHClient(['127.0.0.1'], port=self.listen_port, pkey=self.user_key) cmd = client.exec_command(self.fake_cmd)[0] output = client.get_stdout(cmd, return_buffers=True) expected_exit_code = 0 expected_stdout = [self.fake_resp] expected_stderr = [] exit_code = output['127.0.0.1']['exit_code'] stdout = list(output['127.0.0.1']['stdout']) stderr = list(output['127.0.0.1']['stderr']) self.assertEqual(expected_exit_code, exit_code, msg="Got unexpected exit code - %s, expected %s" % ( exit_code, expected_exit_code, )) self.assertEqual(expected_stdout, stdout, msg="Got unexpected stdout - %s, expected %s" % ( stdout, expected_stdout, )) self.assertEqual(expected_stderr, stderr, msg="Got unexpected stderr - %s, expected %s" % ( stderr, expected_stderr, )) del client server.join()
def test_pssh_hosts_more_than_pool_size(self): """Test we can successfully run on more hosts than our pool size and get logs for all hosts""" # Make a second server on the same port as the first one server2_socket = make_socket('127.0.0.2', port=self.listen_port) server2_port = server2_socket.getsockname()[1] server2 = start_server(server2_socket) hosts = [self.host, '127.0.0.2'] client = ParallelSSHClient( hosts, port=self.listen_port, pkey=self.user_key, pool_size=1, ) output = client.run_command(self.fake_cmd) stdout = [list(output[k]['stdout']) for k in output] expected_stdout = [[self.fake_resp], [self.fake_resp]] self.assertEqual( len(hosts), len(output), msg="Did not get output from all hosts. Got output for \ %s/%s hosts" % ( len(output), len(hosts), )) self.assertEqual(expected_stdout, stdout, msg="Did not get expected output from all hosts. \ Got %s - expected %s" % ( stdout, expected_stdout, )) del client del server2
def test_pssh_client_exec_command_get_buffers(self): client = ParallelSSHClient([self.host], port=self.listen_port, pkey=self.user_key, agent=self.agent) cmd = client.exec_command(self.fake_cmd)[0] output = client.get_stdout(cmd, return_buffers=True) expected_exit_code = 0 expected_stdout = [self.fake_resp] expected_stderr = [] exit_code = output[self.host]['exit_code'] stdout = list(output[self.host]['stdout']) stderr = list(output[self.host]['stderr']) self.assertEqual(expected_exit_code, exit_code, msg="Got unexpected exit code - %s, expected %s" % ( exit_code, expected_exit_code, )) self.assertEqual(expected_stdout, stdout, msg="Got unexpected stdout - %s, expected %s" % ( stdout, expected_stdout, )) self.assertEqual(expected_stderr, stderr, msg="Got unexpected stderr - %s, expected %s" % ( stderr, expected_stderr, ))
def test_pssh_client_directory(self): """Tests copying multiple directories with SSH client. Copy all the files from local directory to server, then make sure they are all present.""" test_file_data = 'test' local_test_path = 'directory_test' remote_test_path = 'directory_test_copied' for path in [local_test_path, remote_test_path]: try: shutil.rmtree(path) except OSError: pass os.mkdir(local_test_path) remote_file_paths = [] for i in range(0, 10): local_file_path_dir = os.path.join(local_test_path, 'dir_foo' + str(i)) os.mkdir(local_file_path_dir) local_file_path = os.path.join(local_file_path_dir, 'foo' + str(i)) remote_file_path = os.path.join(remote_test_path, 'dir_foo' + str(i), 'foo' + str(i)) remote_file_paths.append(remote_file_path) test_file = open(local_file_path, 'w') test_file.write(test_file_data) test_file.close() client = ParallelSSHClient([self.host], port=self.listen_port, pkey=self.user_key) cmds = client.copy_file(local_test_path, remote_test_path, recurse=True) for cmd in cmds: cmd.get() for path in remote_file_paths: self.assertTrue(os.path.isfile(path)) shutil.rmtree(local_test_path) shutil.rmtree(remote_test_path)
def test_pssh_client_run_command_get_output_explicit(self): client = ParallelSSHClient([self.host], port=self.listen_port, pkey=self.user_key) out = client.run_command(self.fake_cmd) cmds = [cmd for host in out for cmd in [out[host]['cmd']]] output = {} for cmd in cmds: client.get_output(cmd, output) expected_exit_code = 0 expected_stdout = [self.fake_resp] expected_stderr = [] stdout = list(output[self.host]['stdout']) stderr = list(output[self.host]['stderr']) exit_code = output[self.host]['exit_code'] self.assertEqual(expected_exit_code, exit_code, msg="Got unexpected exit code - %s, expected %s" % (exit_code, expected_exit_code,)) self.assertEqual(expected_stdout, stdout, msg="Got unexpected stdout - %s, expected %s" % (stdout, expected_stdout,)) self.assertEqual(expected_stderr, stderr, msg="Got unexpected stderr - %s, expected %s" % (stderr, expected_stderr,)) del client
def test_ssh_exception(self): """Test that we get ssh exception in output with correct arguments""" host = '127.0.0.10' server, port = start_server_from_ip(host, ssh_exception=True) hosts = [host] client = ParallelSSHClient(hosts, port=port, user='******', password='******', pkey=RSAKey.generate(1024), num_retries=1) output = client.run_command(self.fake_cmd, stop_on_errors=False) client.pool.join() self.assertTrue('exception' in output[host], msg="Got no exception for host %s - expected connection error" % ( host,)) try: raise output[host]['exception'] except SSHException as ex: self.assertEqual(ex.args[1], host, msg="Exception host argument is %s, should be %s" % ( ex.args[1], host,)) self.assertEqual(ex.args[2], port, msg="Exception port argument is %s, should be %s" % ( ex.args[2], port,)) else: raise Exception("Expected SSHException") server.kill()
def test_pssh_client_run_command_get_output_explicit(self): server = start_server({self.fake_cmd: self.fake_resp}, self.listen_socket) client = ParallelSSHClient(['127.0.0.1'], port=self.listen_port, pkey=self.user_key) out = client.run_command(self.fake_cmd) cmds = [cmd for host in out for cmd in [out[host]['cmd']]] output = client.get_output(commands=cmds) expected_exit_code = 0 expected_stdout = [self.fake_resp] expected_stderr = [] exit_code = output['127.0.0.1']['exit_code'] stdout = list(output['127.0.0.1']['stdout']) stderr = list(output['127.0.0.1']['stderr']) self.assertEqual(expected_exit_code, exit_code, msg="Got unexpected exit code - %s, expected %s" % ( exit_code, expected_exit_code, )) self.assertEqual(expected_stdout, stdout, msg="Got unexpected stdout - %s, expected %s" % ( stdout, expected_stdout, )) self.assertEqual(expected_stderr, stderr, msg="Got unexpected stderr - %s, expected %s" % ( stderr, expected_stderr, )) del client server.join()
def test_pssh_client_timeout(self): listen_socket = make_socket(self.host) listen_port = listen_socket.getsockname()[1] server_timeout=0.2 client_timeout=server_timeout-0.1 server = start_server(listen_socket, timeout=server_timeout) client = ParallelSSHClient([self.host], port=listen_port, pkey=self.user_key, timeout=client_timeout) output = client.run_command(self.fake_cmd) # Handle exception try: gevent.sleep(server_timeout+0.2) client.pool.join() if not server.exception: raise Exception( "Expected gevent.Timeout from socket timeout, got none") raise server.exception except gevent.Timeout: pass # chan_timeout = output[self.host]['channel'].gettimeout() # self.assertEqual(client_timeout, chan_timeout, # msg="Channel timeout %s does not match requested timeout %s" %( # chan_timeout, client_timeout,)) del client server.join()
def test_ssh_proxy_auth(self): """Test connecting to remote destination via SSH proxy client -> proxy -> destination Proxy SSH server accepts no commands and sends no responses, only proxies to destination. Destination accepts a command as usual.""" host2 = '127.0.0.2' proxy_server, proxy_server_port = start_server_from_ip(host2) proxy_user = '******' proxy_password = '******' client = ParallelSSHClient([self.host], port=self.listen_port, pkey=self.user_key, proxy_host=host2, proxy_port=proxy_server_port, proxy_user=proxy_user, proxy_password='******', proxy_pkey=self.user_key, num_retries=1, ) expected_stdout = [self.fake_resp] try: output = client.run_command(self.fake_cmd) stdout = list(output[self.host]['stdout']) self.assertEqual(expected_stdout, stdout, msg="Got unexpected stdout - %s, expected %s" % ( stdout, expected_stdout,)) self.assertEqual(client.host_clients[self.host].proxy_user, proxy_user) self.assertEqual(client.host_clients[self.host].proxy_password, proxy_password) self.assertTrue(client.host_clients[self.host].proxy_pkey) finally: del client proxy_server.kill()
def test_pssh_hosts_iterator_hosts_modification(self): """Test using iterator as host list and modifying host list in place""" server2_socket = make_socket("127.0.0.2", port=self.listen_port) server2_port = server2_socket.getsockname()[1] server2 = start_server(server2_socket) server3_socket = make_socket("127.0.0.3", port=self.listen_port) server3_port = server3_socket.getsockname()[1] server3 = start_server(server3_socket) hosts = [self.host, "127.0.0.2"] client = ParallelSSHClient(iter(hosts), port=self.listen_port, pkey=self.user_key, pool_size=1) output = client.run_command(self.fake_cmd) stdout = [list(output[k]["stdout"]) for k in output] expected_stdout = [[self.fake_resp], [self.fake_resp]] self.assertEqual( len(hosts), len(output), msg="Did not get output from all hosts. Got output for " "%s/%s hosts" % (len(output), len(hosts)), ) # Run again without re-assigning host list, should do nothing output = client.run_command(self.fake_cmd) self.assertFalse(hosts[0] in output, msg="Expected no host output, got %s" % (output,)) self.assertFalse(output, msg="Expected empty output, got %s" % (output,)) # Re-assigning host list with new hosts should work hosts = ["127.0.0.2", "127.0.0.3"] client.hosts = iter(hosts) output = client.run_command(self.fake_cmd) self.assertEqual( len(hosts), len(output), msg="Did not get output from all hosts. Got output for " "%s/%s hosts" % (len(output), len(hosts)), ) self.assertTrue(hosts[1] in output, msg="Did not get output for new host %s" % (hosts[1],)) del client, server2, server3
def test_pssh_client_run_command_get_output_explicit(self): server = start_server({ self.fake_cmd : self.fake_resp }, self.listen_socket) client = ParallelSSHClient(['127.0.0.1'], port=self.listen_port, pkey=self.user_key) out = client.run_command(self.fake_cmd) cmds = [cmd for host in out for cmd in [out[host]['cmd']]] output = client.get_output(commands=cmds) expected_exit_code = 0 expected_stdout = [self.fake_resp] expected_stderr = [] exit_code = output['127.0.0.1']['exit_code'] stdout = list(output['127.0.0.1']['stdout']) stderr = list(output['127.0.0.1']['stderr']) self.assertEqual(expected_exit_code, exit_code, msg="Got unexpected exit code - %s, expected %s" % (exit_code, expected_exit_code,)) self.assertEqual(expected_stdout, stdout, msg="Got unexpected stdout - %s, expected %s" % (stdout, expected_stdout,)) self.assertEqual(expected_stderr, stderr, msg="Got unexpected stderr - %s, expected %s" % (stderr, expected_stderr,)) del client server.join()
def test_pssh_client_exec_command_get_buffers(self): server = start_server({ self.fake_cmd : self.fake_resp }, self.listen_socket) client = ParallelSSHClient(['127.0.0.1'], port=self.listen_port, pkey=self.user_key) cmd = client.exec_command(self.fake_cmd)[0] output = client.get_stdout(cmd, return_buffers=True) expected_exit_code = 0 expected_stdout = [self.fake_resp] expected_stderr = [] exit_code = output['127.0.0.1']['exit_code'] stdout = list(output['127.0.0.1']['stdout']) stderr = list(output['127.0.0.1']['stderr']) self.assertEqual(expected_exit_code, exit_code, msg = "Got unexpected exit code - %s, expected %s" % (exit_code, expected_exit_code,)) self.assertEqual(expected_stdout, stdout, msg = "Got unexpected stdout - %s, expected %s" % (stdout, expected_stdout,)) self.assertEqual(expected_stderr, stderr, msg = "Got unexpected stderr - %s, expected %s" % (stderr, expected_stderr,)) del client server.join()
def test_pssh_client_timeout(self): server_timeout = 0.2 client_timeout = server_timeout - 0.1 server = start_server({self.fake_cmd: self.fake_resp}, self.listen_socket, timeout=server_timeout) client = ParallelSSHClient(['127.0.0.1'], port=self.listen_port, pkey=self.user_key, timeout=client_timeout) output = client.run_command(self.fake_cmd) # Handle exception try: gevent.sleep(server_timeout + 0.2) client.pool.join() if not server.exception: raise Exception( "Expected gevent.Timeout from socket timeout, got none") raise server.exception except gevent.Timeout: pass chan_timeout = output['127.0.0.1']['channel'].gettimeout() self.assertEqual( client_timeout, chan_timeout, msg="Channel timeout %s does not match requested timeout %s" % ( chan_timeout, client_timeout, )) del client server.join()
def main(argv): hosts = [] cmd = '' try: opts, args = getopt.getopt(argv, "ht:c:", ["targets=", "cmd="]) except getopt.GetoptError: print 'parallel-ssh-tauros.py -t <ipsfile> -c <cmd>' sys.exit(2) for opt, arg in opts: if opt == '-h': print 'parallel-ssh-tauros.py -t <ipsfile> -c <cmd>' sys.exit() elif opt in ("-t", "--targets"): filename = arg with open(filename, "r") as ips: for ip in ips: hosts.append(ip.strip()) elif opt in ("-c", "--cmd"): cmd = arg print '==== Targets detected: ', len(hosts) print '==== Cmd: ', cmd password = open("password").readline().strip() client = ParallelSSHClient(hosts, user='******', password=password) output = client.run_command(cmd) for host in output: for line in output[host]['stdout']: print("=> Host %s - output: %s" % (host, line))
def test_pssh_pool_size(self): """Test setting pool size to non default values""" hosts = ['host-%01d' % d for d in xrange(5)] pool_size = 2 client = ParallelSSHClient(hosts, pool_size=pool_size) expected, actual = pool_size, client.pool.size self.assertEqual(expected, actual, msg="Expected pool size to be %s, got %s" % ( expected, actual, )) hosts = ['host-%01d' % d for d in xrange(15)] pool_size = 5 client = ParallelSSHClient(hosts, pool_size=pool_size) expected, actual = client.pool_size, client.pool.size self.assertEqual(expected, actual, msg="Expected pool size to be %s, got %s" % ( expected, actual, )) hosts = ['host-%01d' % d for d in xrange(15)] pool_size = len(hosts) + 5 client = ParallelSSHClient(hosts, pool_size=pool_size) expected, actual = pool_size, client.pool.size self.assertEqual(expected, actual, msg="Expected pool size to be %s, got %s" % ( expected, actual, ))
def test_ssh_proxy(self): """Test connecting to remote destination via SSH proxy client -> proxy -> destination Proxy SSH server accepts no commands and sends no responses, only proxies to destination. Destination accepts a command as usual.""" proxy_server_socket = make_socket('127.0.0.1') proxy_server_port = proxy_server_socket.getsockname()[1] proxy_server = start_server({}, proxy_server_socket) server = start_server({self.fake_cmd: self.fake_resp}, self.listen_socket) client = ParallelSSHClient(['127.0.0.1'], port=self.listen_port, pkey=self.user_key, proxy_host='127.0.0.1', proxy_port=proxy_server_port) output = client.run_command(self.fake_cmd) stdout = list(output['127.0.0.1']['stdout']) expected_stdout = [self.fake_resp] self.assertEqual(expected_stdout, stdout, msg="Got unexpected stdout - %s, expected %s" % ( stdout, expected_stdout, )) server.kill() proxy_server.kill()
def test_pssh_client_override_allow_agent_authentication(self): """Test running command with allow_agent set to False""" client = ParallelSSHClient([self.host], port=self.listen_port, pkey=self.user_key, allow_agent=False) output = client.run_command(self.fake_cmd) expected_exit_code = 0 expected_stdout = [self.fake_resp] expected_stderr = [] stdout = list(output[self.host]['stdout']) stderr = list(output[self.host]['stderr']) exit_code = output[self.host]['exit_code'] self.assertEqual(expected_exit_code, exit_code, msg="Got unexpected exit code - %s, expected %s" % (exit_code, expected_exit_code,)) self.assertEqual(expected_stdout, stdout, msg="Got unexpected stdout - %s, expected %s" % (stdout, expected_stdout,)) self.assertEqual(expected_stderr, stderr, msg="Got unexpected stderr - %s, expected %s" % (stderr, expected_stderr,)) del client
def test_pssh_client_timeout(self): server_timeout=0.2 client_timeout=server_timeout-0.1 server = start_server({ self.fake_cmd : self.fake_resp }, self.listen_socket, timeout=server_timeout) client = ParallelSSHClient(['127.0.0.1'], port=self.listen_port, pkey=self.user_key, timeout=client_timeout) output = client.run_command(self.fake_cmd) # Handle exception try: gevent.sleep(server_timeout+0.2) client.pool.join() if not server.exception: raise Exception( "Expected gevent.Timeout from socket timeout, got none") raise server.exception except gevent.Timeout: pass chan_timeout = output['127.0.0.1']['channel'].gettimeout() self.assertEqual(client_timeout, chan_timeout, msg="Channel timeout %s does not match requested timeout %s" %( chan_timeout, client_timeout,)) del client server.join()
def test_host_config(self): """Test per-host configuration functionality of ParallelSSHClient""" hosts = ['127.0.0.%01d' % n for n in xrange(1,3)] host_config = dict.fromkeys(hosts) servers = [] user = '******' password = '******' for host in hosts: _socket = make_socket(host) port = _socket.getsockname()[1] host_config[host] = {} host_config[host]['port'] = port host_config[host]['user'] = user host_config[host]['password'] = password server = start_server(_socket, fail_auth=hosts.index(host)) servers.append((server, port)) pkey_data = load_private_key(PKEY_FILENAME) host_config[hosts[0]]['private_key'] = pkey_data client = ParallelSSHClient(hosts, host_config=host_config) output = client.run_command(self.fake_cmd, stop_on_errors=False) client.join(output) for host in hosts: self.assertTrue(host in output) try: raise output[hosts[1]]['exception'] except AuthenticationException, ex: pass
def test_pssh_hosts_more_than_pool_size(self): """Test we can successfully run on more hosts than our pool size and get logs for all hosts""" # Make a second server on the same port as the first one server2_socket = make_socket('127.0.0.2', port=self.listen_port) server2_port = server2_socket.getsockname()[1] server1 = start_server({ self.fake_cmd : self.fake_resp }, self.listen_socket) server2 = start_server({ self.fake_cmd : self.fake_resp }, server2_socket) hosts = ['127.0.0.1', '127.0.0.2'] client = ParallelSSHClient(hosts, port=self.listen_port, pkey=self.user_key, pool_size=1, ) output = client.run_command(self.fake_cmd) stdout = [list(output[k]['stdout']) for k in output] expected_stdout = [[self.fake_resp], [self.fake_resp]] self.assertEqual(len(hosts), len(output), msg="Did not get output from all hosts. Got output for \ %s/%s hosts" % (len(output), len(hosts),)) self.assertEqual(expected_stdout, stdout, msg="Did not get expected output from all hosts. \ Got %s - expected %s" % (stdout, expected_stdout,)) del client server1.kill() server2.kill()
def test_ssh_proxy(self): """Test connecting to remote destination via SSH proxy client -> proxy -> destination Proxy SSH server accepts no commands and sends no responses, only proxies to destination. Destination accepts a command as usual.""" del self.client self.client = None self.server.kill() server, _ = start_server_from_ip(self.host, port=self.listen_port) proxy_host = '127.0.0.2' proxy_server, proxy_server_port = start_server_from_ip(proxy_host) client = ParallelSSHClient([self.host], port=self.listen_port, pkey=self.user_key, proxy_host=proxy_host, proxy_port=proxy_server_port, ) try: output = client.run_command(self.fake_cmd) stdout = list(output[self.host]['stdout']) expected_stdout = [self.fake_resp] self.assertEqual(expected_stdout, stdout, msg="Got unexpected stdout - %s, expected %s" % (stdout, expected_stdout,)) finally: del client server.kill() proxy_server.kill()
def test_ssh_exception(self): """Test that we get ssh exception in output with correct arguments""" self.server.kill() host = '127.0.0.10' _socket = make_socket(host) port = _socket.getsockname()[1] server = start_server(_socket, ssh_exception=True) hosts = [host] client = ParallelSSHClient(hosts, port=port, user='******', password='******', pkey=paramiko.RSAKey.generate(1024)) output = client.run_command(self.fake_cmd, stop_on_errors=False) gevent.sleep(.2) client.pool.join() self.assertTrue('exception' in output[host], msg="Got no exception for host %s - expected connection error" % ( host,)) try: raise output[host]['exception'] except SSHException, ex: self.assertEqual(ex.args[1], host, msg="Exception host argument is %s, should be %s" % ( ex.args[1], host,)) self.assertEqual(ex.args[2], port, msg="Exception port argument is %s, should be %s" % ( ex.args[2], port,))
def test_connection_error_exception(self): """Test that we get connection error exception in output with correct arguments""" # Make port with no server listening on it on separate ip host = '127.0.0.3' port = self.make_random_port(host=host) hosts = [host] client = ParallelSSHClient(hosts, port=port, pkey=self.user_key, num_retries=1) output = client.run_command(self.fake_cmd, stop_on_errors=False) client.pool.join() self.assertTrue('exception' in output[host], msg="Got no exception for host %s - expected connection error" % ( host,)) try: raise output[host]['exception'] except ConnectionErrorException as ex: self.assertEqual(ex.args[1], host, msg="Exception host argument is %s, should be %s" % ( ex.args[1], host,)) self.assertEqual(ex.args[2], port, msg="Exception port argument is %s, should be %s" % ( ex.args[2], port,)) else: raise Exception("Expected ConnectionErrorException")
def test_pssh_pool_size(self): """Test pool size logic""" hosts = ['host-%01d' % d for d in xrange(5)] client = ParallelSSHClient(hosts) expected, actual = len(hosts), client.pool.size self.assertEqual(expected, actual, msg="Expected pool size to be %s, got %s" % ( expected, actual, )) hosts = ['host-%01d' % d for d in xrange(15)] client = ParallelSSHClient(hosts) expected, actual = client.pool_size, client.pool.size self.assertEqual(expected, actual, msg="Expected pool size to be %s, got %s" % ( expected, actual, )) hosts = ['host-%01d' % d for d in xrange(15)] client = ParallelSSHClient(hosts, pool_size=len(hosts) + 5) expected, actual = len(hosts), client.pool.size self.assertEqual(expected, actual, msg="Expected pool size to be %s, got %s" % ( expected, actual, ))
def test_per_host_tuple_args(self): host2, host3 = '127.0.0.2', '127.0.0.3' server2, _ = start_server_from_ip(host2, port=self.listen_port) server3, _ = start_server_from_ip(host3, port=self.listen_port) hosts = [self.host, host2, host3] host_args = ('arg1', 'arg2', 'arg3') cmd = 'echo %s' client = ParallelSSHClient(hosts, port=self.listen_port, pkey=self.user_key, num_retries=1) output = client.run_command(cmd, host_args=host_args) for i, host in enumerate(hosts): expected = [host_args[i]] stdout = list(output[host]['stdout']) self.assertEqual(expected, stdout) self.assertTrue(output[host]['exit_code'] == 0) host_args = (('arg1', 'arg2'), ('arg3', 'arg4'), ('arg5', 'arg6'),) cmd = 'echo %s %s' output = client.run_command(cmd, host_args=host_args) for i, host in enumerate(hosts): expected = ["%s %s" % host_args[i]] stdout = list(output[host]['stdout']) self.assertEqual(expected, stdout) self.assertTrue(output[host]['exit_code'] == 0) self.assertRaises(HostArgumentException, client.run_command, cmd, host_args=[host_args[0]]) # Invalid number of args host_args = (('arg1', ),) self.assertRaises( TypeError, client.run_command, cmd, host_args=host_args) for server in [server2, server3]: server.kill()
def test_ssh_proxy_auth(self): """Test connecting to remote destination via SSH proxy client -> proxy -> destination Proxy SSH server accepts no commands and sends no responses, only proxies to destination. Destination accepts a command as usual.""" proxy_server_socket = make_socket('127.0.0.2') proxy_server_port = proxy_server_socket.getsockname()[1] proxy_server = start_server(proxy_server_socket) proxy_user = '******' proxy_password = '******' gevent.sleep(2) client = ParallelSSHClient([self.host], port=self.listen_port, pkey=self.user_key, proxy_host='127.0.0.2', proxy_port=proxy_server_port, proxy_user=proxy_user, proxy_password='******', proxy_pkey=self.user_key, ) gevent.sleep(2) output = client.run_command(self.fake_cmd) stdout = list(output[self.host]['stdout']) expected_stdout = [self.fake_resp] self.assertEqual(expected_stdout, stdout, msg="Got unexpected stdout - %s, expected %s" % ( stdout, expected_stdout,)) self.assertEqual(client.host_clients[self.host].proxy_user, proxy_user) self.assertEqual(client.host_clients[self.host].proxy_password, proxy_password) self.assertTrue(client.host_clients[self.host].proxy_pkey) self.server.kill() proxy_server.kill()
def test_pssh_client_hosts_list_part_failure(self): """Test getting output for remainder of host list in the case where one host in the host list has a failure""" server2_socket = make_socket('127.0.0.2', port=self.listen_port) server2_port = server2_socket.getsockname()[1] server2 = start_server(server2_socket, fail_auth=True) hosts = [self.host, '127.0.0.2'] client = ParallelSSHClient(hosts, port=self.listen_port, pkey=self.user_key, agent=self.agent) output = client.run_command(self.fake_cmd, stop_on_errors=False) client.join(output) self.assertTrue(hosts[0] in output, msg="Successful host does not exist in output - output is %s" % (output,)) self.assertTrue(hosts[1] in output, msg="Failed host does not exist in output - output is %s" % (output,)) self.assertTrue('exception' in output[hosts[1]], msg="Failed host %s has no exception in output - %s" % (hosts[1], output,)) try: raise output[hosts[1]]['exception'] except AuthenticationException: pass else: raise Exception("Expected AuthenticationException, got %s instead" % ( output[hosts[1]]['exception'],)) del client server2.kill()
def post(self): raw_dict = request.get_json(force=True) try: schema.validate(raw_dict) request_dict = raw_dict['data']['attributes'] ipaddress = request_dict['ipaddress'] username = request_dict['username'] password = request_dict['password'] #s = pxssh.pxssh() #s.login(ipaddress, username, password,port=2222,auto_prompt_reset=False) hosts = [ipaddress] client = ParallelSSHClient(hosts, user=username, password=password, port=2222) output= client.run_command("grep ':0' /etc/passwd | grep '/bin/bash' | awk -F: '{print $1}'") users = [] for host in output: for user in output[host]['stdout']: users.append(user) data = {'users': users} del output return data, 201 except ValidationError as err: resp = jsonify({"error": err.messages}) resp.status_code = 403 return resp
def test_per_host_tuple_args(self): server2_socket = make_socket('127.0.0.2', port=self.listen_port) server2_port = server2_socket.getsockname()[1] server2 = start_server(server2_socket) server3_socket = make_socket('127.0.0.3', port=self.listen_port) server3_port = server3_socket.getsockname()[1] server3 = start_server(server3_socket) hosts = [self.host, '127.0.0.2', '127.0.0.3'] host_args = ('arg1', 'arg2', 'arg3') cmd = 'echo %s' client = ParallelSSHClient(hosts, port=self.listen_port, pkey=self.user_key) output = client.run_command(cmd, host_args=host_args) for i, host in enumerate(hosts): expected = [host_args[i]] stdout = list(output[host]['stdout']) self.assertEqual(expected, stdout) self.assertTrue(output[host]['exit_code'] == 0) host_args = (('arg1', 'arg2'), ('arg3', 'arg4'), ('arg5', 'arg6'),) cmd = 'echo %s %s' output = client.run_command(cmd, host_args=host_args) for i, host in enumerate(hosts): expected = ["%s %s" % host_args[i]] stdout = list(output[host]['stdout']) self.assertEqual(expected, stdout) self.assertTrue(output[host]['exit_code'] == 0) self.assertRaises(HostArgumentException, client.run_command, cmd, host_args=[host_args[0]])
def test_pssh_client_timeout(self): listen_socket = make_socket(self.host) listen_port = listen_socket.getsockname()[1] server_timeout=0.2 client_timeout=server_timeout-0.1 server = start_server(listen_socket, timeout=server_timeout) client = ParallelSSHClient([self.host], port=listen_port, pkey=self.user_key, timeout=client_timeout) output = client.run_command(self.fake_cmd) # Handle exception try: gevent.sleep(server_timeout+0.2) client.pool.join() if not server.exception: raise Exception( "Expected gevent.Timeout from socket timeout, got none") raise server.exception except gevent.Timeout: pass # chan_timeout = output[self.host]['channel'].gettimeout() # self.assertEqual(client_timeout, chan_timeout, # msg="Channel timeout %s does not match requested timeout %s" %( # chan_timeout, client_timeout,)) del client server.kill()
def test_per_host_dict_args(self): server2_socket = make_socket('127.0.0.2', port=self.listen_port) server2_port = server2_socket.getsockname()[1] server2 = start_server(server2_socket) server3_socket = make_socket('127.0.0.3', port=self.listen_port) server3_port = server3_socket.getsockname()[1] server3 = start_server(server3_socket) hosts = [self.host, '127.0.0.2', '127.0.0.3'] hosts_gen = (h for h in hosts) host_args = [dict(zip(('host_arg1', 'host_arg2',), ('arg1-%s' % (i,), 'arg2-%s' % (i,),))) for i, _ in enumerate(hosts)] cmd = 'echo %(host_arg1)s %(host_arg2)s' client = ParallelSSHClient(hosts, port=self.listen_port, pkey=self.user_key) output = client.run_command(cmd, host_args=host_args) for i, host in enumerate(hosts): expected = ["%(host_arg1)s %(host_arg2)s" % host_args[i]] stdout = list(output[host]['stdout']) self.assertEqual(expected, stdout) self.assertTrue(output[host]['exit_code'] == 0) self.assertRaises(HostArgumentException, client.run_command, cmd, host_args=[host_args[0]]) # Host list generator should work also client.hosts = hosts_gen output = client.run_command(cmd, host_args=host_args) for i, host in enumerate(hosts): expected = ["%(host_arg1)s %(host_arg2)s" % host_args[i]] stdout = list(output[host]['stdout']) self.assertEqual(expected, stdout) self.assertTrue(output[host]['exit_code'] == 0) client.hosts = (h for h in hosts) self.assertRaises(HostArgumentException, client.run_command, cmd, host_args=[host_args[0]])
def test_pssh_client_directory(self): """Tests copying directories with SSH client. Copy all the files from local directory to server, then make sure they are all present.""" test_file_data = 'test' local_test_path = 'directory_test' remote_test_path = 'directory_test_copied' for path in [local_test_path, remote_test_path]: try: shutil.rmtree(path) except OSError: pass os.mkdir(local_test_path) remote_file_paths = [] for i in range(0, 10): local_file_path = os.path.join(local_test_path, 'foo' + str(i)) remote_file_path = os.path.join(remote_test_path, 'foo' + str(i)) remote_file_paths.append(remote_file_path) test_file = open(local_file_path, 'w') test_file.write(test_file_data) test_file.close() client = ParallelSSHClient([self.host], port=self.listen_port, pkey=self.user_key) cmds = client.copy_file(local_test_path, remote_test_path, recurse=True) for cmd in cmds: cmd.get() for path in remote_file_paths: self.assertTrue(os.path.isfile(path)) shutil.rmtree(local_test_path) shutil.rmtree(remote_test_path)
def test_ssh_exception(self): """Test that we get ssh exception in output with correct arguments""" self.server.kill() host = '127.0.0.10' _socket = make_socket(host) port = _socket.getsockname()[1] server = start_server(_socket, ssh_exception=True) hosts = [host] client = ParallelSSHClient(hosts, port=port, user='******', password='******', pkey=paramiko.RSAKey.generate(1024)) output = client.run_command(self.fake_cmd, stop_on_errors=False) gevent.sleep(1) client.pool.join() self.assertTrue('exception' in output[host], msg="Got no exception for host %s - expected connection error" % ( host,)) try: raise output[host]['exception'] except SSHException, ex: self.assertEqual(ex.args[1], host, msg="Exception host argument is %s, should be %s" % ( ex.args[1], host,)) self.assertEqual(ex.args[2], port, msg="Exception port argument is %s, should be %s" % ( ex.args[2], port,))
def test_connection_error_exception(self): """Test that we get connection error exception in output with correct arguments""" self.server.kill() # Make socket with no server listening on it on separate ip host = '127.0.0.3' _socket = make_socket(host) port = _socket.getsockname()[1] hosts = [host] client = ParallelSSHClient(hosts, port=port, pkey=self.user_key) output = client.run_command(self.fake_cmd, stop_on_errors=False) client.pool.join() self.assertTrue( 'exception' in output[host], msg="Got no exception for host %s - expected connection error" % (host, )) try: raise output[host]['exception'] except ConnectionErrorException, ex: self.assertEqual( ex.args[1], host, msg="Exception host argument is %s, should be %s" % ( ex.args[1], host, )) self.assertEqual( ex.args[2], port, msg="Exception port argument is %s, should be %s" % ( ex.args[2], port, ))
def test_parallel(): """Perform ls and copy file with ParallelSSHClient on localhost""" client = ParallelSSHClient(['localhost']) cmds = client.exec_command('ls -ltrh') output = [client.get_stdout(cmd, return_buffers=True) for cmd in cmds] print output cmds = client.copy_file('../test', 'test_dir/test') client.pool.join()
def __init__(self, hosts, args): self.hosts = hosts self.client = ParallelSSHClient(hosts, user=args['VM_LOGIN_USER']) self.ROOT_DIR = args['MULTIVM_ROOT_DIR'] self.AIO_MODE = args['AIO_MODE'] self.SCRIPT_NAMES = '{%s}' % ','.join(args['SCRIPT_NAMES']) self.UTIL_NAMES = '{%s}' % ','.join(args['UTIL_NAMES']) self.FILENAMES = ','.join(args['SCRIPT_NAMES'] + args['UTIL_NAMES'])
def test_sftp_exceptions(self): # Port with no server listening on it on separate ip host = '127.0.0.3' port = self.make_random_port(host=host) client = ParallelSSHClient([self.host], port=port, num_retries=1) cmds = client.copy_file("test", "test") client.pool.join() for cmd in cmds: self.assertRaises(ConnectionErrorException, cmd.get)
def test_pssh_copy_remote_file(self): """Test parallel copy file to local host""" test_file_data = 'test' local_test_path = 'directory_test_local_remote_copied' remote_test_path = 'directory_test_remote_copy' local_copied_dir = '_'.join([local_test_path, self.host]) new_local_copied_dir = '.'.join([local_test_path, self.host]) for path in [local_test_path, remote_test_path, local_copied_dir, new_local_copied_dir]: try: shutil.rmtree(path) except OSError: try: os.unlink(path) except Exception: pass pass os.mkdir(remote_test_path) local_file_paths = [] for i in range(0, 10): remote_file_path_dir = os.path.join(remote_test_path, 'dir_foo' + str(i)) os.mkdir(remote_file_path_dir) remote_file_path = os.path.join(remote_file_path_dir, 'foo' + str(i)) local_file_path = os.path.join(local_copied_dir, 'dir_foo' + str(i), 'foo' + str(i)) local_file_paths.append(local_file_path) test_file = open(remote_file_path, 'w') test_file.write(test_file_data) test_file.close() client = ParallelSSHClient([self.host], port=self.listen_port, pkey=self.user_key) cmds = client.copy_remote_file(remote_test_path, local_test_path) for cmd in cmds: self.assertRaises(ValueError, cmd.get) cmds = client.copy_remote_file(remote_test_path, local_test_path, recurse=True) for cmd in cmds: cmd.get() try: self.assertTrue(os.path.isdir(local_copied_dir)) for path in local_file_paths: self.assertTrue(os.path.isfile(path)) except Exception: shutil.rmtree(remote_test_path) finally: shutil.rmtree(local_copied_dir) cmds = client.copy_remote_file(remote_test_path, local_test_path, suffix_separator='.', recurse=True) for cmd in cmds: cmd.get() new_local_copied_dir = '.'.join([local_test_path, self.host]) try: for path in local_file_paths: path = path.replace(local_copied_dir, new_local_copied_dir) self.assertTrue(os.path.isfile(path)) finally: shutil.rmtree(new_local_copied_dir) shutil.rmtree(remote_test_path)
def test_pssh_client_exec_command(self): client = ParallelSSHClient([self.host], port=self.listen_port, pkey=self.user_key) cmd = client.exec_command(self.fake_cmd)[0] output = client.get_stdout(cmd) expected = {self.host : {'exit_code' : 0}} self.assertEqual(expected, output, msg="Got unexpected command output - %s" % (output,)) self.assertTrue(output[self.host]['exit_code'] == 0)
def run_distributed4(script_name, arg_tuples): from pssh import ParallelSSHClient hostids = detect_responsive_nodes() hosts = ['gcn-20-%d.sdsc.edu' % i for i in hostids] client = ParallelSSHClient(hosts, timeout=5) output = client.run_command('hostname') for host in output: for line in output[host]['stdout']: print "Host %s - output: %s" % (host, line)
def test_pssh_client_run_long_command(self): expected_lines = 5 client = ParallelSSHClient([self.host], port=self.listen_port, pkey=self.user_key) output = client.run_command(self.long_cmd(expected_lines)) self.assertTrue(self.host in output, msg="Got no output for command") stdout = list(output[self.host]["stdout"]) self.assertTrue( len(stdout) == expected_lines, msg="Expected %s lines of response, got %s" % (expected_lines, len(stdout)) ) del client
def __init__(self, servers, cmd, asRoot=True, outputObservers=[]): Thread.__init__(self) if asRoot: self.client = ParallelSSHClient(servers, user="******") else: self.client = ParallelSSHClient(servers) self.cmd = cmd self.observers = outputObservers self.servers = servers self.asRoot = asRoot
def test_bash_variable_substitution(self): """Test bash variables work correctly""" client = ParallelSSHClient([self.host], port=self.listen_port, pkey=self.user_key) command = """for i in 1 2 3; do echo $i; done""" output = list(client.run_command(command)[self.host]['stdout']) expected = ['1','2','3'] self.assertEqual(output, expected, msg="Unexpected output from bash variable substitution %s - should be %s" % ( output, expected,))
def ssh(): client = ParallelSSHClient(hosts) output = client.run_command('ls -ltr /home/siraj', sudo=True) # print output for host in output: for line in output[host]['stdout']: print 'Host %s - output: %s' % (host, line) sys.stdout.flush()
def __init__(self, servers, cmd, asRoot = True, outputObservers=[]): Thread.__init__(self) if asRoot: self.client = ParallelSSHClient(servers, user="******") else: self.client = ParallelSSHClient(servers) self.cmd = cmd self.observers = outputObservers self.servers = servers self.asRoot = asRoot
def test_pssh_client_exec_command_password(self): """Test password authentication. Embedded server accepts any password even empty string""" client = ParallelSSHClient([self.host], port=self.listen_port, password="") cmd = client.exec_command(self.fake_cmd)[0] output = client.get_stdout(cmd) self.assertTrue(self.host in output, msg="No output for host") self.assertTrue( output[self.host]["exit_code"] == 0, msg="Expected exit code 0, got %s" % (output[self.host]["exit_code"],) ) del client
def test_pssh_client_exec_command(self): server = start_server({ self.fake_cmd : self.fake_resp }, self.listen_socket) client = ParallelSSHClient(['127.0.0.1'], port=self.listen_port, pkey=self.user_key) cmd = client.exec_command(self.fake_cmd)[0] output = client.get_stdout(cmd) expected = {'127.0.0.1' : {'exit_code' : 0}} self.assertEqual(expected, output, msg = "Got unexpected command output - %s" % (output,)) del client server.join()
def test_pssh_client_long_running_command(self): expected_lines = 5 client = ParallelSSHClient([self.host], port=self.listen_port, pkey=self.user_key) cmd = client.exec_command(self.long_cmd(expected_lines))[0] output = client.get_stdout(cmd, return_buffers=True) self.assertTrue(self.host in output, msg="Got no output for command") stdout = list(output[self.host]["stdout"]) self.assertTrue( len(stdout) == expected_lines, msg="Expected %s lines of response, got %s" % (expected_lines, len(stdout)) ) del client
def test_sftp_exceptions(self): self.server.kill() # Make socket with no server listening on it on separate ip host = '127.0.0.3' _socket = make_socket(host) port = _socket.getsockname()[1] client = ParallelSSHClient([self.host], port=port, num_retries=1) cmds = client.copy_file("test", "test") client.pool.join() for cmd in cmds: self.assertRaises(ConnectionErrorException, cmd.get)
def test_pssh_client_exec_command_password(self): """Test password authentication. Fake server accepts any password even empty string""" client = ParallelSSHClient([self.host], port=self.listen_port, password='') cmd = client.exec_command(self.fake_cmd)[0] output = client.get_stdout(cmd) expected = {self.host : {'exit_code' : 0}} self.assertEqual(expected, output, msg="Got unexpected command output - %s" % (output,)) del client
def test_pssh_client_no_stdout_non_zero_exit_code(self): client = ParallelSSHClient([self.host], port=self.listen_port, pkey=self.user_key) output = client.run_command('exit 1') expected_exit_code = 1 exit_code = output[self.host]['exit_code'] client.pool.join() self.assertEqual(expected_exit_code, exit_code, msg="Got unexpected exit code - %s, expected %s" % (exit_code, expected_exit_code,))
def test_pssh_client_copy_file_failure(self): """Test failure scenarios of file copy""" test_file_data = 'test' local_test_path = 'directory_test' remote_test_path = 'directory_test_copied' for path in [local_test_path, remote_test_path]: mask = int('0700') if sys.version_info <= (2,) else 0o700 if os.path.isdir(path): os.chmod(path, mask) for root, dirs, files in os.walk(path): os.chmod(root, mask) for _path in files + dirs: os.chmod(os.path.join(root, _path), mask) try: shutil.rmtree(path) except OSError: pass os.mkdir(local_test_path) os.mkdir(remote_test_path) local_file_path = os.path.join(local_test_path, 'test_file') remote_file_path = os.path.join(remote_test_path, 'test_file') test_file = open(local_file_path, 'w') test_file.write('testing\n') test_file.close() # Permission errors on writing into dir mask = 0111 if sys.version_info <= (2,) else 0o111 os.chmod(remote_test_path, mask) client = ParallelSSHClient([self.host], port=self.listen_port, pkey=self.user_key) cmds = client.copy_file(local_test_path, remote_test_path, recurse=True) for cmd in cmds: try: cmd.get() raise Exception("Expected IOError exception, got none") except IOError: pass self.assertFalse(os.path.isfile(remote_file_path)) # Create directory tree failure test local_file_path = os.path.join(local_test_path, 'test_file') remote_file_path = os.path.join(remote_test_path, 'test_dir', 'test_file') cmds = client.copy_file(local_file_path, remote_file_path, recurse=True) for cmd in cmds: try: cmd.get() raise Exception("Expected IOError exception on creating remote " "directory, got none") except IOError: pass self.assertFalse(os.path.isfile(remote_file_path)) mask = int('0600') if sys.version_info <= (2,) else 0o600 os.chmod(remote_test_path, mask) for path in [local_test_path, remote_test_path]: shutil.rmtree(path)
def bootstrap_servers(servers, username, password, role_name, clone_url): logger.info('bootstrapping {}'.format(servers)) logger.info('Bootstrapping servers: {0}'.format(servers)) command = ''' if [ ! -f '/src/{0}/toy-client.py' ]; then apt-get install -y git python-pip libevent-dev \ && mkdir -p /src ; cd /src; git clone {1}; \ pip3 install -r '/src/{0}/requirements.txt'; fi'''.format(role_name, clone_url) try: ssh_client = ParallelSSHClient(servers, user=username, password=password, pool_size=100) output = read_stdout(ssh_client.run_command('{}'.format(command), stop_on_errors=True)) BOOTSTRAPPED.append(servers) except Exception as e: print('Exception: {}'.format(e))
def test_pssh_client_retries(self): """Test connection error retries""" expected_num_tries = 2 with self.assertRaises(ConnectionErrorException) as cm: client = ParallelSSHClient(['127.0.0.1'], port=self.listen_port, pkey=self.user_key, num_retries=expected_num_tries) cmd = client.exec_command('blah')[0] cmd.get() num_tries = cm.exception.args[-1:][0] self.assertEqual(expected_num_tries, num_tries, msg="Got unexpected number of retries %s - expected %s" % (num_tries, expected_num_tries,))