@@ -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):
@@ -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_"