Francois Gouget : testbot/LibvirtTool: Create live snapshots as needed.

Alexandre Julliard julliard at winehq.org
Tue Sep 24 11:41:03 CDT 2019


Module: tools
Branch: master
Commit: 6c6525ed9cae006e82196c35d0ac29e583356c84
URL:    https://source.winehq.org/git/tools.git/?a=commit;h=6c6525ed9cae006e82196c35d0ac29e583356c84

Author: Francois Gouget <fgouget at codeweavers.com>
Date:   Tue Sep 24 11:10:05 2019 +0200

testbot/LibvirtTool: Create live snapshots as needed.

Live snapshots have to save the content of the VM's memory which takes
space in the disk image. They may also be specific to the host they
are running on (e.g. AMD vs. Intel CPU). And they may need to be
recreated after QEmu upgrades.
So VMs always have a powered off snapshot as reference and backups
made from the powered off state. With VMs that are configured for
autologin and autostart of TestAgentd this patch removes the need for
the administrator to manually recreate the live snapshots.

Signed-off-by: Francois Gouget <fgouget at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 testbot/bin/LibvirtTool.pl               | 85 +++++++++++++++++++++++++++-----
 testbot/lib/WineTestBot/Config.pm        |  7 ++-
 testbot/lib/WineTestBot/LibvirtDomain.pm |  5 +-
 3 files changed, 79 insertions(+), 18 deletions(-)

diff --git a/testbot/bin/LibvirtTool.pl b/testbot/bin/LibvirtTool.pl
index dd330a5..72075ae 100755
--- a/testbot/bin/LibvirtTool.pl
+++ b/testbot/bin/LibvirtTool.pl
@@ -6,7 +6,7 @@
 # network trouble, and thus are best performed in a separate process.
 #
 # Copyright 2009 Ge van Geldorp
-# Copyright 2012-2017 Francois Gouget
+# Copyright 2012-2019 Francois Gouget
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -382,6 +382,25 @@ sub SetupTestAgentd($$)
   $TA->Disconnect();
 }
 
+sub CreateSnapshot($$)
+{
+  my ($Domain, $SnapshotName) = @_;
+
+  if ($SleepAfterBoot != 0)
+  {
+    Debug(Elapsed($Start), " Sleeping for the $SnapshotName snapshot\n");
+    LogMsg "Letting $VMKey settle down for the $SnapshotName snapshot\n";
+    sleep($SleepAfterBoot);
+  }
+
+  Debug(Elapsed($Start), " Creating the $SnapshotName snapshot\n");
+  my $ErrMessage = $Domain->CreateSnapshot($SnapshotName);
+  if (defined $ErrMessage)
+  {
+    FatalError("Could not recreate the $SnapshotName snapshot on $VMKey: $ErrMessage\n");
+  }
+}
+
 sub Revert()
 {
   my $VM = CreateVMs()->GetItem($VMKey);
@@ -391,11 +410,34 @@ sub Revert()
     return 1;
   }
   $CurrentStatus = "reverting";
+  my $DomainSnapshot = $VM->IdleSnapshot;
+  my $ExtraTimeout = 0;
+  my $CreateSnapshot;
 
-  # Revert the VM (and power it on if necessary)
   my $Domain = $VM->GetDomain();
-  Debug(Elapsed($Start), " Reverting $VMKey to ", $VM->IdleSnapshot, "\n");
-  my ($ErrMessage, $Booting) = $Domain->RevertToSnapshot();
+  if (!$Domain->HasSnapshot($DomainSnapshot) and $DomainSnapshot =~ s/-live$//)
+  {
+    # Add some extra time to boot the VM and create the live snapshot
+    $ExtraTimeout += $WaitForBoot + $VMToolTimeout / 2;
+    $CreateSnapshot = 1;
+    Debug(Elapsed($Start), " $VMKey does not yet have a $DomainSnapshot-live snapshot\n");
+  }
+  if (!$Domain->HasSnapshot($DomainSnapshot))
+  {
+    FatalError("Could not find $VMKey\'s $DomainSnapshot snapshot\n");
+  }
+  if ($ExtraTimeout)
+  {
+    Debug(Elapsed($Start), " Extend the $VMKey revert deadline by $ExtraTimeout\n");
+    my $Deadline = $VM->Status eq "maintenance" ? (time() + $VMToolTimeout) :
+                                                  $VM->ChildDeadline;
+    $VM->ChildDeadline($Deadline + $ExtraTimeout);
+    $VM->Save();
+  }
+
+  # Revert the VM (and power it on if necessary)
+  Debug(Elapsed($Start), " Reverting $VMKey to $DomainSnapshot\n");
+  my ($ErrMessage, $Booting) = $Domain->RevertToSnapshot($DomainSnapshot);
   if (defined $ErrMessage)
   {
     # Libvirt/QEmu is buggy and cannot revert a running VM from one hardware
@@ -408,28 +450,45 @@ sub Revert()
       FatalError("Could not power off $VMKey: $ErrMessage\n");
     }
 
-    Debug(Elapsed($Start), " Reverting $VMKey to ", $VM->IdleSnapshot, "... again\n");
-    ($ErrMessage, $Booting) = $Domain->RevertToSnapshot();
+    Debug(Elapsed($Start), " Reverting $VMKey to $DomainSnapshot... again\n");
+    ($ErrMessage, $Booting) = $Domain->RevertToSnapshot($DomainSnapshot);
   }
   if (defined $ErrMessage)
   {
-    FatalError("Could not revert $VMKey to ". $VM->IdleSnapshot .": $ErrMessage\n");
+    FatalError("Could not revert $VMKey to $DomainSnapshot: $ErrMessage\n");
   }
 
