diff --git a/client/tests/kvm/kvm_tests.cfg.sample b/client/tests/kvm/kvm_tests.cfg.sample
index 3a4bf64..8238f3e 100644
--- a/client/tests/kvm/kvm_tests.cfg.sample
+++ b/client/tests/kvm/kvm_tests.cfg.sample
@@ -17,12 +17,12 @@ kill_vm_gracefully = yes
 # Some default VM params
 mem = 512
 image_size = 10G
-ssh_port = 22
+shell_port = 22
 display = vnc
 
 # Port redirections
-redirs = ssh
-guest_port_ssh = 22
+redirs = remote_shell
+guest_port_remote_shell = 22
 
 # NIC parameters
 nic_mode = tap
@@ -146,16 +146,20 @@ variants:
     # Linux section
     - @Linux:
         no timedrift
-        cmd_shutdown = shutdown -h now
-        cmd_reboot = shutdown -r now
-        ssh_status_test_command = echo $?
+        shutdown_command = shutdown -h now
+        reboot_command = shutdown -r now
+        status_test_command = echo $?
         username = root
         password = 123456
+        shell_client = ssh
+        shell_port = 22
+        file_transfer_client = scp
+        file_transfer_port = 22
 
         variants:
             - Fedora:
                 no setup
-                ssh_prompt = "\[root@.{0,50}][\#\$] "
+                shell_prompt = "\[root@.{0,50}][\#\$] "
 
                 variants:
                     - 8.32:
@@ -237,7 +241,7 @@ variants:
                     md5sum_1m = 768ca32503ef92c28f2d144f2a87e4d0
 
             - @Ubuntu:
-                ssh_prompt = "root@.{0,50}[\#\$] "
+                shell_prompt = "root@.{0,50}[\#\$] "
 
                 variants:
                     - Ubuntu-6.10-32:
@@ -269,7 +273,7 @@ variants:
 
             - RHEL:
                 no setup
-                ssh_prompt = "\[root@.{0,50}][\#\$] "
+                shell_prompt = "\[root@.{0,50}][\#\$] "
 
                 variants:
                     - 5.3.i386:
@@ -329,12 +333,17 @@ variants:
     # Windows section
     - @Windows:
         no autotest
-        cmd_shutdown = shutdown /s /t 0
-        cmd_reboot = shutdown /r /t 0
-        ssh_prompt = "C:\\.{0,50}>"
-        ssh_status_test_command = echo %errorlevel%
+        shutdown_command = shutdown /s /t 0
+        reboot_command = shutdown /r /t 0
+        status_test_command = echo %errorlevel%
+        shell_prompt = "C:\\.{0,50}>"
         username = Administrator
         password = 123456
+        shell_client = ssh
+        shell_port = 22
+        file_transfer_client = scp
+        file_transfer_port = 22
+
         migrate:
             migration_test_command = ver && vol
         stress_boot:
@@ -394,8 +403,8 @@ variants:
 
             - Win2003:
                 image_size = 20G
-                cmd_shutdown = shutdown /s /f /t 0
-                cmd_reboot = shutdown /r /f /t 0
+                shutdown_command = shutdown /s /f /t 0
+                reboot_command = shutdown /r /f /t 0
 
                 variants:
                     - 32:
@@ -443,10 +452,10 @@ variants:
             - Win2008:
                 image_name = win2008
                 image_size = 20G
-                cmd_shutdown = shutdown /s /f /t 0
-                cmd_reboot = shutdown /r /f /t 0
-                ssh_port = 23
-                guest_port_ssh = 23
+                shutdown_command = shutdown /s /f /t 0
+                reboot_command = shutdown /r /f /t 0
+                shell_port = 23
+                guest_port_remote_shell = 23
                 use_telnet = yes
                 username = Administrator
                 password = 1q2w3eP
diff --git a/client/tests/kvm/kvm_tests.py b/client/tests/kvm/kvm_tests.py
index d146929..3fa0837 100644
--- a/client/tests/kvm/kvm_tests.py
+++ b/client/tests/kvm/kvm_tests.py
@@ -29,7 +29,7 @@ def run_boot(test, params, env):
 
     logging.info("Waiting for guest to be up...")
 
-    session = kvm_utils.wait_for(vm.ssh_login, 240, 0, 2)
+    session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
     if not session:
         raise error.TestFail("Could not log into guest")
 
@@ -37,7 +37,7 @@ def run_boot(test, params, env):
 
     if params.get("reboot") == "yes":
         # Send the VM's reboot command
