Hello everyone, I like to resubmit patch to add support for "remote migration" in kvm-autotest, based on Michael Goldish's suggestions.
To use this patch the following seven parameters should be added to the existing migration test remote_dst = yes hostip = <localhost ip or name> remoteip = <remote host ip or name> remuser = root rempassword = <password> qemu_path_dst = <qemu binary path on remote host> image_dir_dst = <images dir on remote host> For example: - migrate: install setup type = migration vms += " dst" migration_test_command = help kill_vm_on_error = yes hostip = 192.168.1.2 remoteip = 192.168.1.3 remuser = root rempassword = 123456 remote_dst = yes qemu_path_dst = /tmp/kvm_autotest_root/qemu image_dir_dst = /tmp/kvm_autotest_root/images variants: The parameter "remote_dst = yes", indicates that the VM "dst" should be started on the remote host.If the parameter qemu_path_dst and image_dir_dst, it is assumed tht the qemu binary images path is same on both local and remote host. > Regarding remote_login: > > - Why should remote_login return a session when it gets an unexpected login > prompt? If you get a login prompt doesn't that mean something went wrong? The > username is always provided in the ssh command line, so we shouldn't expect > to receive a login prompt -- or am I missing something? I am pretty confident > this is true in the general case, but maybe it's different when ssh keys have > been exchanged between the hosts. > > - I think it makes little sense to return a session object when you see a > login prompt because that session will be useless. You can't send any > commands to it because you don't have a shell prompt yet. Any command you > send will be interpreted as a username, and will most likely be the wrong > username. > > - When a guest is in the process of booting and we try to log into it, > remote_login sometimes fails because it gets an unexpected login prompt. This > is good, as far as I understand, because it means the guest isn't ready yet > (still booting). The next time remote_login attempts to log in, it usually > succeeds. If we consider an unexpected login prompt OK, we pass login > attempts that actually should have failed (and the resulting sessions will be > useless anyway). > I have removed this from the current patch, so now the remote_login function is unchanged.I will recheck my machine configuration and submit it as new patch if necessary. I had exchanged ssh keys between the hosts(both local and remote hosts), but the login sessions seem to terminates with "Got unexpected login prompt". > Other things: > > - If I understand correctly, remote migration will only work if the remote > qemu binary path is exactly the same as the local one. Maybe we should > receive a qemu path parameter that will allow for some flexibility. update the patch with this option by providing 2 new parameters qemu_path_dst and image_dir_dst > - In VM.make_qemu_command(), in the code that handles redirections, you add > 'self.ssh_port = host_port'. I don't think this is correct because there can > be multiple redirections, unrelated to SSH, so you certainly shouldn't assume > that the only redirection is an SSH one. When you want the host port > redirected to the guest's SSH port, you should use > self.get_port(int(self.params.get("ssh_port"))). This will also work if for > some reason 'ssh_port' changes while the guest is alive. yes,should not have done that. So also removed it from this patch > - It seems that the purpose of 'remote = dst' is to indicate to 'dst' that it > should be started as a remote VM. The preferred way to do this is to pass > something like 'remote_dst = yes' and then in VM.create() you can test for > params.get("remote") == "yes". See "Addressing objects" in the wiki > (http://www.linux-kvm.org/page/KVM-Autotest/Parameters#Addressing_objects_.28VMs.2C_images.2C_NICs_etc.29). > In general, any parameter you want to pass to a specific VM, you pass using > <param>_<vmname> = <value>, e.g. 'mem_dst = 128', and then in VM.create() the > parameter is accessible without the VM name extension (e.g. > self.params.get("mem") will equal "128"). updated the patch with the above suggestion Thank you,for your suggestion Michael, they were very helpful(srry i took so long to reply,was traveling,so was not able to reply and resubmit the patch). Thx yogi
kvm_tests.py | 2 +- kvm_vm.py | 54 +++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 44 insertions(+), 12 deletions(-) Signed-off-by: Yogananth Subramanian <anant...@in.ibm.com> --- 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_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-05-04 09:06:32.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) @@ -254,6 +253,19 @@ 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") == "yes": + self.remote = True + self.hostip = params.get("remoteip") + self.qemu_path = params.get("qemu_path",qemu_path) + qemu_path = self.qemu_path + self.image_dir = params.get("image_dir",image_dir) + image_dir = self.image_dir + 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 +322,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 +395,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 +473,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 +500,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.