[Tools 2/4] testbot: Make it possible to power off VMs using LibvirtTool.

Francois Gouget fgouget at codeweavers.com
Wed Oct 18 13:14:32 CDT 2017


Signed-off-by: Francois Gouget <fgouget at codeweavers.com>
---

Patches 2 to 4 remove the last Libvirt calls from the TestBot server 
which ensures will not get stuck in case there's no response from the 
Libvirt server (e.g. due to network issues).

This patch just introduces the LibvirtTool code which remains unused 
until the following patches invoke it to power off the VMs in the job 
scheduler and Engine initialization respectively.

 testbot/bin/LibvirtTool.pl      | 26 +++++++++++++-----
 testbot/lib/WineTestBot/Jobs.pm |  3 ++-
 testbot/lib/WineTestBot/VMs.pm  | 60 +++++++++++++++++++++++++++++++++++------
 3 files changed, 74 insertions(+), 15 deletions(-)

diff --git a/testbot/bin/LibvirtTool.pl b/testbot/bin/LibvirtTool.pl
index 6aaaf82b..64f0575b 100755
--- a/testbot/bin/LibvirtTool.pl
+++ b/testbot/bin/LibvirtTool.pl
@@ -1,9 +1,9 @@
 #!/usr/bin/perl -Tw
 # -*- Mode: Perl; perl-indent-level: 2; indent-tabs-mode: nil -*-
 #
-# Reverts a VM so that it is ready to run jobs.
-# This operation can take quite a bit of time, particularly in case of
-# network trouble, and thus is best performed in a separate process.
+# Performs poweroff and revert operations on the specified VM.
+# These operations can take quite a bit of time, particularly in case of
+# network trouble, and thus are best performed in a separate process.
 #
 # Copyright 2009 Ge van Geldorp
 # Copyright 2012-2017 Francois Gouget
@@ -104,7 +104,7 @@ while (@ARGV)
   {
     $LogOnly = 1;
   }
-  elsif ($Arg eq "revert")
+  elsif ($Arg =~ /^(?:poweroff|revert)$/)
   {
     $Action = $Arg;
   }
@@ -163,7 +163,7 @@ if (!defined $Usage)
 }
 if (defined $Usage)
 {
-  print "Usage: $Name0 [--debug] [--log-only] [--help] revert VMName\n";
+  print "Usage: $Name0 [--debug] [--log-only] [--help] (poweroff|revert) VMName\n";
   exit $Usage;
 }
 
@@ -251,6 +251,16 @@ sub ChangeStatus($$;$)
   return 0;
 }
 
+sub PowerOff()
+{
+  # Power off VMs no matter what their initial status is
+  $CurrentStatus = $VM->Status;
+  my $ErrMessage = $VM->GetDomain()->PowerOff(1);
+  FatalError("$ErrMessage\n") if (defined $ErrMessage);
+
+  return ChangeStatus(undef, "off", "done");
+}
+
 sub Revert()
 {
   my $VM = CreateVMs()->GetItem($VMKey);
@@ -308,7 +318,11 @@ sub Revert()
 
 
 my $Rc;
-if ($Action eq "revert")
+if ($Action eq "poweroff")
+{
+  $Rc = PowerOff();
+}
+elsif ($Action eq "revert")
 {
   $Rc = Revert();
 }
diff --git a/testbot/lib/WineTestBot/Jobs.pm b/testbot/lib/WineTestBot/Jobs.pm
index c26ff928..26538fa0 100644
--- a/testbot/lib/WineTestBot/Jobs.pm
+++ b/testbot/lib/WineTestBot/Jobs.pm
@@ -562,7 +562,8 @@ sub ScheduleOnHost($$$)
           $SleepingCount++;
           $PrepareNextStep = 1;
         }
-        elsif ($VMStatus eq "off" || $VMStatus eq "dirty")
+        elsif (($VMStatus eq "off" or $VMStatus eq "dirty") and
+               !$VM->HasRunningChild())
         {
           $RevertNiceness++;
           $VMsToRevert{$VMKey} = $RevertNiceness;
diff --git a/testbot/lib/WineTestBot/VMs.pm b/testbot/lib/WineTestBot/VMs.pm
index 86dee6c8..a6b2a8b3 100644
--- a/testbot/lib/WineTestBot/VMs.pm
+++ b/testbot/lib/WineTestBot/VMs.pm
@@ -241,7 +241,7 @@ Returns true if the VM status is compatible with ChildPid being set.
 sub CanHaveChild($)
 {
   my ($self) = @_;
-  return ($self->Status =~ /^(?:reverting|sleeping)$/);
+  return ($self->Status =~ /^(?:dirty|reverting|sleeping)$/);
 }
 
 =pod
@@ -307,12 +307,12 @@ sub OnSaved($)
   }
 }
 