-        session.sendline(vm.get_params().get("cmd_reboot"))
+        session.sendline(vm.get_params().get("reboot_command"))
         logging.info("Reboot command sent; waiting for guest to go down...")
 
         if not kvm_utils.wait_for(lambda: not session.is_responsive(),
@@ -48,7 +48,7 @@ def run_boot(test, params, env):
 
         logging.info("Guest is down; waiting for it to go up again...")
 
-        session = kvm_utils.wait_for(vm.ssh_login, 240, 0, 2)
+        session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
         if not session:
             raise error.TestFail("Could not log into guest after reboot")
 
@@ -76,14 +76,14 @@ def run_shutdown(test, params, env):
 
     logging.info("Waiting for guest to be up...")
 
-    session = kvm_utils.wait_for(vm.ssh_login, 240, 0, 2)
+    session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
     if not session:
         raise error.TestFail("Could not log into guest")
 
     logging.info("Logged in")
 
     # Send the VM's shutdown command
-    session.sendline(vm.get_params().get("cmd_shutdown"))
+    session.sendline(vm.get_params().get("shutdown_command"))
     session.close()
 
     logging.info("Shutdown command sent; waiting for guest to go down...")
@@ -139,7 +139,7 @@ def run_migration(test, params, env):
     # Log into guest and get the output of migration_test_command
     logging.info("Waiting for guest to be up...")
 
-    session = kvm_utils.wait_for(vm.ssh_login, 240, 0, 2)
+    session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
     if not session:
         raise error.TestFail("Could not log into guest")
 
@@ -208,14 +208,14 @@ def run_migration(test, params, env):
 
     # Hack: it seems that the first attempt to communicate with the SSH port
     # following migration always fails (or succeeds after a very long time).
-    # So just connect to the port once so the following call to ssh_login
+    # So just connect to the port once so the following call to remote_login
     # succeeds.
     dest_vm.is_sshd_running(timeout=0.0)
 
     # Log into guest and get the output of migration_test_command
     logging.info("Logging into guest after migration...")
 
-    session = dest_vm.ssh_login()
+    session = dest_vm.remote_login()
     if not session:
         raise error.TestFail("Could not log into guest after migration")
 
@@ -252,7 +252,7 @@ def run_autotest(test, params, env):
 
     logging.info("Logging into guest...")
 
-    session = kvm_utils.wait_for(vm.ssh_login, 240, 0, 2)
+    session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
     if not session:
         raise error.TestFail("Could not log into guest")
 
@@ -298,7 +298,7 @@ def run_autotest(test, params, env):
     if copy:
         logging.info("Copying autotest.tar.bz2 to guest"
                      " (file is missing or has a different size)...")
-        if not vm.scp_to_remote(tarred_autotest_path, ""):
+        if not vm.copy_files_to(tarred_autotest_path, ""):
             raise error.TestFail("Could not copy autotest.tar.bz2 to guest")
 
     # Check if we need to copy <test_name>.tar.bz2
@@ -314,7 +314,7 @@ def run_autotest(test, params, env):
     if copy:
         logging.info("Copying %s.tar.bz2 to guest (file is missing or has a"
                      " different size)..." % test_name)
-        if not vm.scp_to_remote(tarred_test_path, ""):
+        if not vm.copy_files_to(tarred_test_path, ""):
             raise error.TestFail("Could not copy %s.tar.bz2 to guest" %
                                  test_name)
 
@@ -340,7 +340,7 @@ def run_autotest(test, params, env):
     # test.bindir/autotest_control to the autotest dir
     control_file_path = os.path.join(test.bindir, "autotest_control",
                                      test_control_file)
-    if not vm.scp_to_remote(control_file_path, "autotest/control"):
+    if not vm.copy_files_to(control_file_path, "autotest/control"):
         raise error.TestFail("Could not copy the test control file to guest")
     # Run the test
     logging.info("Running test '%s'..." % test_name)
@@ -389,7 +389,7 @@ def run_autotest(test, params, env):
     guest_results_dir = os.path.join(test.outputdir, "guest_results")
     if not os.path.exists(guest_results_dir):
         os.mkdir(guest_results_dir)
-    if not vm.scp_from_remote("autotest/results/default/*", guest_results_dir):
+    if not vm.copy_files_from("autotest/results/default/*", guest_results_dir):
         logging.error("Could not copy results back from guest")
 
     # Fail the test if necessary
@@ -403,11 +403,11 @@ def internal_yum_update(session, command, prompt, timeout):
     """
     Helper function to perform the yum update test.
 
-    @param session: SSH session stablished to the host
-    @param command: Command to be sent to the SSH connection
+    @param session: shell session stablished to the host
+    @param command: Command to be sent to the shell session
     @param prompt: Machine prompt
     @param timeout: How long to wait until we get an appropriate output from
-            the SSH session.
+            the shell session.
     """
     session.sendline(command)
     end_time = time.time() + timeout
@@ -446,7 +446,7 @@ def run_yum_update(test, params, env):
 
     logging.info("Logging into guest...")
 
-    session = kvm_utils.wait_for(vm.ssh_login, 240, 0, 2)
+    session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
     if not session:
         message = "Could not log into guest"
         logging.error(message)
@@ -454,9 +454,9 @@ def run_yum_update(test, params, env):
 
     logging.info("Logged in")
 
-    internal_yum_update(session, "yum update", params.get("ssh_prompt"), 600)
+    internal_yum_update(session, "yum update", params.get("shell_prompt"), 600)
     internal_yum_update(session, "yum update kernel",
-                        params.get("ssh_prompt"), 600)
+                        params.get("shell_prompt"), 600)
 
     session.close()
 
