[PATCH 0/3] bhyve: implement virDomainSetLifecycleAction() API
Roman Bogorodskiy (3): bhyve: add validation for lifecycle actions bhyve: monitor: respect on_poweroff / on_reboot settings bhyve: implement virDomainSetLifecycleAction() API src/bhyve/bhyve_domain.c | 36 +++++++++++++ src/bhyve/bhyve_domain.h | 3 ++ src/bhyve/bhyve_driver.c | 110 ++++++++++++++++++++++++++++++++++++++ src/bhyve/bhyve_monitor.c | 20 +++++-- 4 files changed, 165 insertions(+), 4 deletions(-) -- 2.52.0
The bhyve driver currently supports redefining 'onPoweroff' and 'onReboot', and possible actions are 'destroy' and 'restart'. Redefining 'onCrash' is not supported. Validate all these in bhyveDomainDefValidate(). Signed-off-by: Roman Bogorodskiy <bogorodskiy@gmail.com> --- src/bhyve/bhyve_domain.c | 36 ++++++++++++++++++++++++++++++++++++ src/bhyve/bhyve_domain.h | 3 +++ 2 files changed, 39 insertions(+) diff --git a/src/bhyve/bhyve_domain.c b/src/bhyve/bhyve_domain.c index d5bb22501c..a215e562e7 100644 --- a/src/bhyve/bhyve_domain.c +++ b/src/bhyve/bhyve_domain.c @@ -462,6 +462,39 @@ bhyveDomainDeviceDefValidate(const virDomainDeviceDef *dev, } +int +bhyveValidateLifecycleAction(virDomainLifecycleAction onPoweroff, + virDomainLifecycleAction onReboot, + virDomainLifecycleAction onCrash) +{ + if ((onPoweroff != VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY && + onPoweroff != VIR_DOMAIN_LIFECYCLE_ACTION_RESTART) || + (onReboot != VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY && + onReboot != VIR_DOMAIN_LIFECYCLE_ACTION_RESTART)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("bhyve driver supports only 'restart' and 'destroy' actions for 'on_reboot'/'on_poweroff'")); + return -1; + } + + if (onCrash != VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("bhyve driver does not support 'on_crash' actions other than 'destroy'")); + return -1; + } + + return 0; +} + + +static int +bhyveValidateDomainLifecycleAction(const virDomainDef *def) +{ + return bhyveValidateLifecycleAction(def->onPoweroff, + def->onReboot, + def->onCrash); +} + + static int bhyveDomainDefValidate(const virDomainDef *def, void *opaque G_GNUC_UNUSED, @@ -549,6 +582,9 @@ bhyveDomainDefValidate(const virDomainDef *def, return -1; } + if (bhyveValidateDomainLifecycleAction(def) < 0) + return -1; + if (!def->os.loader) return 0; diff --git a/src/bhyve/bhyve_domain.h b/src/bhyve/bhyve_domain.h index fa7a685d59..c9fa776651 100644 --- a/src/bhyve/bhyve_domain.h +++ b/src/bhyve/bhyve_domain.h @@ -55,3 +55,6 @@ extern virXMLNamespace virBhyveDriverDomainXMLNamespace; int virBhyveDomainObjStartWorker(virDomainObj *dom); void virBhyveDomainObjStopWorker(virDomainObj *dom); int bhyveDomainNamePathsCleanup(const char *name, bool bestEffort); +int bhyveValidateLifecycleAction(virDomainLifecycleAction onPoweroff, + virDomainLifecycleAction onReboot, + virDomainLifecycleAction onCrash); -- 2.52.0
Currently, the bhyve driver respects domain's on_poweroff and on_reboot settings for when shutdown and reboot are triggered via libvirt API. However, they are not respected when the event is triggered within the guest. Address that by updating monitor to execute the configured action. Signed-off-by: Roman Bogorodskiy <bogorodskiy@gmail.com> --- src/bhyve/bhyve_monitor.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/bhyve/bhyve_monitor.c b/src/bhyve/bhyve_monitor.c index 8cf4b41ca3..3be5ae89ad 100644 --- a/src/bhyve/bhyve_monitor.c +++ b/src/bhyve/bhyve_monitor.c @@ -157,12 +157,24 @@ bhyveMonitorIO(int watch, int kq, int events G_GNUC_UNUSED, void *opaque) } else if (WIFEXITED(status)) { if (WEXITSTATUS(status) == 0 || mon->reboot) { /* 0 - reboot */ - VIR_INFO("Guest %s rebooted; restarting domain.", name); - virBhyveProcessRestart(driver, vm); + if (vm->def->onReboot == VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY || + vm->def->onReboot == VIR_DOMAIN_LIFECYCLE_ACTION_PRESERVE) { + VIR_INFO("Guest %s rebooted; domain on_reboot setting overridden, shutting down.", name); + virBhyveProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN); + } else { + VIR_INFO("Guest %s rebooted; restarting domain.", name); + virBhyveProcessRestart(driver, vm); + } } else if (WEXITSTATUS(status) < 3) { /* 1 - shutdown, 2 - halt, 3 - triple fault. others - error */ - VIR_INFO("Guest %s shut itself down; destroying domain.", name); - virBhyveProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN); + if (vm->def->onPoweroff == VIR_DOMAIN_LIFECYCLE_ACTION_RESTART || + vm->def->onPoweroff == VIR_DOMAIN_LIFECYCLE_ACTION_RESTART_RENAME) { + VIR_INFO("Guest %s shut itself down; domain on_poweroff setting overridden, attempting reboot.", name); + virBhyveProcessRestart(driver, vm); + } else { + VIR_INFO("Guest %s shut itself down; destroying domain.", name); + virBhyveProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN); + } } else { VIR_INFO("Guest %s had an error and exited with status %d; destroying domain.", name, WEXITSTATUS(status)); -- 2.52.0
Implement virDomainSetLifecycleAction() API for the bhyve driver. Support both config and live configuration update. Signed-off-by: Roman Bogorodskiy <bogorodskiy@gmail.com> --- src/bhyve/bhyve_driver.c | 110 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/src/bhyve/bhyve_driver.c b/src/bhyve/bhyve_driver.c index 668e46ad37..feeb140ba4 100644 --- a/src/bhyve/bhyve_driver.c +++ b/src/bhyve/bhyve_driver.c @@ -2807,6 +2807,115 @@ bhyveDomainRename(virDomainPtr domain, return ret; } +static int +bhyveDomainSetLifecycleActionValidate(virDomainDef *def, + virDomainLifecycle type, + virDomainLifecycleAction action) +{ + virDomainLifecycleAction onPoweroff = def->onPoweroff; + virDomainLifecycleAction onReboot = def->onReboot; + virDomainLifecycleAction onCrash = def->onCrash; + + switch (type) { + case VIR_DOMAIN_LIFECYCLE_POWEROFF: + onPoweroff = action; + break; + case VIR_DOMAIN_LIFECYCLE_REBOOT: + onReboot = action; + break; + case VIR_DOMAIN_LIFECYCLE_CRASH: + onCrash = action; + break; + case VIR_DOMAIN_LIFECYCLE_LAST: + break; + } + + if (bhyveValidateLifecycleAction(onPoweroff, onReboot, onCrash) < 0) + return -1; + + return 0; +} + +static void +bhyveDomainModifyLifecycleAction(virDomainDef *def, + virDomainLifecycle type, + virDomainLifecycleAction action) +{ + switch (type) { + case VIR_DOMAIN_LIFECYCLE_POWEROFF: + def->onPoweroff = action; + break; + case VIR_DOMAIN_LIFECYCLE_REBOOT: + def->onReboot = action; + break; + case VIR_DOMAIN_LIFECYCLE_CRASH: + def->onCrash = action; + break; + case VIR_DOMAIN_LIFECYCLE_LAST: + break; + } +} + +static int +bhyveDomainSetLifecycleAction(virDomainPtr domain, + unsigned int type, + unsigned int action, + unsigned int flags) +{ + struct _bhyveConn *privconn = domain->conn->privateData; + virDomainObj *vm = NULL; + virDomainDef *def = NULL; + virDomainDef *persistentDef = NULL; + int ret = -1; + + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, -1); + + if (!virDomainDefLifecycleActionAllowed(type, action)) + goto cleanup; + + if (!(vm = bhyveDomObjFromDomain(domain))) + return -1; + + if (virDomainSetLifecycleActionEnsureACL(domain->conn, vm->def) < 0) + goto cleanup; + + if (virDomainObjBeginJob(vm, VIR_JOB_MODIFY) < 0) + goto cleanup; + + if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0) + goto endjob; + + if ((def && bhyveDomainSetLifecycleActionValidate(def, type, action) < 0) || + (persistentDef && bhyveDomainSetLifecycleActionValidate(persistentDef, type, action) < 0)) + goto endjob; + + if (def) { + bhyveDomainModifyLifecycleAction(def, type, action); + + if (virDomainObjSave(vm, privconn->xmlopt, + BHYVE_STATE_DIR) < 0) + goto endjob; + } + + if (persistentDef) { + bhyveDomainModifyLifecycleAction(persistentDef, type, action); + + if (virDomainDefSave(persistentDef, privconn->xmlopt, + BHYVE_CONFIG_DIR) < 0) + goto endjob; + } + + ret = 0; + + endjob: + virDomainObjEndJob(vm); + + cleanup: + virDomainObjEndAPI(&vm); + return ret; +} + static virHypervisorDriver bhyveHypervisorDriver = { .name = "bhyve", .connectURIProbe = bhyveConnectURIProbe, @@ -2885,6 +2994,7 @@ static virHypervisorDriver bhyveHypervisorDriver = { .domainAuthorizedSSHKeysGet = bhyveDomainAuthorizedSSHKeysGet, /* 12.6.0 */ .domainAuthorizedSSHKeysSet = bhyveDomainAuthorizedSSHKeysSet, /* 12.6.0 */ .domainRename = bhyveDomainRename, /* 12.6.0 */ + .domainSetLifecycleAction = bhyveDomainSetLifecycleAction, /* 12.7.0 */ }; -- 2.52.0
participants (1)
-
Roman Bogorodskiy