From patchwork Sun Oct 24 11:01:09 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Goldish X-Patchwork-Id: 265442 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o9OB1RJ5008706 for ; Sun, 24 Oct 2010 11:01:28 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932489Ab0JXLBY (ORCPT ); Sun, 24 Oct 2010 07:01:24 -0400 Received: from mx1.redhat.com ([209.132.183.28]:26235 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932486Ab0JXLBX (ORCPT ); Sun, 24 Oct 2010 07:01:23 -0400 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o9OB1MVa012356 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Sun, 24 Oct 2010 07:01:22 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id o9OB1LLh000945; Sun, 24 Oct 2010 07:01:21 -0400 Received: from localhost.localdomain (dhcp-1-188.tlv.redhat.com [10.35.1.188]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id o9OB1BC8007247; Sun, 24 Oct 2010 07:01:20 -0400 From: Michael Goldish To: autotest@test.kernel.org, kvm@vger.kernel.org Cc: Michael Goldish Subject: [KVM-AUTOTEST PATCH 6/7] KVM test: refactor migration code Date: Sun, 24 Oct 2010 13:01:09 +0200 Message-Id: <1287918070-4579-6-git-send-email-mgoldish@redhat.com> In-Reply-To: <1287918070-4579-5-git-send-email-mgoldish@redhat.com> References: <1287918070-4579-1-git-send-email-mgoldish@redhat.com> <1287918070-4579-2-git-send-email-mgoldish@redhat.com> <1287918070-4579-3-git-send-email-mgoldish@redhat.com> <1287918070-4579-4-git-send-email-mgoldish@redhat.com> <1287918070-4579-5-git-send-email-mgoldish@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Sun, 24 Oct 2010 11:01:28 +0000 (UTC) diff --git a/client/tests/kvm/kvm_preprocessing.py b/client/tests/kvm/kvm_preprocessing.py index e3de0b3..1ddf99b 100644 --- a/client/tests/kvm/kvm_preprocessing.py +++ b/client/tests/kvm/kvm_preprocessing.py @@ -59,14 +59,8 @@ def preprocess_vm(test, params, env, name): kvm_utils.env_register_vm(env, name, vm) start_vm = False - for_migration = False - if params.get("start_vm_for_migration") == "yes": - logging.debug("'start_vm_for_migration' specified; (re)starting VM " - "with -incoming option...") - start_vm = True - for_migration = True - elif params.get("restart_vm") == "yes": + if params.get("restart_vm") == "yes": logging.debug("'restart_vm' specified; (re)starting VM...") start_vm = True elif params.get("start_vm") == "yes": @@ -81,7 +75,7 @@ def preprocess_vm(test, params, env, name): if start_vm: # Start the VM (or restart it if it's already up) - if not vm.create(name, params, test.bindir, for_migration): + if not vm.create(name, params, test.bindir): raise error.TestError("Could not start VM") else: # Don't start the VM, just update its params diff --git a/client/tests/kvm/kvm_test_utils.py b/client/tests/kvm/kvm_test_utils.py index d9c5a6e..1bb8920 100644 --- a/client/tests/kvm/kvm_test_utils.py +++ b/client/tests/kvm/kvm_test_utils.py @@ -167,79 +167,76 @@ def migrate(vm, env=None, mig_timeout=3600, mig_protocol="tcp", raise error.TestFail("Timeout expired while waiting for migration " "to finish") + dest_vm = vm.clone() - migration_file = os.path.join("/tmp/", - mig_protocol + time.strftime("%Y%m%d-%H%M%S")) - if mig_protocol == "tcp": - mig_extra_params = " -incoming tcp:0:%d" - elif mig_protocol == "unix": - mig_extra_params = " -incoming unix:%s" - elif mig_protocol == "exec": + if mig_protocol == "exec": # Exec is a little different from other migrate methods - first we # ask the monitor the migration, then the vm state is dumped to a # compressed file, then we start the dest vm with -incoming pointing # to it - mig_extra_params = " -incoming \"exec: gzip -c -d %s\"" % migration_file - uri = "\"exec:gzip -c > %s\"" % migration_file - vm.monitor.cmd("stop") - o = vm.monitor.migrate(uri) - wait_for_migration() - - # Clone the source VM and ask the clone to wait for incoming migration - dest_vm = vm.clone() - if not dest_vm.create(extra_params=mig_extra_params, mac_source=vm): - raise error.TestError("Could not create dest VM") - - try: - if mig_protocol == "tcp": - uri = "tcp:localhost:%d" % dest_vm.migration_port - elif mig_protocol == "unix": - uri = "unix:%s" % dest_vm.migration_file + try: + exec_file = "/tmp/exec-%s.gz" % kvm_utils.generate_random_string(8) + exec_cmd = "gzip -c -d %s" % exec_file + uri = '"exec:gzip -c > %s"' % exec_file + vm.monitor.cmd("stop") + vm.monitor.migrate(uri) + wait_for_migration() - if mig_protocol != "exec": - o = vm.monitor.migrate(uri) + if not dest_vm.create(migration_mode=mig_protocol, + migration_exec_cmd=exec_cmd, mac_source=vm): + raise error.TestError("Could not create dest VM") + finally: + logging.debug("Removing migration file %s", exec_file) + try: + os.remove(exec_file) + except OSError: + pass + else: + if not dest_vm.create(migration_mode=mig_protocol, mac_source=vm): + raise error.TestError("Could not create dest VM") + try: + if mig_protocol == "tcp": + uri = "tcp:localhost:%d" % dest_vm.migration_port + elif mig_protocol == "unix": + uri = "unix:%s" % dest_vm.migration_file + vm.monitor.migrate(uri) - if mig_protocol == "tcp" and mig_cancel: + if mig_cancel: time.sleep(2) - o = vm.monitor.cmd("migrate_cancel") + vm.monitor.cmd("migrate_cancel") if not kvm_utils.wait_for(mig_cancelled, 60, 2, 2, - "Waiting for migration cancel"): - raise error.TestFail("Fail to cancel migration") + "Waiting for migration " + "cancellation"): + raise error.TestFail("Failed to cancel migration") dest_vm.destroy(gracefully=False) return vm + else: + wait_for_migration() + except: + dest_vm.destroy() + raise + + # Report migration status + if mig_succeeded(): + logging.info("Migration finished successfully") + elif mig_failed(): + raise error.TestFail("Migration failed") + else: + raise error.TestFail("Migration ended with unknown status") - wait_for_migration() - - # Report migration status - if mig_succeeded(): - logging.info("Migration finished successfully") - elif mig_failed(): - raise error.TestFail("Migration failed") - else: - raise error.TestFail("Migration ended with unknown status") - - o = dest_vm.monitor.info("status") - if "paused" in o: - logging.debug("Destination VM is paused, resuming it...") - dest_vm.monitor.cmd("cont") - - if os.path.exists(migration_file): - logging.debug("Removing migration file %s", migration_file) - os.remove(migration_file) - - # Kill the source VM - vm.destroy(gracefully=False) + if "paused" in dest_vm.monitor.info("status"): + logging.debug("Destination VM is paused, resuming it...") + dest_vm.monitor.cmd("cont") - # Replace the source VM with the new cloned VM - if env is not None: - kvm_utils.env_register_vm(env, vm.name, dest_vm) + # Kill the source VM + vm.destroy(gracefully=False) - # Return the new cloned VM - return dest_vm + # Replace the source VM with the new cloned VM + if env is not None: + kvm_utils.env_register_vm(env, vm.name, dest_vm) - except: - dest_vm.destroy() - raise + # Return the new cloned VM + return dest_vm def get_time(session, time_command, time_filter_re, time_format): diff --git a/client/tests/kvm/kvm_vm.py b/client/tests/kvm/kvm_vm.py index a5c110c..a860437 100755 --- a/client/tests/kvm/kvm_vm.py +++ b/client/tests/kvm/kvm_vm.py @@ -507,23 +507,20 @@ class VM: return qemu_cmd - def create(self, name=None, params=None, root_dir=None, - for_migration=False, timeout=5.0, extra_params=None, - mac_source=None): + def create(self, name=None, params=None, root_dir=None, timeout=5.0, + migration_mode=None, migration_exec_cmd=None, mac_source=None): """ Start the VM by running a qemu command. - All parameters are optional. The following applies to all parameters - but for_migration: If a parameter is not supplied, the corresponding - value stored in the class attributes is used, and if it is supplied, - it is stored for later use. + All parameters are optional. If name, params or root_dir are not + supplied, the respective values stored as class attributes are used. @param name: The name of the object @param params: A dict containing VM params @param root_dir: Base directory for relative filenames - @param for_migration: If True, start the VM with the -incoming - option - @param extra_params: extra params for qemu command.e.g -incoming option - Please use this parameter instead of for_migration. + @param migration_mode: If supplied, start VM for incoming migration + using this protocol (either 'tcp', 'unix' or 'exec') + @param migration_exec_cmd: Command to embed in '-incoming "exec: ..."' + (e.g. 'gzip -c -d filename') if migration_mode is 'exec' @param mac_source: A VM object from which to copy MAC addresses. If not specified, new addresses will be generated. """ @@ -655,17 +652,15 @@ class VM: # Make qemu command qemu_command = self.make_qemu_command() - # Enable migration support for VM by adding extra_params. - if extra_params is not None: - if " -incoming tcp:0:%d" == extra_params: - self.migration_port = kvm_utils.find_free_port(5200, 6000) - qemu_command += extra_params % self.migration_port - elif " -incoming unix:%s" == extra_params: - self.migration_file = os.path.join("/tmp/", "unix-" + - time.strftime("%Y%m%d-%H%M%S")) - qemu_command += extra_params % self.migration_file - else: - qemu_command += extra_params + # Add migration parameters if required + if migration_mode == "tcp": + self.migration_port = kvm_utils.find_free_port(5200, 6000) + qemu_command += " -incoming tcp:0:%d" % self.migration_port + elif migration_mode == "unix": + self.migration_file = "/tmp/migration-unix-%s" % self.instance + qemu_command += " -incoming unix:%s" % self.migration_file + elif migration_mode == "exec": + qemu_command += ' -incoming "exec:%s"' % migration_exec_cmd logging.debug("Running qemu command:\n%s", qemu_command) self.process = kvm_subprocess.run_bg(qemu_command, None, @@ -826,6 +821,11 @@ class VM: os.unlink(f) except OSError: pass + if hasattr(self, "migration_file"): + try: + os.unlink(self.migration_file) + except OSError: + pass num_nics = len(kvm_utils.get_sub_dict_names(self.params, "nics")) for vlan in range(num_nics): self.free_mac_address(vlan)