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 <[email protected]>
---
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.