From patchwork Mon Jun 15 12:16:36 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Goldish X-Patchwork-Id: 30305 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n5FCE8AE015603 for ; Mon, 15 Jun 2009 12:14:09 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1759551AbZFOMNh (ORCPT ); Mon, 15 Jun 2009 08:13:37 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1757983AbZFOMNg (ORCPT ); Mon, 15 Jun 2009 08:13:36 -0400 Received: from mx2.redhat.com ([66.187.237.31]:36637 "EHLO mx2.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756789AbZFOMNf (ORCPT ); Mon, 15 Jun 2009 08:13:35 -0400 Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id n5FCDbqc007599; Mon, 15 Jun 2009 08:13:37 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx2.corp.redhat.com (8.13.1/8.13.1) with ESMTP id n5FCDasP022351; Mon, 15 Jun 2009 08:13:37 -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 n5FCDVWV012172; Mon, 15 Jun 2009 08:13:35 -0400 From: Michael Goldish To: autotest@test.kernel.org, kvm@vger.kernel.org Cc: Michael Goldish Subject: [KVM-AUTOTEST PATCH 2/5] Modify kvm_vm and kvm_preprocessing to use the new kvm_subprocess module Date: Mon, 15 Jun 2009 15:16:36 +0300 Message-Id: In-Reply-To: <1139ad1a2cb9e1f86a7269feecc186114aeb5451.1245067920.git.mgoldish@redhat.com> References: <1245068199-25679-1-git-send-email-mgoldish@redhat.com> <1139ad1a2cb9e1f86a7269feecc186114aeb5451.1245067920.git.mgoldish@redhat.com> In-Reply-To: <1139ad1a2cb9e1f86a7269feecc186114aeb5451.1245067920.git.mgoldish@redhat.com> References: <1139ad1a2cb9e1f86a7269feecc186114aeb5451.1245067920.git.mgoldish@redhat.com> X-Scanned-By: MIMEDefang 2.58 on 172.16.27.26 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Signed-off-by: Michael Goldish --- client/tests/kvm/kvm_preprocessing.py | 17 +----- client/tests/kvm/kvm_vm.py | 103 +++++++++++++-------------------- 2 files changed, 44 insertions(+), 76 deletions(-) diff --git a/client/tests/kvm/kvm_preprocessing.py b/client/tests/kvm/kvm_preprocessing.py index f60cfe8..7fac46a 100644 --- a/client/tests/kvm/kvm_preprocessing.py +++ b/client/tests/kvm/kvm_preprocessing.py @@ -1,7 +1,7 @@ import sys, os, time, commands, re, logging from autotest_lib.client.bin import test from autotest_lib.client.common_lib import error -import kvm_vm, kvm_utils +import kvm_vm, kvm_utils, kvm_subprocess def preprocess_image(test, params): @@ -167,17 +167,6 @@ def preprocess(test, params, env): @param params: A dict containing all VM and image parameters. @param env: The environment (a dict-like object). """ - # Verify the identities of all living VMs - for vm in env.values(): - if not kvm_utils.is_vm(vm): - continue - if vm.is_dead(): - continue - if not vm.verify_process_identity(): - logging.debug("VM '%s' seems to have been replaced by another" - " process" % vm.name) - vm.pid = None - # Destroy and remove VMs that are no longer needed in the environment requested_vms = kvm_utils.get_sub_dict_names(params, "vms") for key in env.keys(): @@ -239,8 +228,8 @@ def postprocess(test, params, env): # Remove them all logging.debug("'keep_ppm_files' not specified; removing all PPM files" " from results dir...") - kvm_utils.run_bg("rm -vf %s" % os.path.join(test.debugdir, "*.ppm"), - None, logging.debug, "(rm) ", timeout=5.0) + rm_cmd = "rm -vf %s" % os.path.join(test.debugdir, "*.ppm") + kvm_subprocess.run_fg(rm_cmd, logging.debug, "(rm) ", timeout=5.0) def postprocess_on_error(test, params, env): diff --git a/client/tests/kvm/kvm_vm.py b/client/tests/kvm/kvm_vm.py index 5028161..9aea3fb 100644 --- a/client/tests/kvm/kvm_vm.py +++ b/client/tests/kvm/kvm_vm.py @@ -1,6 +1,6 @@ #!/usr/bin/python import time, socket, os, logging, fcntl -import kvm_utils +import kvm_utils, kvm_subprocess """ Utility classes and functions to handle Virtual Machine creation using qemu. @@ -54,17 +54,22 @@ def create_image(params, qemu_img_path, image_dir): qemu_img_cmd += " %s" % size logging.debug("Running qemu-img command:\n%s" % qemu_img_cmd) - (status, pid, output) = kvm_utils.run_bg(qemu_img_cmd, None, - logging.debug, "(qemu-img) ", - timeout=30) + (status, output) = kvm_subprocess.run_fg(qemu_img_cmd, logging.debug, + "(qemu-img) ", timeout=30) - if status: - logging.debug("qemu-img exited with status %d" % status) - logging.error("Could not create image %s" % image_filename) + if status is None: + logging.error("Timeout elapsed while waiting for qemu-img command " + "to complete:\n%s" % qemu_img_cmd) + return None + elif status != 0: + logging.error("Could not create image; " + "qemu-img command failed:\n%s" % qemu_img_cmd) + logging.error("Status: %s" % status) + logging.error("Output:" + kvm_utils.format_str_for_message(output)) return None if not os.path.exists(image_filename): - logging.debug("Image file does not exist for some reason") - logging.error("Could not create image %s" % image_filename) + logging.error("Image could not be created for some reason; " + "qemu-img command:\n%s" % qemu_img_cmd) return None logging.info("Image created in %s" % image_filename) @@ -106,7 +111,7 @@ class VM: @param image_dir: The directory where images reside @param iso_dir: The directory where ISOs reside """ - self.pid = None + self.process = None self.name = name self.params = params @@ -153,28 +158,6 @@ class VM: return VM(name, params, qemu_path, image_dir, iso_dir) - def verify_process_identity(self): - """ - Make sure .pid really points to the original qemu process. If .pid - points to the same process that was created with the create method, - or to a dead process, return True. Otherwise return False. - """ - if self.is_dead(): - return True - filename = "/proc/%d/cmdline" % self.pid - if not os.path.exists(filename): - logging.debug("Filename %s does not exist" % filename) - return False - file = open(filename) - cmdline = file.read() - 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): """ @@ -378,25 +361,26 @@ class VM: qemu_command += " -incoming tcp:0:%d" % self.migration_port logging.debug("Running qemu command:\n%s", qemu_command) - (status, pid, output) = kvm_utils.run_bg(qemu_command, None, - logging.debug, "(qemu) ") - - if status: - logging.debug("qemu exited with status %d", status) - logging.error("VM could not be created -- qemu command" - " failed:\n%s", qemu_command) + self.process = kvm_subprocess.run_bg(qemu_command, None, + logging.debug, "(qemu) ") + + if not self.process.is_alive(): + logging.error("VM could not be created; " + "qemu command failed:\n%s" % qemu_command) + logging.error("Status: %s" % self.process.get_status()) + logging.error("Output:" + kvm_utils.format_str_for_message( + self.process.get_output())) + self.destroy() return False - self.pid = pid - if not kvm_utils.wait_for(self.is_alive, timeout, 0, 1): - logging.debug("VM is not alive for some reason") - logging.error("VM could not be created with" - " command:\n%s", qemu_command) + logging.error("VM is not alive for some reason; " + "qemu command:\n%s" % qemu_command) self.destroy() return False - logging.debug("VM appears to be alive with PID %d", self.pid) + logging.debug("VM appears to be alive with PID %d", + self.process.get_pid()) return True finally: @@ -495,9 +479,11 @@ class VM: # Is it already dead? if self.is_dead(): logging.debug("VM is already down") + if self.process: + self.process.close() return - logging.debug("Destroying VM with PID %d..." % self.pid) + logging.debug("Destroying VM with PID %d..." % self.process.get_pid()) if gracefully and self.params.get("cmd_shutdown"): # Try to destroy with SSH command @@ -510,7 +496,7 @@ class VM: "down...") if kvm_utils.wait_for(self.is_dead, 60, 1, 1): logging.debug("VM is down") - self.pid = None + self.process.close() return # Try to destroy with a monitor command @@ -521,28 +507,21 @@ class VM: # Wait for the VM to be really dead if kvm_utils.wait_for(self.is_dead, 5, 0.5, 0.5): logging.debug("VM is down") - self.pid = None + self.process.close() return # If the VM isn't dead yet... - logging.debug("Cannot quit normally; Sending a kill to close the" - " deal...") - kvm_utils.safe_kill(self.pid, 9) - # Wait for the VM to be really dead - if kvm_utils.wait_for(self.is_dead, 5, 0.5, 0.5): - logging.debug("VM is down") - self.pid = None - return - - logging.error("We have a zombie! PID %d is a zombie!" % self.pid) + logging.debug("Cannot quit normally; Sending a kill to close the " + "deal...") + self.process.close(9) def is_alive(self): """ Return True if the VM's monitor is responsive. """ - # Check if the process exists - if not kvm_utils.pid_exists(self.pid): + # Check if the process is running + if self.is_dead(): return False # Try sending a monitor command (status, output) = self.send_monitor_cmd("help") @@ -553,9 +532,9 @@ class VM: def is_dead(self): """ - Return True iff the VM's PID does not exist. + Return True if the qemu process is dead. """ - return not kvm_utils.pid_exists(self.pid) + return not self.process or not self.process.is_alive() def get_params(self):