Module: tools
Branch: master
Commit: 548f7e305da1257b7b5e9a61d597c3d3be89f442
URL: http://source.winehq.org/git/tools.git/?a=commit;h=548f7e305da1257b7b5e9a61…
Author: Francois Gouget <fgouget(a)codeweavers.com>
Date: Wed Oct 18 20:16:44 2017 +0200
testbot: Avoid blocking virtualization functions in the Engine initialization.
The Cleanup() method now uses LibvirtTool to verify that idle VMs are
still good and to power off VMs.
Note that the VMs are marked dirty while LibvirtTool performs the idle
check to prevent the scheduler from using them.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard(a)winehq.org>
---
testbot/bin/Engine.pl | 56 ++++++++++++++------------------
testbot/bin/LibvirtTool.pl | 24 ++++++++++++--
testbot/lib/WineTestBot/LibvirtDomain.pm | 21 ++++++++++++
testbot/lib/WineTestBot/VMs.pm | 17 ++++++++++
4 files changed, 84 insertions(+), 34 deletions(-)
diff --git a/testbot/bin/Engine.pl b/testbot/bin/Engine.pl
index 9c461df..02c361c 100755
--- a/testbot/bin/Engine.pl
+++ b/testbot/bin/Engine.pl
@@ -112,32 +112,27 @@ sub Cleanup(;$$)
foreach my $Task (@{$Tasks->GetItems()})
{
my $TaskKey = join("/", $Job->Id, $Step->No, $Task->No);
+ my $ChildPid = $Task->ChildPid;
+ $ChildPid = undef if (defined $ChildPid and !kill(0, $ChildPid));
my $Requeue;
- if (!defined $Task->ChildPid)
+ if (!defined $ChildPid)
{
# That task's process died somehow.
$Requeue = 1;
}
- elsif (!$Task->VM->GetDomain()->IsPoweredOn())
+ elsif ($Task->VM->Status ne "running")
{
- # A running task should have a powered on VM.
+ # The Task and VM status should match.
$Requeue = 1;
- # Kill the task process if it's still there.
- kill("TERM", $Task->ChildPid);
+ kill("TERM", $ChildPid);
}
elsif ($KillTasks)
{
# Kill the task and requeue. Note that since the VM is still running
# we're not in the computer reboot case so ChildPid is probably
# still valid.
- kill("TERM", $Task->ChildPid);
- $Requeue = 1;
- }
- elsif (!kill(0, $Task->ChildPid))
- {
- # The event that caused the WineTestBot server to restart probably
- # also killed the task's child process.
+ kill("TERM", $ChildPid);
$Requeue = 1;
}
else
@@ -181,36 +176,35 @@ sub Cleanup(;$$)
next;
}
- my $Domain = $VM->GetDomain();
- if ($Domain->IsPoweredOn())
+ if ($VM->HasRunningChild())
{
if ($KillVMs)
{
$VM->KillChild();
+ $VM->RunPowerOff();
}
- elsif ($VM->Status eq "idle")
+ elsif (!$VM->CanHaveChild())
{
- # Assume these are still ready for use
- next;
- }
- elsif ($VM->CanHaveChild() and $VM->HasRunningChild())
- {
- # This VM is still being reverted. Let that process run its course.
- LogMsg "$VMKey is being reverted\n";
- next;
+ # The VM should not have a process.
+ $VM->KillChild();
+ $VM->RunPowerOff();
}
- LogMsg "Powering off $VMKey\n";
- $Domain->PowerOff();
+ # else let the process finish its work
}
else
{
- next if ($VM->Status eq "off");
- LogMsg "Marking $VMKey as off\n";
+ if ($VM->Status eq "idle")
+ {
+ $VM->RunCheckIdle();
+ }
+ else
+ {
+ # Power off the VM, even if its status is already off.
+ # This is the simplest way to resync the VM status field.
+ # Also powering off a powered off VM will detect offline VMs.
+ $VM->RunPowerOff();
+ }
}
-
- $VM->Status('off');
- $VM->ChildPid(undef);
- $VM->Save();
}
}
diff --git a/testbot/bin/LibvirtTool.pl b/testbot/bin/LibvirtTool.pl
index 64f0575..fcc0e81 100755
--- a/testbot/bin/LibvirtTool.pl
+++ b/testbot/bin/LibvirtTool.pl
@@ -104,7 +104,7 @@ while (@ARGV)
{
$LogOnly = 1;
}
- elsif ($Arg =~ /^(?:poweroff|revert)$/)
+ elsif ($Arg =~ /^(?:checkidle|poweroff|revert)$/)
{
$Action = $Arg;
}
@@ -163,7 +163,7 @@ if (!defined $Usage)
}
if (defined $Usage)
{
- print "Usage: $Name0 [--debug] [--log-only] [--help] (poweroff|revert) VMName\n";
+ print "Usage: $Name0 [--debug] [--log-only] [--help] (checkidle|poweroff|revert) VMName\n";
exit $Usage;
}
@@ -261,6 +261,20 @@ sub PowerOff()
return ChangeStatus(undef, "off", "done");
}
+sub CheckIdle()
+{
+ $CurrentStatus = "dirty";
+ my $IsPoweredOn = $VM->GetDomain()->IsPoweredOn();
+ return ChangeStatus("dirty", "offline", "done") if (!defined $IsPoweredOn);
+ return ChangeStatus("dirty", "off", "done") if (!$IsPoweredOn);
+
+ my ($ErrMessage, $SnapshotName) = $VM->GetDomain()->GetSnapshotName();
+ FatalError("$ErrMessage\n") if (defined $ErrMessage);
+ return PowerOff() if ($SnapshotName ne $VM->IdleSnapshot);
+
+ return ChangeStatus("dirty", "idle", "done");
+}
+
sub Revert()
{
my $VM = CreateVMs()->GetItem($VMKey);
@@ -318,7 +332,11 @@ sub Revert()
my $Rc;
-if ($Action eq "poweroff")
+if ($Action eq "checkidle")
+{
+ $Rc = CheckIdle();
+}
+elsif ($Action eq "poweroff")
{
$Rc = PowerOff();
}
diff --git a/testbot/lib/WineTestBot/LibvirtDomain.pm b/testbot/lib/WineTestBot/LibvirtDomain.pm
index 5fbff18..20d619a 100644
--- a/testbot/lib/WineTestBot/LibvirtDomain.pm
+++ b/testbot/lib/WineTestBot/LibvirtDomain.pm
@@ -202,6 +202,27 @@ sub _GetSnapshot($$)
return (_eval_err() || "Snapshot '$SnapshotName' not found", undef, undef);
}
+sub GetSnapshotName($)
+{
+ my ($self) = @_;
+
+ my ($ErrMessage, $Domain) = $self->_GetDomain();
+ return ($ErrMessage, undef) if (defined $ErrMessage);
+
+ my $SnapshotName;
+ eval
+ {
+ if ($Domain->has_current_snapshot())
+ {
+ my $Snapshot = $Domain->current_snapshot();
+ $SnapshotName = $Snapshot->get_name() if ($Snapshot);
+ }
+ };
+ return $self->_Reset(_eval_err(), undef) if ($@);
+
+ return (undef, $SnapshotName);
+}
+
sub RevertToSnapshot($)
{
my ($self) = @_;
diff --git a/testbot/lib/WineTestBot/VMs.pm b/testbot/lib/WineTestBot/VMs.pm
index a6b2a8b..377eb0a 100644
--- a/testbot/lib/WineTestBot/VMs.pm
+++ b/testbot/lib/WineTestBot/VMs.pm
@@ -399,6 +399,23 @@ sub _RunVMTool($$$)
=pod
=over 12
+=item C<RunCheckIdle()>
+
+If the virtual machine state matches that of this VM instance, sets its status
+to idle. If not the VM is simply marked as off. While this is happening the
+VM status is set to dirty so the job scheduler does not try to use it.
+
+This operation can take a long time so it is performed in a separate process.
+
+=back
+=cut
+
+sub RunCheckIdle($)
+{
+ my ($self) = @_;
+ return $self->_RunVMTool("dirty", ["--log-only", "checkidle", $self->GetKey()]);
+}
+
=item C<RunPowerOff()>
Powers off the VM so that it stops using resources.
Module: tools
Branch: master
Commit: 3b323fcebc2e43c3cc381e248e6b79aa64853fac
URL: http://source.winehq.org/git/tools.git/?a=commit;h=3b323fcebc2e43c3cc381e24…
Author: Francois Gouget <fgouget(a)codeweavers.com>
Date: Wed Oct 18 20:14:42 2017 +0200
testbot: Tweak the jobs scheduler to use LibvirtTool to power off VMs.
The main impact is that powering off a VM is now asynchronous and must
not be left alone by the scheduler while they are being powered off.
To that end VMs that are being powered off keep their dirty status
but have a ChildPid which separates them from 'fresh' dirty VMs.
This also requires not ignoring the dirty to off VM status transitions
in HandleVMStatusChange() otherwise the scheduler may miss on an
opportunity to spin up some idle VMs for future jobs. Generally speaking
HandleVMStatusChange() should not be second guessing the scheduler
anyway so remove all filtering.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard(a)winehq.org>
---
testbot/bin/Engine.pl | 12 ++++--------
testbot/lib/WineTestBot/Jobs.pm | 43 ++++++++++++++++++++++++-----------------
2 files changed, 29 insertions(+), 26 deletions(-)
diff --git a/testbot/bin/Engine.pl b/testbot/bin/Engine.pl
index b9c6ceb..9c461df 100755
--- a/testbot/bin/Engine.pl
+++ b/testbot/bin/Engine.pl
@@ -380,15 +380,11 @@ sub HandleVMStatusChange($$$)
return "0Invalid status";
}
- if ($OldStatus eq "reverting" || $OldStatus eq "running" ||
- $NewStatus eq "idle" || $NewStatus eq "dirty")
+ my $ErrMessage = ScheduleJobs();
+ if (defined($ErrMessage))
{
- my $ErrMessage = ScheduleJobs();
- if (defined($ErrMessage))
- {
- LogMsg "Scheduling problem in HandleVMStatusChange: $ErrMessage\n";
- return "0$ErrMessage";
- }
+ LogMsg "Scheduling problem in HandleVMStatusChange: $ErrMessage\n";
+ return "0$ErrMessage";
}
return "1OK";
diff --git a/testbot/lib/WineTestBot/Jobs.pm b/testbot/lib/WineTestBot/Jobs.pm
index 26538fa..6e7937f 100644
--- a/testbot/lib/WineTestBot/Jobs.pm
+++ b/testbot/lib/WineTestBot/Jobs.pm
@@ -591,13 +591,14 @@ sub ScheduleOnHost($$$)
# Figure out how many VMs we will actually be able to revert now and only
# keep the highest priority ones.
my @SortedVMsToRevert = sort { $VMsToRevert{$a} <=> $VMsToRevert{$b} } keys %VMsToRevert;
- # Sleeping VMs will soon be running
my $MaxReverts = ($RunningCount > 0) ?
$MaxRevertsWhileRunningVMs : $MaxRevertingVMs;
- my $ActiveCount = $IdleCount + $SleepingCount + $RunningCount + $RevertingCount;
+ my $ActiveCount = $IdleCount + $RunningCount + $RevertingCount + $SleepingCount + @DirtyVMs;
+ # This is the number of VMs we would revert if idle and dirty VMs did not
+ # stand in the way. And those that do will be shut down.
my $RevertableCount = min(scalar(@SortedVMsToRevert),
$MaxReverts - $RevertingCount,
- $MaxActiveVMs - ($ActiveCount - $IdleCount));
+ $MaxActiveVMs - ($ActiveCount - $IdleCount - @DirtyVMs));
if ($RevertableCount < @SortedVMsToRevert)
{
$RevertableCount = 0 if ($RevertableCount < 0);
@@ -613,19 +614,20 @@ sub ScheduleOnHost($$$)
# resources while waiting for their turn.
foreach my $VMKey (@DirtyVMs)
{
- if (!exists $VMsToRevert{$VMKey})
- {
- my $VM = $HostVMs->GetItem($VMKey);
- # FIXME Domain operations can be slow and should not be run by the Engine
- my $ErrMessage = $VM->GetDomain()->PowerOff();
- return $ErrMessage if (defined $ErrMessage);
- }
+ next if (exists $VMsToRevert{$VMKey});
+
+ my $VM = $HostVMs->GetItem($VMKey);
+ next if ($VM->Status ne "dirty" or defined $VM->ChildPid);
+
+ my $ErrMessage = $VM->RunPowerOff();
+ return $ErrMessage if (defined $ErrMessage);
}
# Power off some idle VMs we don't need immediately so we can revert more
# of the VMs we need now.
+ my $PlannedActiveCount = $ActiveCount - @DirtyVMs + @SortedVMsToRevert;
if ($IdleCount > 0 && @SortedVMsToRevert > 0 &&
- $ActiveCount + @SortedVMsToRevert > $MaxActiveVMs)
+ $PlannedActiveCount > $MaxActiveVMs)
{
# Sort from least important to most important
my @SortedIdleVMs = sort { $VMPriorities{$a} <=> $VMPriorities{$b} } keys %IdleVMs;
@@ -634,25 +636,30 @@ sub ScheduleOnHost($$$)
my $VM = $HostVMs->GetItem($VMKey);
next if (!$IdleVMs{$VMKey});
- # FIXME Domain operations can be slow and should not be run by the Engine
- my $ErrMessage = $VM->GetDomain()->PowerOff();
+ my $ErrMessage = $VM->RunPowerOff();
return $ErrMessage if (defined $ErrMessage);
- $IdleCount--;
- $ActiveCount--;
- last if ($ActiveCount + @SortedVMsToRevert <= $MaxActiveVMs);
+ $PlannedActiveCount--;
+ last if ($PlannedActiveCount <= $MaxActiveVMs);
}
+ # The scheduler will be run again when these VMs have been powered off and
+ # then we will do the reverts. In the meantime don't change $ActiveCount.
}
# Revert the VMs that are blocking jobs
foreach my $VMKey (@SortedVMsToRevert)
{
+ last if ($RevertingCount == $MaxReverts);
+
my $VM = $HostVMs->GetItem($VMKey);
+ next if ($VM->Status eq "off" and $ActiveCount >= $MaxActiveVMs);
+
delete $VMPriorities{$VMKey};
my $ErrMessage = $VM->RunRevert();
return $ErrMessage if (defined $ErrMessage);
+
+ $RevertingCount++;
+ $ActiveCount++ if ($VM->Status eq "off");
}
- $RevertingCount += @SortedVMsToRevert;
- $ActiveCount += @SortedVMsToRevert;
# Prepare some VMs for the current jobs next step
foreach my $VMKey (@VMsNext)
Module: tools
Branch: master
Commit: 74aeb1e5cb401da6c11e351c1c9afb0196ed5f30
URL: http://source.winehq.org/git/tools.git/?a=commit;h=74aeb1e5cb401da6c11e351c…
Author: Francois Gouget <fgouget(a)codeweavers.com>
Date: Wed Oct 18 20:14:32 2017 +0200
testbot: Make it possible to power off VMs using LibvirtTool.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard(a)winehq.org>
---
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 6aaaf82..64f0575 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 c26ff92..26538fa 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 86dee6c..a6b2a8b 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),
Module: tools
Branch: master
Commit: 9c07f07c27c608a5c114b46f4bb2bc562079a477
URL: http://source.winehq.org/git/tools.git/?a=commit;h=9c07f07c27c608a5c114b46f…
Author: Francois Gouget <fgouget(a)codeweavers.com>
Date: Wed Oct 18 20:09:07 2017 +0200
testbot/LibvirtTool: Return a suitable exit code in ChangeStatus().
This fixes the LibvirtTool exit code (which is fortunately not used) and
simplifies the code.
Document the FatalError() and ChangeStatus() functions, particularly
their return code, or lack thereof.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard(a)winehq.org>
---
testbot/bin/LibvirtTool.pl | 36 ++++++++++++++++++++++++++++++++----
1 file changed, 32 insertions(+), 4 deletions(-)
diff --git a/testbot/bin/LibvirtTool.pl b/testbot/bin/LibvirtTool.pl
index 149e850..6aaaf82 100755
--- a/testbot/bin/LibvirtTool.pl
+++ b/testbot/bin/LibvirtTool.pl
@@ -176,6 +176,18 @@ my $Start = Time();
my $CurrentStatus;
+=pod
+=over 12
+
+=item C<FatalError()>
+
+Logs the fatal error, notifies the administrator and exits the process.
+
+This function never returns!
+
+=back
+=cut
+
sub FatalError($)
{
my ($ErrMessage) = @_;
@@ -200,6 +212,20 @@ sub FatalError($)
exit 1;
}
+=pod
+=over 12
+
+=item C<ChangeStatus()>
+
+Checks that the VM status has not been tampered with and sets it to the new
+value.
+
+Returns a value suitable for the process exit code: 0 in case of success,
+1 otherwise.
+
+=back
+=cut
+
sub ChangeStatus($$;$)
{
my ($From, $To, $Done) = @_;
@@ -209,7 +235,9 @@ sub ChangeStatus($$;$)
if (!$VM or (defined $From and $VM->Status ne $From))
{
LogMsg "Not changing status\n";
- return undef;
+ # Not changing the status is allowed in debug mode so the VM can be
+ # put in 'maintenance' mode to avoid interference from the TestBot.
+ return $Debug ? 0 : 1;
}
$VM->Status($To);
@@ -220,7 +248,7 @@ sub ChangeStatus($$;$)
FatalError("Could not change the $VMKey VM status: $ErrMessage\n");
}
$CurrentStatus = $To;
- return 1;
+ return 0;
}
sub Revert()
@@ -252,7 +280,7 @@ sub Revert()
}
# The VM is now sleeping which may allow some tasks to run
- return 1 if (!ChangeStatus("reverting", "sleeping"));
+ return 1 if (ChangeStatus("reverting", "sleeping"));
# Check the TestAgent connection. Note that this may take some time
# if the VM needs to boot first.
@@ -275,7 +303,7 @@ sub Revert()
sleep($SleepAfterRevert);
}
- return ChangeStatus("sleeping", "idle", "done") ? 0 : 1;
+ return ChangeStatus("sleeping", "idle", "done");
}
Module: tools
Branch: master
Commit: 79ff56652c602ca55f53e0d08ba6846fb67f63f5
URL: http://source.winehq.org/git/tools.git/?a=commit;h=79ff56652c602ca55f53e0d0…
Author: Francois Gouget <fgouget(a)codeweavers.com>
Date: Wed Oct 18 15:38:51 2017 +0200
testbot: Document how to use powered off snapshots.
RevertToSnapshot() will automatically boot up the VM if necessary. So
all that is needed to use a powered off snapshot is making sure it will
boot up to a usable state and making sure 3*$WaitForToolsInVM will give
enough time to the VM to boot.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard(a)winehq.org>
---
testbot/bin/LibvirtTool.pl | 3 +++
testbot/doc/INSTALL.txt | 15 +++++++++++----
testbot/lib/WineTestBot/Config.pm | 5 +++--
testbot/lib/WineTestBot/LibvirtDomain.pm | 1 +
4 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/testbot/bin/LibvirtTool.pl b/testbot/bin/LibvirtTool.pl
index 358eebf..149e850 100755
--- a/testbot/bin/LibvirtTool.pl
+++ b/testbot/bin/LibvirtTool.pl
@@ -243,6 +243,7 @@ sub Revert()
LogMsg "Trying the revert anyway...\n";
}
+ # Revert the VM (and power it on if necessary)
Debug(Elapsed($Start), " Reverting $VMKey to ", $VM->IdleSnapshot, "\n");
$ErrMessage = $Domain->RevertToSnapshot();
if (defined $ErrMessage)
@@ -253,6 +254,8 @@ sub Revert()
# The VM is now sleeping which may allow some tasks to run
return 1 if (!ChangeStatus("reverting", "sleeping"));
+ # Check the TestAgent connection. Note that this may take some time
+ # if the VM needs to boot first.
Debug(Elapsed($Start), " Trying the TestAgent connection\n");
LogMsg "Waiting for ". $VM->Name ." (up to ${WaitForToolsInVM}s per attempt)\n";
my $TA = $VM->GetAgent();
diff --git a/testbot/doc/INSTALL.txt b/testbot/doc/INSTALL.txt
index 07919a3..0b95656 100644
--- a/testbot/doc/INSTALL.txt
+++ b/testbot/doc/INSTALL.txt
@@ -141,8 +141,11 @@ Dependencies:
Where PORT is the $AgentPort that was configured in ConfigLocal.pl
on the WineTestBot server, and SRCHOST is either omitted or the hostname
of the WineTestBot server.
-- Take a snapshot of the running VM. Make sure restoring this snapshot
- will result in a running build VM.
+- Take a snapshot of the VM. The shorter the revert time the better. This
+ usually implies taking a snapshot of the running VM as set up in the previous
+ step. However it is also possible to use snapshots of the powered off VM. In
+ that case make sure booting the VM will automatically start the TestAgent
+ server in the right configuration.
- Register this VM as a build VM on the web site.
@@ -156,8 +159,12 @@ Dependencies:
Where PORT is the $AgentPort that was configured in ConfigLocal.pl
on the WineTestBot server, and SRCHOST is either omitted or the hostname
of the WineTestBot server.
-- Take a snapshot of the running VM. Make sure restoring this snapshot
- will result in a running Windows VM.
+- Take a snapshot of the VM. The shorter the revert time the better. This
+ usually implies taking a snapshot of the running VM as set up in the previous
+ step. However it is also possible to use snapshots of the powered off VM. In
+ that case make sure booting the VM will automatically log in and start the
+ TestAgent server in the right configuration and with the appropriate
+ privileges.
- Register this VM on the web site. On a production WineTestBot server
you would likely want to make it an 'extra' VM until you have
confirmed that it works as expected.
diff --git a/testbot/lib/WineTestBot/Config.pm b/testbot/lib/WineTestBot/Config.pm
index c5586c7..4f38633 100644
--- a/testbot/lib/WineTestBot/Config.pm
+++ b/testbot/lib/WineTestBot/Config.pm
@@ -71,8 +71,9 @@ $MaxRevertsWhileRunningVMs = 1;
$MaxActiveVMs = 2;
$MaxVMsWhenIdle = undef;
-# How long to wait when connecting to the VM's TestAgent server after a revert
-# (in seconds).
+# How long to wait for each of the 3 connection attempts to the VM's TestAgent
+# server after a revert (in seconds). If there are powered off snapshots this
+# must be long enough for the VM to boot up first.
$WaitForToolsInVM = 30;
# How long to let the VM settle down after the revert before starting a task on
# it (in seconds).
diff --git a/testbot/lib/WineTestBot/LibvirtDomain.pm b/testbot/lib/WineTestBot/LibvirtDomain.pm
index d449f9d..5fbff18 100644
--- a/testbot/lib/WineTestBot/LibvirtDomain.pm
+++ b/testbot/lib/WineTestBot/LibvirtDomain.pm
@@ -210,6 +210,7 @@ sub RevertToSnapshot($)
my ($ErrMessage, $Domain, $Snapshot) = $self->_GetSnapshot($SnapshotName);
return $ErrMessage if (defined $ErrMessage);
+ # Note that if the snapshot was of a powered off domain, this boots it up
eval { $Snapshot->revert_to(Sys::Virt::DomainSnapshot::REVERT_RUNNING) };
return $@ ? $self->_Reset(_eval_err()) : $self->_UpdateStatus($Domain);
}