From patchwork Mon Jul 20 15:07:09 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Goldish X-Patchwork-Id: 36342 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 n6KF4Jux016769 for ; Mon, 20 Jul 2009 15:04:19 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751897AbZGTPDT (ORCPT ); Mon, 20 Jul 2009 11:03:19 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751913AbZGTPDT (ORCPT ); Mon, 20 Jul 2009 11:03:19 -0400 Received: from mx2.redhat.com ([66.187.237.31]:59902 "EHLO mx2.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751883AbZGTPDP (ORCPT ); Mon, 20 Jul 2009 11:03:15 -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 n6KF3FfP000492; Mon, 20 Jul 2009 11:03:15 -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 n6KF3Emr025137; Mon, 20 Jul 2009 11:03:14 -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 n6KF39lF007669; Mon, 20 Jul 2009 11:03:13 -0400 From: Michael Goldish To: autotest@test.kernel.org, kvm@vger.kernel.org Cc: Michael Goldish Subject: [KVM-AUTOTEST PATCH 02/17] Modify kvm_vm and kvm_preprocessing to use the new kvm_subprocess module Date: Mon, 20 Jul 2009 18:07:09 +0300 Message-Id: <4980fdb4f9630c89ba21bd4af49a3b7626fb29f1.1248102188.git.mgoldish@redhat.com> In-Reply-To: References: <1248102444-31111-1-git-send-email-mgoldish@redhat.com> In-Reply-To: References: 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 | 27 ++------ client/tests/kvm/kvm_vm.py | 111 +++++++++++++++----------------- 2 files changed, 59 insertions(+), 79 deletions(-) diff --git a/client/tests/kvm/kvm_preprocessing.py b/client/tests/kvm/kvm_preprocessing.py index 80d7be8..7b97f00 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, signal 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): @@ -75,7 +75,7 @@ def preprocess_vm(test, params, env, name): qemu_path, image_dir, iso_dir): - logging.debug("VM's qemu command differs from requested one;" + logging.debug("VM's qemu command differs from requested one; " "restarting it...") start_vm = True @@ -158,13 +158,11 @@ def process_command(test, params, env, command, command_timeout, # execute command logging.info("Executing command '%s'..." % command) timeout = int(command_timeout) - (status, pid, output) = kvm_utils.run_bg("cd %s; %s" % (test.bindir, + (status, output) = kvm_subprocess.run_fg("cd %s; %s" % (test.bindir, command), - None, logging.debug, - "(command) ", - timeout = timeout) + logging.debug, "(command) ", + timeout=timeout) if status != 0: - kvm_utils.safe_kill(pid, signal.SIGTERM) logging.warn("Custom processing command failed: '%s'..." % command) if command_noncritical != "yes": raise error.TestError("Custom processing command failed") @@ -204,17 +202,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(): @@ -282,8 +269,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) #execute any post_commands if params.get("post_command"): diff --git a/client/tests/kvm/kvm_vm.py b/client/tests/kvm/kvm_vm.py index 48f2916..8bc2403 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.uuid = None self.name = name @@ -154,28 +159,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): """ @@ -394,25 +377,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: @@ -511,9 +495,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 @@ -521,12 +507,11 @@ class VM: (status, output) = self.ssh(self.params.get("cmd_shutdown")) # Was the command sent successfully? if status == 0: - #if self.ssh(self.params.get("cmd_shutdown")): - logging.debug("Shutdown command sent; Waiting for VM to go" + logging.debug("Shutdown command sent; waiting for VM to go " "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 @@ -537,28 +522,29 @@ 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) + logging.debug("Cannot quit normally; sending a kill to close the " + "deal...") + kvm_utils.safe_kill(self.process.get_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 + self.process.close() return - logging.error("We have a zombie! PID %d is a zombie!" % self.pid) + logging.error("Process %s is a zombie!" % self.process.get_pid()) + self.process.close() 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") @@ -569,9 +555,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): @@ -610,6 +596,13 @@ class VM: return None + def get_pid(self): + """ + Return the VM's PID. + """ + return self.process.get_pid() + + def is_sshd_running(self, timeout=10): """ Return True iff the guest's SSH port is responsive.