@@ -477,7 +477,7 @@ def run_linux_s3(test, params, env):
 
     logging.info("Waiting for guest to be up...")
 
-    session = kvm_utils.wait_for(vm.ssh_login, 240, 0, 2)
+    session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
     if not session:
         raise error.TestFail("Could not log into guest")
 
@@ -520,7 +520,7 @@ def run_stress_boot(tests, params, env):
     number of VMs successfully started:
     1) boot the first vm
     2) boot the second vm cloned from the first vm, check whether it boots up
-       and all booted vms can ssh-login
+       and all booted vms respond to shell commands
     3) go on until cannot create VM anymore or cannot allocate memory for VM
 
     @param test:   kvm test object
@@ -536,7 +536,7 @@ def run_stress_boot(tests, params, env):
 
     logging.info("Waiting for first guest to be up...")
 
-    session = kvm_utils.wait_for(vm.ssh_login, 240, 0, 2)
+    session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
     if not session:
         raise error.TestFail("Could not log into first guest")
 
@@ -560,14 +560,14 @@ def run_stress_boot(tests, params, env):
             if not curr_vm.create():
                 raise error.TestFail("Cannot create VM #%d" % num)
 
-            curr_vm_session = kvm_utils.wait_for(curr_vm.ssh_login, 240, 0, 2)
+            curr_vm_session = kvm_utils.wait_for(curr_vm.remote_login, 240, 0, 2)
             if not curr_vm_session:
                 raise error.TestFail("Could not log into guest #%d" % num)
 
             logging.info("Guest #%d boots up successfully" % num)
             sessions.append(curr_vm_session)
 
-            # check whether all previous ssh sessions are responsive
+            # check whether all previous shell sessions are responsive
             for i, se in enumerate(sessions):
                 if se.get_command_status(params.get("alive_test_cmd")) != 0:
                     raise error.TestFail("Session #%d is not responsive" % i)
@@ -651,7 +651,7 @@ def run_timedrift(test, params, env):
 
     logging.info("Waiting for guest to be up...")
 
-    session = kvm_utils.wait_for(vm.ssh_login, 240, 0, 2)
+    session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2)
     if not session:
         raise error.TestFail("Could not log into guest")
 
@@ -690,7 +690,7 @@ def run_timedrift(test, params, env):
         # Run some load on the guest
         logging.info("Starting load on guest...")
         for i in range(guest_load_instances):
-            load_session = vm.ssh_login()
+            load_session = vm.remote_login()
             if not load_session:
                 raise error.TestFail("Could not log into guest")
             load_session.set_output_prefix("(guest load %d) " % i)