-sub RunRevert($)
+sub _RunVMTool($$$)
 {
-  my ($self) = @_;
+  my ($self, $NewStatus, $Args) = @_;
 
   my $Tool = "LibvirtTool.pl";
-  my $Args = ["$BinDir/$Tool", "--log-only", "revert", $self->GetKey()];
+  unshift @$Args, "$BinDir/$Tool";
 
   # There are two $VM->ChildPid race conditions to avoid:
   # - Between the child process and new calls to ScheduleJobs().
@@ -321,8 +321,8 @@ sub RunRevert($)
   #   which would result in a new child being started.
   #   Note that the status is not guaranteed to change in _RunVMTool() so it
   #   cannot be relied on to avoid this race.
-  # - Between RunRevert() and the exit of the child process.
-  #   The child process may exit before RunRevert() gets around to setting
+  # - Between _RunVMTool() and the exit of the child process.
+  #   The child process may exit before _RunVMTool() gets around to setting
   #   ChildPid after the fork(). This would result in ChildPid remaining set
   #   indefinitely.
   # So set ChildPid in the parent and synchronize with the child so it only
@@ -347,7 +347,7 @@ sub RunRevert($)
     close($fd_read);
 
     # Set the Status and ChildPid
-    $self->Status("reverting");
+    $self->Status($NewStatus);
     $self->ChildPid($Pid);
     my ($ErrProperty, $ErrMessage) = $self->Save();
     if ($ErrMessage)
@@ -396,6 +396,51 @@ sub RunRevert($)
   exit 1;
 }
 
+=pod
+=over 12
+
+=item C<RunPowerOff()>
+
+Powers off the VM so that it stops using resources.
+
+The power off need not perform a clean shut down of the guest OS.
+This operation can take a long time so it is performed in a separate process.
+
+=back
+=cut
+
+sub RunPowerOff($)
+{
+  my ($self) = @_;
+  # This can be used to power off VMs from any state, including 'idle' but we
+  # don't want the job scheduler to think it can use the VM while it is being
+  # powered off. So force the status to dirty.
+  return $self->_RunVMTool("dirty", ["--log-only", "poweroff", $self->GetKey()]);
+}
+
+=pod
+=over 12
+
+=item C<RunRevert()>
+
+Reverts the VM so that it is ready to run jobs.
+
+Note that in addition to the hypervisor revert operation this implies checking
+that it responds to our commands ($WaitForToolsInVM) and possibly letting the
+VM settle down ($SleepAfterRevert). If this operation fails the administrator
+is notified and the VM is marked as offline.
+
+This operation can take a long time so it is performed in a separate process.
+
+=back
+=cut
+
+sub RunRevert($)
+{
+  my ($self) = @_;
+  return $self->_RunVMTool("reverting", ["--log-only", "revert", $self->GetKey()]);
+}
+
 
 package WineTestBot::VMs;
 
@@ -430,7 +475,6 @@ BEGIN
     CreateEnumPropertyDescriptor("Type", "Type of VM", !1, 1, ['win32', 'win64', 'build']),
     CreateEnumPropertyDescriptor("Role", "VM Role", !1, 1, ['extra', 'base', 'winetest', 'retired', 'deleted']),
     CreateEnumPropertyDescriptor("Status", "Current status", !1, 1, ['dirty', 'reverting', 'sleeping', 'idle', 'running', 'off', 'offline', 'maintenance']),
-    # Note: ChildPid is only valid when Status == 'reverting' or 'sleeping'.
     CreateBasicPropertyDescriptor("ChildPid", "Child process id", !1, !1, "N", 5),
     CreateBasicPropertyDescriptor("VirtURI", "LibVirt URI of the VM", !1, 1, "A", 64),
     CreateBasicPropertyDescriptor("VirtDomain", "LibVirt Domain for the VM", !1, 1, "A", 32),
-- 
2.14.2




More information about the wine-patches mailing list