When libvirt is starting a domain, it reports the state as SHUTOFF until
it's RUNNING. This is not ideal because domain startup may take a long
time (usually because of some configuration issues, firewalls blocking
access to network disks, etc.) and domain lists provided by libvirt look
awkward. One can see weird shutoff domains with IDs in a list of active
domains or even shutoff transient domains. In any case, it looks more
like a bug in libvirt than a normal state a domain goes through.
I'm not quite sure what the best way to fix this is. In this patch, I
tried to use PAUSED state with STARTING_UP reason. Alternatively, we
could keep using SHUTOFF state and just set STARTING_UP reason instead
of UNKNOWN but it just feels wrong and wouldn't really solve the
confusion when looking at virsh list.
I made the change to qemu driver only in this RFC patch, I will update
all drivers once we agree on the best approach.
Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
include/libvirt/libvirt-domain.h | 1 +
src/conf/domain_conf.c | 3 ++-
src/qemu/qemu_process.c | 22 ++++++++++++++--------
tools/virsh-domain-monitor.c | 3 ++-
4 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 4dbd7f5..90150f6 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -116,6 +116,7 @@ typedef enum {
VIR_DOMAIN_PAUSED_SHUTTING_DOWN = 8, /* paused during shutdown process */
VIR_DOMAIN_PAUSED_SNAPSHOT = 9, /* paused while creating a snapshot */
VIR_DOMAIN_PAUSED_CRASHED = 10, /* paused due to a guest crash */
+ VIR_DOMAIN_PAUSED_STARTING_UP = 11, /* the domain is being started */
# ifdef VIR_ENUM_SENTINELS
VIR_DOMAIN_PAUSED_LAST
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index b3d63f8..2b7c5bf 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -661,7 +661,8 @@ VIR_ENUM_IMPL(virDomainPausedReason, VIR_DOMAIN_PAUSED_LAST,
"from snapshot",
"shutdown",
"snapshot",
- "panicked")
+ "panicked",
+ "starting up")
VIR_ENUM_IMPL(virDomainShutdownReason, VIR_DOMAIN_SHUTDOWN_LAST,
"unknown",
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 1d4e957..d317b19 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3412,6 +3412,7 @@ qemuProcessUpdateState(virQEMUDriverPtr driver, virDomainObjPtr vm)
virDomainState state;
virDomainPausedReason reason;
virDomainState newState = VIR_DOMAIN_NOSTATE;
+ int oldReason;
int newReason;
bool running;
char *msg = NULL;
@@ -3425,9 +3426,16 @@ qemuProcessUpdateState(virQEMUDriverPtr driver, virDomainObjPtr
vm)
if (ret < 0)
return -1;
- state = virDomainObjGetState(vm, NULL);
+ state = virDomainObjGetState(vm, &oldReason);
- if (state == VIR_DOMAIN_PAUSED && running) {
+ if (running &&
+ (state == VIR_DOMAIN_SHUTOFF ||
+ (state == VIR_DOMAIN_PAUSED &&
+ oldReason == VIR_DOMAIN_PAUSED_STARTING_UP))) {
+ newState = VIR_DOMAIN_RUNNING;
+ newReason = VIR_DOMAIN_RUNNING_BOOTED;
+ ignore_value(VIR_STRDUP_QUIET(msg, "finished booting"));
+ } else if (state == VIR_DOMAIN_PAUSED && running) {
newState = VIR_DOMAIN_RUNNING;
newReason = VIR_DOMAIN_RUNNING_UNPAUSED;
ignore_value(VIR_STRDUP_QUIET(msg, "was unpaused"));
@@ -3446,10 +3454,6 @@ qemuProcessUpdateState(virQEMUDriverPtr driver, virDomainObjPtr
vm)
ignore_value(virAsprintf(&msg, "was paused (%s)",
virDomainPausedReasonTypeToString(reason)));
}
- } else if (state == VIR_DOMAIN_SHUTOFF && running) {
- newState = VIR_DOMAIN_RUNNING;
- newReason = VIR_DOMAIN_RUNNING_BOOTED;
- ignore_value(VIR_STRDUP_QUIET(msg, "finished booting"));
}
if (newState != VIR_DOMAIN_NOSTATE) {
@@ -3817,7 +3821,9 @@ qemuProcessReconnect(void *opaque)
goto error;
state = virDomainObjGetState(obj, &reason);
- if (state == VIR_DOMAIN_SHUTOFF) {
+ if (state == VIR_DOMAIN_SHUTOFF ||
+ (state == VIR_DOMAIN_PAUSED &&
+ reason == VIR_DOMAIN_PAUSED_STARTING_UP)) {
VIR_DEBUG("Domain '%s' wasn't fully started yet, killing
it",
obj->def->name);
goto error;
@@ -4435,7 +4441,7 @@ int qemuProcessStart(virConnectPtr conn,
vm->def->id = qemuDriverAllocateID(driver);
qemuDomainSetFakeReboot(driver, vm, false);
- virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_UNKNOWN);
+ virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_STARTING_UP);
if (virAtomicIntInc(&driver->nactive) == 1 &&
driver->inhibitCallback)
driver->inhibitCallback(true, driver->inhibitOpaque);
diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c
index 925eb1b..da23ace 100644
--- a/tools/virsh-domain-monitor.c
+++ b/tools/virsh-domain-monitor.c
@@ -184,7 +184,8 @@ VIR_ENUM_IMPL(vshDomainPausedReason,
N_("from snapshot"),
N_("shutting down"),
N_("creating snapshot"),
- N_("crashed"))
+ N_("crashed"),
+ N_("starting up"))
VIR_ENUM_DECL(vshDomainShutdownReason)
VIR_ENUM_IMPL(vshDomainShutdownReason,
--
2.3.0