- Add _remote_login() and _remote_scp() which, instead
  of taking a command line, take an existing session
  and operate on it.  This is useful for logging into
  existing always-open sessions, such as serial console
  sessions.

- Merge ssh/telnet/netcat into remote_login().

Signed-off-by: Michael Goldish <mgold...@redhat.com>
---
 client/tests/kvm/kvm_utils.py |  209 +++++++++++++++++++----------------------
 client/tests/kvm/kvm_vm.py    |   11 +--
 2 files changed, 100 insertions(+), 120 deletions(-)

diff --git a/client/tests/kvm/kvm_utils.py b/client/tests/kvm/kvm_utils.py
index 367e1e5..d4edbaa 100644
--- a/client/tests/kvm/kvm_utils.py
+++ b/client/tests/kvm/kvm_utils.py
@@ -451,143 +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 r...@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 r...@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', login timeout %ds, "
-                  "transfer timeout %ds", command, login_timeout,
-                  transfer_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" %
+               (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 r...@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):
     """
@@ -598,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.
     """
@@ -619,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.
     """
@@ -630,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" %
-               (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 1944372..225f26a 100755
--- a/client/tests/kvm/kvm_vm.py
+++ b/client/tests/kvm/kvm_vm.py
@@ -903,15 +903,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_"
-- 
1.7.0.1

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to