Steps:
1 virsh reboot guest1 --mode=acpi
2 virsh shutdown guest1 --mode=agent
Expected result:
As the SHUTDOWN job is after REBOOT, we expected the guest to be *shutoff*.
Exacted result:
After the 2 steps above, the guest got *rebooted*.
The reason to this problem:
1 in qemuDomainReboot(mode acpi), it sets priv->fakeReboot to 1.
2 after shutdown/reboot, qemu monitor IO trigged qemuProcessHandleShutdown(), which
finds that priv->fakeReboot is 1, and reboot the guest.
Root Cause of the problem:
After further look into the problem, We found that the design of acpi/agent
shutdown/reboot seems a little chaotic.
-----------------------------------
sheet1 who sets fakeReboot
-----------------------------------
shutdown reboot
acpi Y(0) Y(1)
agent N N
It's apparently, *acpi-mode* jobs set fakeReboot.
-----------------------------------
sheet2 who needs to check fakeReboot(qemuProcessHandleShutdown())
-----------------------------------
shutdown reboot
acpi Y Y
agent *Y* *N*
Things become a little odd here. only agent-mode reboot doesn't check fakeReboot.
We can tell from the above 2 sheets, that they're not consistent.
*Agent-mode shutdown checks fakeReboot(trigger by SHUTDOWN monitorIO event), while it
didn't set it before.*
The chaos is not caused by libvirtd, it's a systematic problem, including guest os
and qemu. (guest os writes ACPI, triggers qemu, qemu then triggers libvirtd)
Solution:
A simple solution is to make the 1st sheet consistent to the 2nd sheet, which is:
-----------------------------------
sheet3 who should set fakeReboot:
-----------------------------------
shutdown reboot
acpi Y(0) Y(1)
agent *Y(0)* N
-----------------------------------
we let agent-mode shutdown set fakeReboot to 0.
Signed-off-by: Zhang Bo <oscar.zhangbo(a)huawei.com>
Signed-off-by: Wang Yufei <james.wangyufei(a)huawei.com>
---
src/qemu/qemu_driver.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 7eb5a7d..c751dcf 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -1959,6 +1959,8 @@ static int qemuDomainShutdownFlags(virDomainPtr dom, unsigned int
flags)
goto endjob;
}
+ qemuDomainSetFakeReboot(driver, vm, isReboot);
+
if (useAgent) {
qemuDomainObjEnterAgent(vm);
ret = qemuAgentShutdown(priv->agent, agentFlag);
@@ -1970,7 +1972,6 @@ static int qemuDomainShutdownFlags(virDomainPtr dom, unsigned int
flags)
*/
if (!useAgent ||
(ret < 0 && (acpiRequested || !flags))) {
- qemuDomainSetFakeReboot(driver, vm, isReboot);
/* Even if agent failed, we have to check if guest went away
* by itself while our locks were down. */
--
1.7.12.4