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 <[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_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)