diff --git a/client/tests/kvm/kvm_utils.py b/client/tests/kvm/kvm_utils.py
index 17c2b73..d1c9781 100644
--- a/client/tests/kvm/kvm_utils.py
+++ b/client/tests/kvm/kvm_utils.py
@@ -492,9 +492,9 @@ def scp_to_remote(host, port, username, password, local_path, remote_path,
     """
     Copy files to a remote host (guest).
 
-    @param host: Hostname of the guest
-    @param username: User that will be used to copy the files
-    @param password: Host's password
+    @param host: Hostname or IP address
+    @param username: Username (if required)
+    @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
@@ -512,9 +512,9 @@ def scp_from_remote(host, port, username, password, remote_path, local_path,
     """
     Copy files from a remote host (guest).
 
-    @param host: Hostname of the guest
-    @param username: User that will be used to copy the files
-    @param password: Host's password
+    @param host: Hostname or IP address
+    @param username: Username (if required)
+    @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
@@ -531,9 +531,10 @@ def ssh(host, port, username, password, prompt, timeout=10):
     """
     Log into a remote host (guest) using SSH.
 
-    @param host: Hostname of the guest
-    @param username: User that will be used to log into the host.
-    @param password: Host's password
+    @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.
 
@@ -548,9 +549,10 @@ def telnet(host, port, username, password, prompt, timeout=10):
     """
     Log into a remote host (guest) using Telnet.
 
-    @param host: Hostname of the guest
-    @param username: User that will be used to log into the host.
-    @param password: Host's password
+    @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.
 
diff --git a/client/tests/kvm/kvm_vm.py b/client/tests/kvm/kvm_vm.py
index 2c828c6..4a862bd 100644
--- a/client/tests/kvm/kvm_vm.py
+++ b/client/tests/kvm/kvm_vm.py
@@ -191,7 +191,10 @@ class VM:
                cdrom -- ISO filename to use with the qemu -cdrom parameter
                (iso_dir is pre-pended to the ISO filename)
                extra_params -- a string to append to the qemu command
-               ssh_port -- should be 22 for SSH, 23 for Telnet
+               shell_port -- port of the remote shell daemon on the guest
+               (SSH, Telnet or the home-made Remote Shell Server)
+               shell_client -- client program to use for connecting to the
+               remote shell daemon on the guest (ssh, telnet or nc)
                x11_display -- if specified, the DISPLAY environment variable
                will be be set to this value for the qemu process (useful for
                SDL rendering)
@@ -533,14 +536,13 @@ class VM:
         """
         Destroy the VM.
 
-        If gracefully is True, first attempt to kill the VM via SSH/Telnet
-        with a shutdown command. Then, attempt to destroy the VM via the
-        monitor with a 'quit' command. If that fails, send SIGKILL to the
-        qemu process.
+        If gracefully is True, first attempt to shutdown the VM with a shell
+        command.  Then, attempt to destroy the VM via the monitor with a 'quit'
+        command.  If that fails, send SIGKILL to the qemu process.
 
         @param gracefully: Whether an attempt will be made to end the VM
-                using monitor command before trying to kill the qemu process
-                or not.
+                using a shell command before trying to end the qemu process
+                with a 'quit' or a kill signal.
         """
         # Is it already dead?
         if self.is_dead():
@@ -551,18 +553,22 @@ class VM:
 
         logging.debug("Destroying VM with PID %d..." % self.process.get_pid())
 
-        if gracefully and self.params.get("cmd_shutdown"):
-            # Try to destroy with SSH command
-            logging.debug("Trying to shutdown VM with SSH command...")
-            (status, output) = self.ssh(self.params.get("cmd_shutdown"))
-            # Was the command sent successfully?
-            if status == 0:
-                logging.debug("Shutdown command sent; waiting for VM to go "
-                              "down...")
-                if kvm_utils.wait_for(self.is_dead, 60, 1, 1):
-                    logging.debug("VM is down")
-                    self.process.close()
-                    return
+        if gracefully and self.params.get("shutdown_command"):
+            # Try to destroy with shell command
+            logging.debug("Trying to shutdown VM with shell command...")
+            session = self.remote_login()
+            if session:
+                try:
+                    # Send the shutdown command
+                    session.sendline(self.params.get("shutdown_command"))
+                    logging.debug("Shutdown command sent; waiting for VM to go "
+                                  "down...")
+                    if kvm_utils.wait_for(self.is_dead, 60, 1, 1):
+                        logging.debug("VM is down")
+                        self.process.close()
+                        return
+                finally:
+                    session.close()
 
         # Try to destroy with a monitor command
         logging.debug("Trying to kill VM with monitor command...")
@@ -680,22 +686,22 @@ class VM:
 
     def is_sshd_running(self, timeout=10):
         """
-        Return True iff the guest's SSH port is responsive.
+        Return True iff the guest's remote shell port is responsive.
 
-        @param timeout: Time (seconds) before giving up checking the SSH daemon
+        @param timeout: Time (seconds) before giving up checking the daemon's
                 responsiveness.
         """
         address = self.get_address()
-        port = self.get_port(int(self.params.get("ssh_port")))
+        port = self.get_port(int(self.params.get("shell_port")))
         if not address or not port:
             logging.debug("IP address or port unavailable")
             return False
         return kvm_utils.is_sshd_running(address, port, timeout=timeout)
 
 
-    def ssh_login(self, nic_index=0, timeout=10):
+    def remote_login(self, nic_index=0, timeout=10):
         """
-        Log into the guest via SSH/Telnet.
+        Log into the guest via SSH/Telnet/Netcat.
         If timeout expires while waiting for output from the guest (e.g. a
         password prompt or a shell prompt) -- fail.
 
@@ -706,85 +712,76 @@ class VM:
         """
         username = self.params.get("username", "")
         password = self.params.get("password", "")
-        prompt = self.params.get("ssh_prompt", "[\#\$]")
-        use_telnet = self.params.get("use_telnet") == "yes"
+        prompt = self.params.get("shell_prompt", "[\#\$]")
+        client = self.params.get("shell_client")
         address = self.get_address(nic_index)
-        port = self.get_port(int(self.params.get("ssh_port")))
+        port = self.get_port(int(self.params.get("shell_port")))
+
         if not address or not port:
             logging.debug("IP address or port unavailable")
             return None
 
-        if use_telnet:
-            session = kvm_utils.telnet(address, port, username, password,
-                                       prompt, timeout)
-        else:
+        if client == "ssh":
             session = kvm_utils.ssh(address, port, username, password,
                                     prompt, timeout)
+        elif client == "telnet":
+            session = kvm_utils.telnet(address, port, username, password,
+                                       prompt, timeout)
+
         if session:
-            session.set_status_test_command(self.params.get("ssh_status_test_"
+            session.set_status_test_command(self.params.get("status_test_"
                                                             "command", ""))
         return session
 
 
-    def scp_to_remote(self, local_path, remote_path, nic_index=0, timeout=300):
+    def copy_files_to(self, local_path, remote_path, nic_index=0, timeout=300):
         """
-        Transfer files to the guest via SCP.
+        Transfer files to the guest.
 
         @param local_path: Host path
         @param remote_path: Guest path
+        @param nic_index: The index of the NIC to connect to.
         @param timeout: Time (seconds) before giving up on doing the remote
                 copy.
         """
         username = self.params.get("username", "")
         password = self.params.get("password", "")
+        client = self.params.get("file_transfer_client")
         address = self.get_address(nic_index)
-        port = self.get_port(int(self.params.get("ssh_port")))
+        port = self.get_port(int(self.params.get("file_transfer_port")))
+
         if not address or not port:
             logging.debug("IP address or port unavailable")
             return None
-        return kvm_utils.scp_to_remote(address, port, username, password,
-                                       local_path, remote_path, timeout)
 
+        if client == "scp":
+            return kvm_utils.scp_to_remote(address, port, username, password,
+                                           local_path, remote_path, timeout)
 
-    def scp_from_remote(self, remote_path, local_path, nic_index=0, timeout=300):
+
+    def copy_files_from(self, remote_path, local_path, nic_index=0, timeout=300):
         """
-        Transfer files from the guest via SCP.
+        Transfer files from the guest.
 
         @param local_path: Guest path
         @param remote_path: Host path
+        @param nic_index: The index of the NIC to connect to.
         @param timeout: Time (seconds) before giving up on doing the remote
                 copy.
         """
         username = self.params.get("username", "")
         password = self.params.get("password", "")
+        client = self.params.get("file_transfer_client")
         address = self.get_address(nic_index)
-        port = self.get_port(int(self.params.get("ssh_port")))
+        port = self.get_port(int(self.params.get("file_transfer_port")))
+
         if not address or not port:
             logging.debug("IP address or port unavailable")
             return None
-        return kvm_utils.scp_from_remote(address, port, username, password,
-                                         remote_path, local_path, timeout)
-
-
-    def ssh(self, command, timeout=10):
-        """
-        Login via SSH/Telnet and send a command.
-
-        @command: Command that will be sent.
-        @timeout: Time before giving up waiting on a status return.
-        @return: A tuple (status, output). status is 0 on success and 1 on
-                failure.
-        """
-        session = self.ssh_login(timeout=timeout)
-        if not session:
-            return (1, "")
-
-        logging.debug("Sending command: %s" % command)
-        session.sendline(command)
-        output = session.read_nonblocking(1.0)
-        session.close()
 
-        return (0, output)
+        if client == "scp":
+            return kvm_utils.scp_from_remote(address, port, username, password,
+                                             remote_path, local_path, timeout)
 
 
     def send_key(self, keystr):
