From patchwork Fri Jun 18 00:14:28 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Goldish X-Patchwork-Id: 106777 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o5I0FLT9015965 for ; Fri, 18 Jun 2010 00:15:21 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1760858Ab0FRAPQ (ORCPT ); Thu, 17 Jun 2010 20:15:16 -0400 Received: from mx1.redhat.com ([209.132.183.28]:26880 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1760905Ab0FRAPG (ORCPT ); Thu, 17 Jun 2010 20:15:06 -0400 Received: from int-mx03.intmail.prod.int.phx2.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.16]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o5I0F3D1004188 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 17 Jun 2010 20:15:03 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx03.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o5I0F2lq016406; Thu, 17 Jun 2010 20:15:03 -0400 Received: from localhost.localdomain (dhcp-1-188.tlv.redhat.com [10.35.1.188]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id o5I0EljR005733; Thu, 17 Jun 2010 20:15:01 -0400 From: Michael Goldish To: autotest@test.kernel.org, kvm@vger.kernel.org Cc: Michael Goldish Subject: [KVM-AUTOTEST PATCH 11/18] KVM test: restructure remote_login() and remote_scp() Date: Fri, 18 Jun 2010 03:14:28 +0300 Message-Id: <1276820075-31310-11-git-send-email-mgoldish@redhat.com> In-Reply-To: <1276820075-31310-10-git-send-email-mgoldish@redhat.com> References: <1276820075-31310-1-git-send-email-mgoldish@redhat.com> <1276820075-31310-2-git-send-email-mgoldish@redhat.com> <1276820075-31310-3-git-send-email-mgoldish@redhat.com> <1276820075-31310-4-git-send-email-mgoldish@redhat.com> <1276820075-31310-5-git-send-email-mgoldish@redhat.com> <1276820075-31310-6-git-send-email-mgoldish@redhat.com> <1276820075-31310-7-git-send-email-mgoldish@redhat.com> <1276820075-31310-8-git-send-email-mgoldish@redhat.com> <1276820075-31310-9-git-send-email-mgoldish@redhat.com> <1276820075-31310-10-git-send-email-mgoldish@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.16 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Fri, 18 Jun 2010 00:15:21 +0000 (UTC) diff --git a/client/tests/kvm/kvm_utils.py b/client/tests/kvm/kvm_utils.py index 8569ac3..468e7a8 100644 --- a/client/tests/kvm/kvm_utils.py +++ b/client/tests/kvm/kvm_utils.py @@ -451,142 +451,183 @@ def check_kvm_source_dir(source_dir): # The following are functions used for SSH, SCP and Telnet communication with # guests. -def remote_login(command, password, prompt, linesep="\n", timeout=10): +def _remote_login(session, password, prompt, timeout=10): """ - Log into a remote host (guest) using SSH or Telnet. Run the given command - using kvm_spawn and provide answers to the questions asked. If timeout - expires while waiting for output from the child (e.g. a password prompt - or a shell prompt) -- fail. + Log into a remote host (guest) using SSH or Telnet. Wait for questions + and provide answers. If timeout expires while waiting for output from the + child (e.g. a password prompt or a shell prompt) -- fail. @brief: Log into a remote host (guest) using SSH or Telnet. - @param command: The command to execute (e.g. "ssh root@localhost") + @param session: A kvm_expect or kvm_shell_session instance to operate on @param password: The password to send in reply to a password prompt @param prompt: The shell prompt that indicates a successful login - @param linesep: The line separator to send instead of "\\n" - (sometimes "\\r\\n" is required) @param timeout: The maximal time duration (in seconds) to wait for each step of the login procedure (i.e. the "Are you sure" prompt, the password prompt, the shell prompt, etc) - @return Return the kvm_spawn object on success and None on failure. + @return: True on success and False otherwise. """ - sub = kvm_subprocess.kvm_shell_session(command, - linesep=linesep, - prompt=prompt) - password_prompt_count = 0 - logging.debug("Trying to login with command '%s'" % command) - while True: - (match, text) = sub.read_until_last_line_matches( + (match, text) = session.read_until_last_line_matches( [r"[Aa]re you sure", r"[Pp]assword:\s*$", r"^\s*[Ll]ogin:\s*$", r"[Cc]onnection.*closed", r"[Cc]onnection.*refused", r"[Pp]lease wait", prompt], timeout=timeout, internal_timeout=0.5) if match == 0: # "Are you sure you want to continue connecting" logging.debug("Got 'Are you sure...'; sending 'yes'") - sub.sendline("yes") + session.sendline("yes") continue elif match == 1: # "password:" if password_prompt_count == 0: logging.debug("Got password prompt; sending '%s'" % password) - sub.sendline(password) + session.sendline(password) password_prompt_count += 1 continue else: logging.debug("Got password prompt again") - sub.close() - return None + return False elif match == 2: # "login:" logging.debug("Got unexpected login prompt") - sub.close() - return None + return False elif match == 3: # "Connection closed" logging.debug("Got 'Connection closed'") - sub.close() - return None + return False elif match == 4: # "Connection refused" logging.debug("Got 'Connection refused'") - sub.close() - return None + return False elif match == 5: # "Please wait" logging.debug("Got 'Please wait'") timeout = 30 continue elif match == 6: # prompt logging.debug("Got shell prompt -- logged in") - return sub + return session else: # match == None logging.debug("Timeout elapsed or process terminated") - sub.close() - return None + return False -def remote_scp(command, password, transfer_timeout=600, login_timeout=10): +def _remote_scp(session, password, transfer_timeout=600, login_timeout=10): """ - Run the given command using kvm_spawn and provide answers to the questions - asked. If transfer_timeout expires while waiting for the transfer to - complete, fail. If login_timeout expires while waiting for output from the - child (e.g. a password prompt), fail. + Transfer file(s) to a remote host (guest) using SCP. Wait for questions + and provide answers. If login_timeout expires while waiting for output + from the child (e.g. a password prompt), fail. If transfer_timeout expires + while waiting for the transfer to complete, fail. @brief: Transfer files using SCP, given a command line. - @param command: The command to execute - (e.g. "scp -r foobar root@localhost:/tmp/"). + @param session: A kvm_expect or kvm_shell_session instance to operate on @param password: The password to send in reply to a password prompt. @param transfer_timeout: The time duration (in seconds) to wait for the - transfer to complete. + transfer to complete. @param login_timeout: The maximal time duration (in seconds) to wait for - each step of the login procedure (i.e. the "Are you sure" prompt or the - password prompt) + each step of the login procedure (i.e. the "Are you sure" prompt + or the password prompt) @return: True if the transfer succeeds and False on failure. """ - sub = kvm_subprocess.kvm_expect(command) - password_prompt_count = 0 timeout = login_timeout - logging.debug("Trying to SCP with command '%s', timeout %ss", - command, timeout) - while True: - (match, text) = sub.read_until_last_line_matches( + (match, text) = session.read_until_last_line_matches( [r"[Aa]re you sure", r"[Pp]assword:\s*$", r"lost connection"], timeout=timeout, internal_timeout=0.5) if match == 0: # "Are you sure you want to continue connecting" logging.debug("Got 'Are you sure...'; sending 'yes'") - sub.sendline("yes") + session.sendline("yes") continue elif match == 1: # "password:" if password_prompt_count == 0: logging.debug("Got password prompt; sending '%s'" % password) - sub.sendline(password) + session.sendline(password) password_prompt_count += 1 timeout = transfer_timeout continue else: logging.debug("Got password prompt again") - sub.close() return False elif match == 2: # "lost connection" logging.debug("Got 'lost connection'") - sub.close() return False else: # match == None - if sub.is_alive(): + if session.is_alive(): logging.debug("Timeout expired") - sub.close() return False else: - status = sub.get_status() - sub.close() + status = session.get_status() logging.debug("SCP process terminated with status %s", status) return status == 0 +def remote_login(client, host, port, username, password, prompt, linesep="\n", + timeout=10): + """ + Log into a remote host (guest) using SSH/Telnet/Netcat. + + @param client: The client to use ('ssh', 'telnet' or 'nc') + @param host: Hostname or IP address + @param port: Port to connect to + @param username: Username (if required) + @param password: Password (if required) + @param prompt: Shell prompt (regular expression) + @param linesep: The line separator to use when sending lines + (e.g. '\\n' or '\\r\\n') + @param timeout: The maximal time duration (in seconds) to wait for + each step of the login procedure (i.e. the "Are you sure" prompt + or the password prompt) + + @return: kvm_shell_session object on success and None on failure. + """ + if client == "ssh": + cmd = ("ssh -o UserKnownHostsFile=/dev/null " + "-o PreferredAuthentications=password -p %s %s@%s" % + (port, username, host)) + elif client == "telnet": + cmd = "telnet -l %s %s %s" % (username, host, port) + elif client == "nc": + cmd = "nc %s %s" % (host, port) + else: + logging.error("Unknown remote shell client: %s" % client) + return + logging.debug("Trying to login with command '%s'" % cmd) + session = kvm_subprocess.kvm_shell_session(cmd, linesep=linesep, + prompt=prompt) + if _remote_login(session, password, prompt, timeout): + return session + else: + session.close() + + +def remote_scp(command, password, transfer_timeout=600, login_timeout=10): + """ + Transfer file(s) to a remote host (guest) using SCP. + + @brief: Transfer files using SCP, given a command line. + + @param command: The command to execute + (e.g. "scp -r foobar root@localhost:/tmp/"). + @param password: The password to send in reply to a password prompt. + @param transfer_timeout: The time duration (in seconds) to wait for the + transfer to complete. + @param login_timeout: The maximal time duration (in seconds) to wait for + each step of the login procedure (i.e. the "Are you sure" prompt + or the password prompt) + + @return: True if the transfer succeeds and False on failure. + """ + logging.debug("Trying to SCP with command '%s', timeout %ss", + command, transfer_timeout) + session = kvm_subprocess.kvm_expect(command) + try: + return _remote_scp(session, password, transfer_timeout, login_timeout) + finally: + session.close() + + def scp_to_remote(host, port, username, password, local_path, remote_path, timeout=600): """ @@ -597,8 +638,8 @@ def scp_to_remote(host, port, username, password, local_path, remote_path, @param password: Password (if required) @param local_path: Path on the local machine where we are copying from @param remote_path: Path on the remote machine where we are copying to - @param timeout: Time in seconds that we will wait before giving up to - copy the files. + @param timeout: The time duration (in seconds) to wait for the transfer + to complete. @return: True on success and False on failure. """ @@ -618,8 +659,8 @@ def scp_from_remote(host, port, username, password, remote_path, local_path, @param password: Password (if required) @param local_path: Path on the local machine where we are copying from @param remote_path: Path on the remote machine where we are copying to - @param timeout: Time in seconds that we will wait before giving up to copy - the files. + @param timeout: The time duration (in seconds) to wait for the transfer + to complete. @return: True on success and False on failure. """ @@ -629,59 +670,6 @@ def scp_from_remote(host, port, username, password, remote_path, local_path, return remote_scp(command, password, timeout) -def ssh(host, port, username, password, prompt, linesep="\n", timeout=10): - """ - Log into a remote host (guest) using SSH. - - @param host: Hostname or IP address - @param username: Username (if required) - @param password: Password (if required) - @param prompt: Shell prompt (regular expression) - @timeout: Time in seconds that we will wait before giving up on logging - into the host. - - @return: kvm_spawn object on success and None on failure. - """ - command = ("ssh -o UserKnownHostsFile=/dev/null " - "-o PreferredAuthentications=password -p %s %s@%s" % - (port, username, host)) - return remote_login(command, password, prompt, linesep, timeout) - - -def telnet(host, port, username, password, prompt, linesep="\n", timeout=10): - """ - Log into a remote host (guest) using Telnet. - - @param host: Hostname or IP address - @param username: Username (if required) - @param password: Password (if required) - @param prompt: Shell prompt (regular expression) - @timeout: Time in seconds that we will wait before giving up on logging - into the host. - - @return: kvm_spawn object on success and None on failure. - """ - command = "telnet -l %s %s %s" % (username, host, port) - return remote_login(command, password, prompt, linesep, timeout) - - -def netcat(host, port, username, password, prompt, linesep="\n", timeout=10): - """ - Log into a remote host (guest) using Netcat. - - @param host: Hostname or IP address - @param username: Username (if required) - @param password: Password (if required) - @param prompt: Shell prompt (regular expression) - @timeout: Time in seconds that we will wait before giving up on logging - into the host. - - @return: kvm_spawn object on success and None on failure. - """ - command = "nc %s %s" % (host, port) - return remote_login(command, password, prompt, linesep, timeout) - - # The following are utility functions related to ports. def is_port_free(port): diff --git a/client/tests/kvm/kvm_vm.py b/client/tests/kvm/kvm_vm.py index 8113a45..c82226d 100755 --- a/client/tests/kvm/kvm_vm.py +++ b/client/tests/kvm/kvm_vm.py @@ -901,15 +901,8 @@ class VM: logging.debug("IP address or port unavailable") return None - if client == "ssh": - session = kvm_utils.ssh(address, port, username, password, - prompt, linesep, timeout) - elif client == "telnet": - session = kvm_utils.telnet(address, port, username, password, - prompt, linesep, timeout) - elif client == "nc": - session = kvm_utils.netcat(address, port, username, password, - prompt, linesep, timeout) + session = kvm_utils.remote_login(client, address, port, username, + password, prompt, linesep, timeout) if session: session.set_status_test_command(self.params.get("status_test_"