bhyve: implement the virDomainRename API

Implementation is fairly similar to the one found in the test and qemu
drivers. Lack of checkpoint and snapshot support in the bhyve driver
makes the implementation a bit simpler.

Signed-off-by: Roman Bogorodskiy <bogorodskiy@gmail.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
This commit is contained in:
Roman Bogorodskiy committed 2026-07-10 18:36:33 +02:00
1 parent 635b976879
commit 0526e5f5f5
3 files changed
+153

No files matched your search

+27
View File
@@ -703,3 +703,30 @@ virBhyveDomainObjStopWorker(virDomainObj *dom)
g_object_unref(eventThread);
virObjectLock(dom);
}
int
bhyveDomainNamePathsCleanup(const char *name,
bool bestEffort)
{
g_autofree char *cfg_file = NULL;
g_autofree char *autostart_link = NULL;
cfg_file = virDomainConfigFile(BHYVE_CONFIG_DIR, name);
autostart_link = virDomainConfigFile(BHYVE_AUTOSTART_DIR, name);
if (virFileExists(cfg_file) &&
unlink(cfg_file) < 0) {
virReportSystemError(errno, _("Failed to unlink '%1$s'"), cfg_file);
if (!bestEffort)
return -1;
}
if (virFileIsLink(autostart_link) == 1 &&
unlink(autostart_link) < 0) {
virReportSystemError(errno, _("Failed to unlink '%1$s'"), autostart_link);
if (!bestEffort)
return -1;
}
return 0;
}
+1
View File
@@ -54,3 +54,4 @@ extern virXMLNamespace virBhyveDriverDomainXMLNamespace;
int virBhyveDomainObjStartWorker(virDomainObj *dom);
void virBhyveDomainObjStopWorker(virDomainObj *dom);
int bhyveDomainNamePathsCleanup(const char *name, bool bestEffort);
+125
View File
@@ -2683,6 +2683,130 @@ bhyveDomainAuthorizedSSHKeysSet(virDomainPtr domain,
return rv;
}
static int
bhyveDomainRenameCallback(virDomainObj *vm,
const char *new_name,
unsigned int flags,
void *opaque)
{
struct _bhyveConn *privconn = opaque;
virObjectEvent *event_new = NULL;
virObjectEvent *event_old = NULL;
int ret = -1;
virErrorPtr err = NULL;
g_autofree char *new_dom_name = NULL;
g_autofree char *old_dom_name = NULL;
g_autofree char *new_dom_cfg_file = NULL;
g_autofree char *new_dom_autostart_link = NULL;
virCheckFlags(0, ret);
if (strchr(new_name, '/')) {
virReportError(VIR_ERR_XML_ERROR,
_("name %1$s cannot contain '/'"), new_name);
return -1;
}
new_dom_name = g_strdup(new_name);
new_dom_cfg_file = virDomainConfigFile(BHYVE_CONFIG_DIR, new_dom_name);
if (bhyveDomainNamePathsCleanup(new_name, false) < 0)
goto cleanup;
if (vm->autostart) {
new_dom_autostart_link = virDomainConfigFile(BHYVE_AUTOSTART_DIR, new_dom_name);
if (symlink(new_dom_cfg_file, new_dom_autostart_link) < 0) {
virReportSystemError(errno,
_("Failed to create symlink '%1$s' to '%2$s'"),
new_dom_autostart_link, new_dom_cfg_file);
return -1;
}
}
/* Switch name in domain definition. */
old_dom_name = g_steal_pointer(&vm->def->name);
vm->def->name = g_steal_pointer(&new_dom_name);
if (virDomainDefSave(vm->def, privconn->xmlopt, BHYVE_CONFIG_DIR) < 0)
goto cleanup;
event_old = virDomainEventLifecycleNew(vm->def->id, old_dom_name, vm->def->uuid,
VIR_DOMAIN_EVENT_UNDEFINED,
VIR_DOMAIN_EVENT_UNDEFINED_RENAMED);
event_new = virDomainEventLifecycleNewFromObj(vm,
VIR_DOMAIN_EVENT_DEFINED,
VIR_DOMAIN_EVENT_DEFINED_RENAMED);
virObjectEventStateQueue(privconn->domainEventState, event_old);
virObjectEventStateQueue(privconn->domainEventState, event_new);
ret = 0;
cleanup:
if (ret < 0) {
if (old_dom_name) {
new_dom_name = vm->def->name;
vm->def->name = old_dom_name;
old_dom_name = NULL;
}
virErrorPreserveLast(&err);
bhyveDomainNamePathsCleanup(new_dom_name, true);
} else {
bhyveDomainNamePathsCleanup(old_dom_name, true);
}
virErrorRestore(&err);
return ret;
}
static int
bhyveDomainRename(virDomainPtr domain,
const char *new_name,
unsigned int flags)
{
struct _bhyveConn *privconn = domain->conn->privateData;
virDomainObj *vm = NULL;
int ret = -1;
virCheckFlags(0, ret);
if (!(vm = bhyveDomObjFromDomain(domain)))
goto cleanup;
if (virDomainRenameEnsureACL(domain->conn, vm->def) < 0)
goto cleanup;
if (virDomainObjBeginJob(vm, VIR_JOB_MODIFY) < 0)
goto cleanup;
if (!vm->persistent) {
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
_("cannot rename a transient domain"));
goto endjob;
}
if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_SHUTOFF) {
virReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("domain has to be shutoff before renaming"));
goto endjob;
}
if (virDomainObjListRename(privconn->domains, vm, new_name, flags,
bhyveDomainRenameCallback, privconn) < 0)
goto endjob;
/* Success, domain has been renamed. */
ret = 0;
endjob:
virDomainObjEndJob(vm);
cleanup:
virDomainObjEndAPI(&vm);
return ret;
}
static virHypervisorDriver bhyveHypervisorDriver = {
.name = "bhyve",
.connectURIProbe = bhyveConnectURIProbe,
@@ -2760,6 +2884,7 @@ static virHypervisorDriver bhyveHypervisorDriver = {
.domainSetUserPassword = bhyveDomainSetUserPassword, /* 12.6.0 */
.domainAuthorizedSSHKeysGet = bhyveDomainAuthorizedSSHKeysGet, /* 12.6.0 */
.domainAuthorizedSSHKeysSet = bhyveDomainAuthorizedSSHKeysSet, /* 12.6.0 */
.domainRename = bhyveDomainRename, /* 12.6.0 */
};