}
static bool quit = false;
+static bool wantReboot = false;
static virMutex lock;
{
virLXCControllerPtr ctrl = opaque;
int ret;
+ int status;
- ret = waitpid(-1, NULL, WNOHANG);
+ ret = waitpid(-1, &status, WNOHANG);
if (ret == ctrl->initpid) {
virMutexLock(&lock);
quit = true;
+ if (WIFSIGNALED(status) &&
+ WTERMSIG(status) == SIGHUP)
+ wantReboot = true;
virMutexUnlock(&lock);
}
}
err = virGetLastError();
if (!err || err->code == VIR_ERR_OK)
- rc = 0;
+ rc = wantReboot ? 1 : 0;
cleanup:
virMutexDestroy(&lock);
case 0:
msg.status = VIR_LXC_PROTOCOL_EXIT_STATUS_SHUTDOWN;
break;
+ case 1:
+ msg.status = VIR_LXC_PROTOCOL_EXIT_STATUS_REBOOT;
+ break;
default:
msg.status = VIR_LXC_PROTOCOL_EXIT_STATUS_ERROR;
break;
return 0;
}
+static virConnectPtr
+virLXCProcessAutoDestroyGetConn(virLXCDriverPtr driver,
+ virDomainObjPtr vm)
+{
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(vm->def->uuid, uuidstr);
+ VIR_DEBUG("vm=%s uuid=%s", vm->def->name, uuidstr);
+ return virHashLookup(driver->autodestroy, uuidstr);
+}
+
+
+static int
+virLXCProcessReboot(virLXCDriverPtr driver,
+ virDomainObjPtr vm)
+{
+ virConnectPtr conn = virLXCProcessAutoDestroyGetConn(driver, vm);
+ int reason = vm->state.reason;
+ bool autodestroy = false;
+ int ret = -1;
+ virDomainDefPtr savedDef;
+
+ if (conn) {
+ virConnectRef(conn);
+ autodestroy = true;
+ } else {
+ conn = virConnectOpen("lxc:///");
+ /* Ignoring NULL conn which is mostly harmless here */
+ }
+
+ /* In a reboot scenario, we need to make sure we continue
+ * to use the current 'def', and not switch to 'newDef'.
+ * So temporarily hide the newDef and then reinstate it
+ */
+ savedDef = vm->newDef;
+ vm->newDef = NULL;
+ virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
+ vm->newDef = savedDef;
+ if (virLXCProcessStart(conn, driver, vm, autodestroy, reason) < 0) {
+ VIR_WARN("Unable to handle reboot of vm %s",
+ vm->def->name);
+ goto cleanup;
+ }
+
+ if (conn)
+ virConnectClose(conn);
+
+ ret = 0;
+
+cleanup:
+ return ret;
+}
+
/**
* virLXCProcessCleanup:
priv = vm->privateData;
virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
- if (!priv->doneStopEvent) {
- event = virDomainEventNewFromObj(vm,
- VIR_DOMAIN_EVENT_STOPPED,
- priv->stopReason);
- virDomainAuditStop(vm, "shutdown");
+ if (!priv->wantReboot) {
+ virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
+ if (!priv->doneStopEvent) {
+ event = virDomainEventNewFromObj(vm,
+ VIR_DOMAIN_EVENT_STOPPED,
+ priv->stopReason);
+ virDomainAuditStop(vm, "shutdown");
+ } else {
+ VIR_DEBUG("Stop event has already been sent");
+ }
+ if (!vm->persistent) {
+ virDomainRemoveInactive(&driver->domains, vm);
+ vm = NULL;
+ }
} else {
- VIR_DEBUG("Stop event has already been sent");
- }
- if (!vm->persistent) {
- virDomainRemoveInactive(&driver->domains, vm);
- vm = NULL;
+ int ret = virLXCProcessReboot(driver, vm);
+ virDomainAuditStop(vm, "reboot");
+ virDomainAuditStart(vm, "reboot", ret == 0);
+ if (ret == 0) {
+ event = virDomainEventRebootNewFromObj(vm);
+ } else {
+ event = virDomainEventNewFromObj(vm,
+ VIR_DOMAIN_EVENT_STOPPED,
+ priv->stopReason);
+ if (!vm->persistent) {
+ virDomainRemoveInactive(&driver->domains, vm);
+ vm = NULL;
+ }
+ }
}
if (vm)
case VIR_LXC_PROTOCOL_EXIT_STATUS_ERROR:
priv->stopReason = VIR_DOMAIN_EVENT_STOPPED_FAILED;
break;
+ case VIR_LXC_PROTOCOL_EXIT_STATUS_REBOOT:
+ priv->stopReason = VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN;
+ priv->wantReboot = true;
+ break;
default:
priv->stopReason = VIR_DOMAIN_EVENT_STOPPED_FAILED;
break;
}
priv->stopReason = VIR_DOMAIN_EVENT_STOPPED_FAILED;
+ priv->wantReboot = false;
vm->def->id = vm->pid;
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason);
priv->doneStopEvent = false;