diff mbox

[KVM-AUTOTEST,02/17] Modify kvm_vm and kvm_preprocessing to use the new kvm_subprocess module

Message ID 4980fdb4f9630c89ba21bd4af49a3b7626fb29f1.1248102188.git.mgoldish@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Michael Goldish July 20, 2009, 3:07 p.m. UTC
Signed-off-by: Michael Goldish <mgoldish@redhat.com>
---
 client/tests/kvm/kvm_preprocessing.py |   27 ++------
 client/tests/kvm/kvm_vm.py            |  111 +++++++++++++++-----------------
 2 files changed, 59 insertions(+), 79 deletions(-)

Comments

Lucas Meneghel Rodrigues July 23, 2009, 1:37 a.m. UTC | #1
Looks good to me. Applied.

On Mon, Jul 20, 2009 at 12:07 PM, Michael Goldish<mgoldish@redhat.com> wrote:
> Signed-off-by: Michael Goldish <mgoldish@redhat.com>
> ---
>  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.
> --
> 1.5.4.1
>
> _______________________________________________
> Autotest mailing list
> Autotest@test.kernel.org
> http://test.kernel.org/cgi-bin/mailman/listinfo/autotest
>
diff mbox

Patch

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.