Hello everyone, I like to submit patch to add support for "remote migration" in kvm-autotest. To use this patch the following four parameters should be added to the existing migration test remote = dst hostip = <localhost ip or name> remoteip = <remote host ip or name> remuser = root rempassword = <password> the field remote=dst indicates the VM "dst" should be created on remote machine. For example: - migrate: install setup type = migration vms += " dst" migration_test_command = help kill_vm_on_error = yes remote = dst hostip = 192.168.1.2 remoteip = 192.168.1.3 remuser = root rempassword = 123456 variants: Three files r being modified in this patch kvm_utils.py, kvm_tests.py and kvm_vm.py. kvm_utils.py - if the ssh-keys have been exchanged between the test machines,then remote login fails with message "Got unexpected login prompt", to prevent this, have made it return a session rather then None kvm_tests.py - the host address used in migration is made dynamic kvm_vm.py - have replaced unix sockets with tcp sockets for monitor, in both remote and local VM. Added two new variables(remote,ssh_port) to class VM,remote set to True if the VM is on a remote machine,ssh_port contains the redirection port, funtion get_address() returns the ip of the host whr the VM is(local or remote). Thx Yogi
kvm_tests.py | 2 - kvm_utils.py | 3 -- kvm_vm.py | 61 ++++++++++++++++++++++++++++++++++++++++++++--------------- 3 files changed, 48 insertions(+), 18 deletions(-) Signed-off-by: Yogananth Subramanian <anantyog@xxxxxxxxxx> --- diff -aurp kvm-autotest.orgi//client/tests/kvm_runtest_2/kvm_tests.py kvm-autotest/client/tests/kvm_runtest_2/kvm_tests.py --- kvm-autotest.orgi//client/tests/kvm_runtest_2/kvm_tests.py 2009-04-29 18:33:10.000000000 +0000 +++ kvm-autotest/client/tests/kvm_runtest_2/kvm_tests.py 2009-04-30 05:59:24.000000000 +0000 @@ -81,7 +81,7 @@ def run_migration(test, params, env): session.close() # Define the migration command - cmd = "migrate -d tcp:localhost:%d" % dest_vm.migration_port + cmd = "migrate -d tcp:%s:%d" % (dest_vm.hostip,dest_vm.migration_port) kvm_log.debug("Migration command: %s" % cmd) # Migrate diff -aurp kvm-autotest.orgi//client/tests/kvm_runtest_2/kvm_utils.py kvm-autotest/client/tests/kvm_runtest_2/kvm_utils.py --- kvm-autotest.orgi//client/tests/kvm_runtest_2/kvm_utils.py 2009-04-29 18:33:10.000000000 +0000 +++ kvm-autotest/client/tests/kvm_runtest_2/kvm_utils.py 2009-04-30 06:13:47.000000000 +0000 @@ -431,8 +431,7 @@ def remote_login(command, password, prom return None elif match == 2: # "login:" kvm_log.debug("Got unexpected login prompt") - sub.close() - return None + return sub elif match == 3: # "Connection closed" kvm_log.debug("Got 'Connection closed'") sub.close() diff -aurp kvm-autotest.orgi//client/tests/kvm_runtest_2/kvm_vm.py kvm-autotest/client/tests/kvm_runtest_2/kvm_vm.py --- kvm-autotest.orgi//client/tests/kvm_runtest_2/kvm_vm.py 2009-04-29 18:33:10.000000000 +0000 +++ kvm-autotest/client/tests/kvm_runtest_2/kvm_vm.py 2009-04-30 06:31:34.000000000 +0000 @@ -3,6 +3,7 @@ import time import socket import os +import re import kvm_utils import kvm_log @@ -105,6 +106,7 @@ class VM: self.qemu_path = qemu_path self.image_dir = image_dir self.iso_dir = iso_dir + self.remote = False def verify_process_identity(self): """Make sure .pid really points to the original qemu process. @@ -124,8 +126,6 @@ class VM: file.close() if not self.qemu_path in cmdline: return False - if not self.monitor_file_name in cmdline: - return False return True def make_qemu_command(self, name=None, params=None, qemu_path=None, image_dir=None, iso_dir=None): @@ -173,7 +173,6 @@ class VM: qemu_cmd = qemu_path qemu_cmd += " -name '%s'" % name - qemu_cmd += " -monitor unix:%s,server,nowait" % self.monitor_file_name for image_name in kvm_utils.get_sub_dict_names(params, "images"): image_params = kvm_utils.get_sub_dict(params, image_name) @@ -211,6 +210,7 @@ class VM: redir_params = kvm_utils.get_sub_dict(params, redir_name) guest_port = int(redir_params.get("guest_port")) host_port = self.get_port(guest_port) + self.ssh_port = host_port qemu_cmd += " -redir tcp:%s::%s" % (host_port, guest_port) if params.get("display") == "vnc": @@ -254,6 +254,17 @@ class VM: image_dir = self.image_dir iso_dir = self.iso_dir + # If VM is remote, set hostip to ip of the remote machine + # If VM is local set hostip to localhost or hostip param + if params.get("remote") == self.name: + self.remote = True + self.hostip = params.get("remoteip") + else: + self.remote = False + self.hostip = params.get("hostip","localhost") + + + # Verify the md5sum of the ISO image iso = params.get("cdrom") if iso: @@ -310,8 +321,28 @@ class VM: # Add -incoming option to the qemu command qemu_command += " -incoming tcp:0:%d" % self.migration_port - kvm_log.debug("Running qemu command:\n%s" % qemu_command) - (status, pid, output) = kvm_utils.run_bg(qemu_command, None, kvm_log.debug, "(qemu) ") + self.monitor_port = kvm_utils.find_free_port(5400, 6000) + qemu_command +=" -monitor tcp:0:%d,server,nowait" % self.monitor_port + + # If the VM is remote, get the username and password of remote host and lanch qemu + # command on the remote machine. + if self.remote: + remuser = params.get("remuser") + rempassword = params.get("rempassword") + sub = kvm_utils.ssh(self.hostip,22,remuser,rempassword,self.params.get("ssh_prompt", "[\#\$]")) + qemu_command +=" &" + kvm_log.debug("Running qemu command:\n%s" % qemu_command) + sub.sendline(qemu_command) + + (status,output) = sub.read_up_to_prompt() + if "Exit " in output: + status = int(re.findall("Exit\s(\d+)",output)[0]) + else: + pid = int(re.findall(".*] (\d+)",output)[0]) + status = 0 + else: + kvm_log.debug("Running qemu command:\n%s" % qemu_command) + (status, pid, output) = kvm_utils.run_bg(qemu_command, None, kvm_log.debug, "(qemu) ") if status: kvm_log.debug("qemu exited with status %d" % status) @@ -363,9 +394,8 @@ class VM: # Connect to monitor kvm_log.debug("Sending monitor command: %s" % command) try: - s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - s.setblocking(False) - s.connect(self.monitor_file_name) + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect((self.hostip,self.monitor_port)) except: kvm_log.debug("Could not connect to monitor socket") return (1, "") @@ -442,8 +472,9 @@ class VM: def is_alive(self): """Return True iff the VM's monitor is responsive.""" # Check if the process exists - if not kvm_utils.pid_exists(self.pid): - return False + if not self.remote: + if not kvm_utils.pid_exists(self.pid): + return False # Try sending a monitor command (status, output) = self.send_monitor_cmd("help") if status: @@ -468,7 +499,7 @@ class VM: address of its own). Otherwise return the guest's IP address. """ # Currently redirection is always used, so return 'localhost' - return "localhost" + return self.hostip def get_port(self, port): """Return the port in host space corresponding to port in guest space. @@ -486,7 +517,7 @@ class VM: def is_sshd_running(self, timeout=10): """Return True iff the guest's SSH port is responsive.""" address = self.get_address() - port = self.get_port(int(self.params.get("ssh_port"))) + port = self.ssh_port if not port: return False return kvm_utils.is_sshd_running(address, port, timeout=timeout) @@ -503,7 +534,7 @@ class VM: prompt = self.params.get("ssh_prompt", "[\#\$]") use_telnet = self.params.get("use_telnet") == "yes" address = self.get_address() - port = self.get_port(int(self.params.get("ssh_port"))) + port = self.ssh_port if not port: return None @@ -520,7 +551,7 @@ class VM: username = self.params.get("username", "") password = self.params.get("password", "") address = self.get_address() - port = self.get_port(int(self.params.get("ssh_port"))) + port = self.ssh_port if not port: return None return kvm_utils.scp_to_remote(address, port, username, password, local_path, remote_path, timeout) @@ -530,7 +561,7 @@ class VM: username = self.params.get("username", "") password = self.params.get("password", "") address = self.get_address() - port = self.get_port(int(self.params.get("ssh_port"))) + port = self.ssh_port if not port: return None return kvm_utils.scp_from_remote(address, port, username, password, remote_path, local_path, timeout)