-  # The VM is now sleeping which may allow some tasks to run
-  return 1 if (ChangeStatus("reverting", "sleeping"));
+  # Mark the VM as sleeping which allows the scheduler to abort the revert in
+  # favor of higher priority tasks. But don't allow interruptions in the
+  # middle of snapshot creation!
+  if (!$CreateSnapshot)
+  {
+    return 1 if (ChangeStatus("reverting", "sleeping"));
+  }
 
   # Set up the TestAgent server
   SetupTestAgentd($VM, $Booting);
 
-  if ($SleepAfterRevert != 0)
+  if ($CreateSnapshot)
   {
+    CreateSnapshot($Domain, $VM->IdleSnapshot);
+  }
+  else
+  {
+    my $Sleep = ($Booting and $SleepAfterBoot > $SleepAfterRevert) ?
+                $SleepAfterBoot : $SleepAfterRevert;
     Debug(Elapsed($Start), " Sleeping\n");
-    LogMsg "Letting ". $VM->Name  ." settle down for ${SleepAfterRevert}s\n";
-    sleep($SleepAfterRevert);
+    LogMsg "Letting $VMKey settle down for ${Sleep}s\n";
+    sleep($Sleep);
+  }
+
+  if ($CreateSnapshot)
+  {
+    # The activity monitor does not like it when VMs skip the sleeping step
+    return 1 if (ChangeStatus("reverting", "sleeping"));
   }
 
-  return ChangeStatus("sleeping", "idle", "done");
+  return ChangeStatus($CurrentStatus, "idle", "done");
 }
 
 
diff --git a/testbot/lib/WineTestBot/Config.pm b/testbot/lib/WineTestBot/Config.pm
index 27e863c..56971b7 100644
--- a/testbot/lib/WineTestBot/Config.pm
+++ b/testbot/lib/WineTestBot/Config.pm
@@ -28,7 +28,7 @@ WineTestBot::Config - Site-independent configuration settings
 use vars qw (@ISA @EXPORT @EXPORT_OK $UseSSL $LogDir $DataDir $BinDir
              %RepoURLs $DbDataSource $DbUsername $DbPassword $MaxRevertingVMs
              $MaxRevertsWhileRunningVMs $MaxActiveVMs $MaxRunningVMs
-             $MaxVMsWhenIdle $SleepAfterRevert $WaitForBoot
+             $MaxVMsWhenIdle $WaitForBoot $SleepAfterBoot $SleepAfterRevert
              $VMToolTimeout $MaxVMErrors $MaxTaskTries $AdminEMail $RobotEMail
              $WinePatchToOverride $WinePatchCc
              $ExeBuildNativeTimeout $ExeBuildTestTimeout $ExeModuleTimeout
@@ -44,7 +44,8 @@ require Exporter;
 @ISA = qw(Exporter);
 @EXPORT = qw($UseSSL $LogDir $DataDir $BinDir %RepoURLs
              $MaxRevertingVMs $MaxRevertsWhileRunningVMs $MaxActiveVMs
-             $MaxRunningVMs $MaxVMsWhenIdle $SleepAfterRevert $WaitForBoot
+             $MaxRunningVMs $MaxVMsWhenIdle $WaitForBoot $SleepAfterBoot
+             $SleepAfterRevert
              $VMToolTimeout $MaxVMErrors $MaxTaskTries $AdminEMail
              $RobotEMail $WinePatchToOverride $WinePatchCc $SuiteTimeout
              $ExeBuildNativeTimeout $ExeBuildTestTimeout $ExeModuleTimeout
@@ -92,6 +93,8 @@ $MaxVMsWhenIdle = undef;
 
 # How long to attempt to connect to the TestAgent while the VM is booting.
 $WaitForBoot = 90;
+# How long to let the VM settle down after booting it before taking a snapshot.
+$SleepAfterBoot = 30;
 # How long to let the VM settle down after a revert before starting a task on
 # it (in seconds).
 $SleepAfterRevert = 0;
diff --git a/testbot/lib/WineTestBot/LibvirtDomain.pm b/testbot/lib/WineTestBot/LibvirtDomain.pm
index 1f70c97..14bf71d 100644
--- a/testbot/lib/WineTestBot/LibvirtDomain.pm
+++ b/testbot/lib/WineTestBot/LibvirtDomain.pm
@@ -307,11 +307,10 @@ sub GetSnapshotName($)
   return (undef, $SnapshotName);
 }
 
-sub RevertToSnapshot($)
+sub RevertToSnapshot($$)
 {
-  my ($self) = @_;
+  my ($self, $SnapshotName) = @_;
 
-  my $SnapshotName = $self->{VM}->IdleSnapshot;
   my ($ErrMessage, $Domain, $Snapshot) = $self->_GetSnapshot($SnapshotName);
   return ($ErrMessage, undef) if (defined $ErrMessage);
 




More information about the wine-cvs mailing list