[libvirt] [PATCH] Use PAUSED state for domains that are starting up

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. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- After going through all hypervisor drivers it seems none of them needs to be updated. That is, this patch matches the one I sent as RFC for design discussions. 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 9487b80..d5c148b 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 cc8616b..783c382 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 d1f089d..649b3df 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3418,6 +3418,7 @@ qemuProcessUpdateState(virQEMUDriverPtr driver, virDomainObjPtr vm) virDomainState state; virDomainPausedReason reason; virDomainState newState = VIR_DOMAIN_NOSTATE; + int oldReason; int newReason; bool running; char *msg = NULL; @@ -3431,9 +3432,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")); @@ -3452,10 +3460,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) { @@ -3828,7 +3832,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; @@ -4459,7 +4465,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 464ac11..30ddae4 100644 --- a/tools/virsh-domain-monitor.c +++ b/tools/virsh-domain-monitor.c @@ -199,7 +199,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.1

Jiri Denemark wrote:
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 recently noticed similar behavior in the libxl driver when starting large memory domains, which can take considerable time.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> ---
After going through all hypervisor drivers it seems none of them needs to be updated. That is, this patch matches the one I sent as RFC for design discussions.
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 9487b80..d5c148b 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 */
Cool. I'll use this in libxlDomainStart() in the libxl driver.
# ifdef VIR_ENUM_SENTINELS VIR_DOMAIN_PAUSED_LAST diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index cc8616b..783c382 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 d1f089d..649b3df 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3418,6 +3418,7 @@ qemuProcessUpdateState(virQEMUDriverPtr driver, virDomainObjPtr vm) virDomainState state; virDomainPausedReason reason; virDomainState newState = VIR_DOMAIN_NOSTATE; + int oldReason; int newReason; bool running; char *msg = NULL; @@ -3431,9 +3432,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")); @@ -3452,10 +3460,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) { @@ -3828,7 +3832,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; @@ -4459,7 +4465,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 464ac11..30ddae4 100644 --- a/tools/virsh-domain-monitor.c +++ b/tools/virsh-domain-monitor.c @@ -199,7 +199,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,
I'm no expert in the qemu driver code, but this looks sane to me. ACK. Regards, Jim

On Wed, Mar 11, 2015 at 14:20:02 -0600, Jim Fehlig wrote:
Jiri Denemark wrote:
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 recently noticed similar behavior in the libxl driver when starting large memory domains, which can take considerable time.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> ---
After going through all hypervisor drivers it seems none of them needs to be updated. That is, this patch matches the one I sent as RFC for design discussions.
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 9487b80..d5c148b 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 */
Cool. I'll use this in libxlDomainStart() in the libxl driver.
Hmm, I looked at all drivers including libxl and didn't find a good place put this change. I guess it's because I'm totally unfamiliar with libxl (driver).
I'm no expert in the qemu driver code, but this looks sane to me. ACK.
OK, given the previous design ACK from Daniel, I pushed this patch. Jirka
participants (2)
-
Jim Fehlig
-
Jiri Denemark