Snapshots with a name ending in '-off' request that the VM be cleanly shut down if possible rather than summarily powered off. So check the domain's current snapshot and do a clean shutdown before powering off for every operation, including checkoff, monitor and revert.
Signed-off-by: Francois Gouget fgouget@codeweavers.com --- testbot/bin/LibvirtTool.pl | 118 ++++++++++++++++++++++--------------- 1 file changed, 72 insertions(+), 46 deletions(-)
diff --git a/testbot/bin/LibvirtTool.pl b/testbot/bin/LibvirtTool.pl index f135b9b51..c4dbffbaa 100755 --- a/testbot/bin/LibvirtTool.pl +++ b/testbot/bin/LibvirtTool.pl @@ -257,6 +257,66 @@ sub ChangeStatus($$;$) return 0; }
+sub ShutDown() +{ + my $Domain = $VM->GetDomain(); + my $CurrentSnapshot = $Domain->GetSnapshotName(); + if (!defined $CurrentSnapshot or $CurrentSnapshot !~ /-off$/ or + !$Domain->IsPoweredOn()) + { + return 1; + } + + Debug(Elapsed($Start), " Performing a clean shutdown of $VMKey $CurrentSnapshot\n"); + LogMsg "Performing a clean shutdown of $VMKey $CurrentSnapshot\n"; + + # Use SetTime() to detect if privileged operations are allowed. + my $TA = $VM->GetAgent(); + if (!$TA->SetTime()) + { + # Not a fatal error. Try the next port in case the VM runs a privileged + # TestAgentd daemon there. + $TA->Disconnect(); + $TA = $VM->GetAgent(1); + if (!$TA->SetTime()) + { + Error "Unable to get a privileged TestAgent: ". $TA->GetLastError() ."\n"; + $TA->Disconnect(); + return 0; + } + } + + my $Success = 1; + my $Cmd = $VM->Type =~ /^win(?:32|64)$/ ? + ["shutdown.exe", "/p", "/d", "00:00"] : + ["/sbin/shutdown", "--poweroff", "now"]; + Debug(Elapsed($Start), " Running @$Cmd\n"); + if (!$TA->Run($Cmd, 0)) + { + Error "Could not run @$Cmd: ". $TA->GetLastError() ."\n"; + $Success = 0; + } + else + { + Debug(Elapsed($Start), " Waiting for the VM to power off\n"); + my $Deadline = time() + $WaitForShutdown; + while ($Domain->IsPoweredOn()) + { + if (time() >= $Deadline) + { + Error "Timed out waiting for $VMKey to perform a clean shutdown. Forcefully shutting down now...\n"; + $Success = 0; + last; + } + sleep(1); + } + } + $TA->Disconnect(); + Debug(Elapsed($Start), " Successfully shut down $VMKey\n"); + LogMsg "Successfully shut down $VMKey\n"; + return $Success; +} + sub Monitor() { # Still try recovering the VM in case of repeated errors, but space out @@ -301,6 +361,9 @@ sub Monitor() my $IsReady = $VM->GetDomain()->IsReady(); if ($IsReady and $VM->GetDomain()->IsPoweredOn()) { + # Try to perform a clean shutdown if requested + ShutDown(); + my $ErrMessage = $VM->GetDomain()->PowerOff(); if (defined $ErrMessage) { @@ -324,55 +387,12 @@ sub Monitor()
sub PowerOff() { - my $Domain = $VM->GetDomain(); - if ($VM->IdleSnapshot =~ /-off$/ and $Domain->IsPoweredOn()) - { - # Attempt to perform a clean shutdown. - # Use SetTime() to detect if privileged operations are allowed. - my $TA = $VM->GetAgent(); - if (!$TA->SetTime()) - { - # Not a fatal error. Try the next port in case the VM runs a privileged - # TestAgentd daemon there. - $TA->Disconnect(); - $TA = $VM->GetAgent(1); - if (!$TA->SetTime()) - { - Error "Unable to get a privileged TestAgent: ". $TA->GetLastError() ."\n"; - $TA->Disconnect(); - $TA = undef; - } - } - if ($TA) - { - my $Cmd = $VM->Type =~ /^win(?:32|64)$/ ? - ["shutdown.exe", "/p", "/d", "00:00"] : - ["/sbin/shutdown", "--poweroff", "now"]; - Debug(Elapsed($Start), " Running @$Cmd\n"); - if (!$TA->Run($Cmd, 0)) - { - Error "Could not run @$Cmd: ". $TA->GetLastError() ."\n"; - } - else - { - Debug(Elapsed($Start), " Waiting for the VM to power off\n"); - my $Deadline = time() + $WaitForShutdown; - while ($Domain->IsPoweredOn()) - { - if (time() >= $Deadline) - { - Error "Timed out waiting for ". $VM->Name ." to perform a clean shutdown. Forcefully shutting down now...\n"; - last; - } - sleep(1); - } - } - } - } + # Try to perform a clean shutdown if requested + ShutDown();
# Power off the VM no matter what its initial status is $CurrentStatus = $VM->Status; - my $ErrMessage = $Domain->PowerOff(); + my $ErrMessage = $VM->GetDomain()->PowerOff(); FatalError("$ErrMessage\n") if (defined $ErrMessage);
return ChangeStatus(undef, "off", "done"); @@ -407,6 +427,9 @@ sub CheckOff() FatalError("$ErrMessage\n") if (defined $ErrMessage); if ($SnapshotName eq $VM->IdleSnapshot) { + # Try to perform a clean shutdown if requested + ShutDown(); + my $ErrMessage = $VM->GetDomain()->PowerOff(); FatalError("$ErrMessage\n") if (defined $ErrMessage); } @@ -584,6 +607,9 @@ sub Revert() $VM->Save(); }
+ # Before reverting, try to perform a clean shutdown if requested + ShutDown(); + # Revert the VM (and power it on if necessary) Debug(Elapsed($Start), " Reverting $VMKey to $DomainSnapshot\n"); my ($ErrMessage, $Booting) = $Domain->RevertToSnapshot($DomainSnapshot);