From: David Shane Holden <dpejesh(a)yahoo.com>
Signed-off-by: Roman Bogorodskiy <bogorodskiy(a)gmail.com>
---
src/bhyve/bhyve_driver.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++-
src/bhyve/bhyve_utils.h | 5 ++
2 files changed, 139 insertions(+), 1 deletion(-)
diff --git a/src/bhyve/bhyve_driver.c b/src/bhyve/bhyve_driver.c
index a524d35..b06463e 100644
--- a/src/bhyve/bhyve_driver.c
+++ b/src/bhyve/bhyve_driver.c
@@ -72,6 +72,44 @@ bhyveDriverUnlock(bhyveConnPtr driver)
virMutexUnlock(&driver->lock);
}
+static int
+bhyveAutostartDomain(virDomainObjPtr vm, void *opaque)
+{
+ const struct bhyveAutostartData *data = opaque;
+ int ret = 0;
+ virObjectLock(vm);
+ if (vm->autostart && !virDomainObjIsActive(vm)) {
+ virResetLastError();
+ ret = virBhyveProcessStart(data->conn, data->driver, vm,
+ VIR_DOMAIN_RUNNING_BOOTED, 0);
+ if (ret < 0) {
+ virErrorPtr err = virGetLastError();
+ VIR_ERROR(_("Failed to autostart VM '%s': %s"),
+ vm->def->name, err ? err->message : _("unknown
error"));
+ }
+ }
+ virObjectUnlock(vm);
+ return ret;
+}
+
+static void
+bhyveAutostartDomains(bhyveConnPtr driver)
+{
+ /* XXX: Figure out a better way todo this. The domain
+ * startup code needs a connection handle in order
+ * to lookup the bridge associated with a virtual
+ * network
+ */
+ virConnectPtr conn = virConnectOpen("bhyve:///system");
+ /* Ignoring NULL conn which is mostly harmless here */
+
+ struct bhyveAutostartData data = { driver, conn };
+
+ virDomainObjListForEach(driver->domains, bhyveAutostartDomain, &data);
+
+ virObjectUnref(conn);
+}
+
static virCapsPtr
bhyveBuildCapabilities(void)
{
@@ -262,6 +300,89 @@ cleanup:
}
static int
+bhyveDomainGetAutostart(virDomainPtr domain, int *autostart)
+{
+ virDomainObjPtr vm;
+ int ret = -1;
+
+ if (!(vm = bhyveDomObjFromDomain(domain)))
+ goto cleanup;
+
+ if (virDomainGetAutostartEnsureACL(domain->conn, vm->def) < 0)
+ goto cleanup;
+
+ *autostart = vm->autostart;
+ ret = 0;
+
+cleanup:
+ virObjectUnlock(vm);
+ return ret;
+}
+
+static int
+bhyveDomainSetAutostart(virDomainPtr domain, int autostart)
+{
+ virDomainObjPtr vm;
+ char *configFile = NULL;
+ char *autostartLink = NULL;
+ int ret = -1;
+
+ if (!(vm = bhyveDomObjFromDomain(domain)))
+ goto cleanup;
+
+ if (virDomainSetAutostartEnsureACL(domain->conn, vm->def) < 0)
+ goto cleanup;
+
+ if (!vm->persistent) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("cannot set autostart for transient domain"));
+ goto cleanup;
+ }
+
+ autostart = (autostart != 0);
+
+ if (vm->autostart != autostart) {
+ if ((configFile = virDomainConfigFile(BHYVE_CONFIG_DIR, vm->def->name)) ==
NULL)
+ goto cleanup;
+ if ((autostartLink = virDomainConfigFile(BHYVE_AUTOSTART_DIR,
vm->def->name)) == NULL)
+ goto cleanup;
+
+ if (autostart) {
+ if (virFileMakePath(BHYVE_AUTOSTART_DIR) < 0) {
+ virReportSystemError(errno,
+ _("cannot create autostart directory
%s"),
+ BHYVE_AUTOSTART_DIR);
+ goto cleanup;
+ }
+
+ if (symlink(configFile, autostartLink) < 0) {
+ virReportSystemError(errno,
+ _("Failed to create symlink '%s' to
'%s'"),
+ autostartLink, configFile);
+ goto cleanup;
+ }
+ } else {
+ if (unlink(autostartLink) < 0 && errno != ENOENT && errno
!= ENOTDIR) {
+ virReportSystemError(errno,
+ _("Failed to delete symlink
'%s'"),
+ autostartLink);
+ goto cleanup;
+ }
+ }
+
+ vm->autostart = autostart;
+ }
+
+ ret = 0;
+
+cleanup:
+ VIR_FREE(configFile);
+ VIR_FREE(autostartLink);
+ virObjectUnlock(vm);
+ return ret;
+}
+
+static int
bhyveDomainIsActive(virDomainPtr domain)
{
virDomainObjPtr obj;
@@ -701,7 +822,7 @@ bhyveStateInitialize(bool priveleged ATTRIBUTE_UNUSED,
if (virDomainObjListLoadAllConfigs(bhyve_driver->domains,
BHYVE_CONFIG_DIR,
- NULL, 0,
+ BHYVE_AUTOSTART_DIR, 0,
bhyve_driver->caps,
bhyve_driver->xmlopt,
1 << VIR_DOMAIN_VIRT_BHYVE,
@@ -715,6 +836,15 @@ cleanup:
return -1;
}
+static void
+bhyveStateAutoStart(void)
+{
+ if (!bhyve_driver)
+ return;
+
+ bhyveAutostartDomains(bhyve_driver);
+}
+
static int
bhyveConnectGetMaxVcpus(virConnectPtr conn ATTRIBUTE_UNUSED,
const char *type)
@@ -803,6 +933,8 @@ static virDriver bhyveDriver = {
.domainGetXMLDesc = bhyveDomainGetXMLDesc, /* 1.2.2 */
.domainIsActive = bhyveDomainIsActive, /* 1.2.2 */
.domainIsPersistent = bhyveDomainIsPersistent, /* 1.2.2 */
+ .domainGetAutostart = bhyveDomainGetAutostart, /* 1.2.3 */
+ .domainSetAutostart = bhyveDomainSetAutostart, /* 1.2.3 */
.nodeGetCPUStats = bhyveNodeGetCPUStats, /* 1.2.2 */
.nodeGetMemoryStats = bhyveNodeGetMemoryStats, /* 1.2.2 */
.nodeGetInfo = bhyveNodeGetInfo, /* 1.2.3 */
@@ -817,6 +949,7 @@ static virDriver bhyveDriver = {
static virStateDriver bhyveStateDriver = {
.name = "bhyve",
.stateInitialize = bhyveStateInitialize,
+ .stateAutoStart = bhyveStateAutoStart,
.stateCleanup = bhyveStateCleanup,
};
diff --git a/src/bhyve/bhyve_utils.h b/src/bhyve/bhyve_utils.h
index 6c76770..94f31b0 100644
--- a/src/bhyve/bhyve_utils.h
+++ b/src/bhyve/bhyve_utils.h
@@ -46,6 +46,11 @@ struct _bhyveConn {
typedef struct _bhyveConn bhyveConn;
typedef struct _bhyveConn *bhyveConnPtr;
+struct bhyveAutostartData {
+ bhyveConnPtr driver;
+ virConnectPtr conn;
+};
+
void bhyveDriverLock(bhyveConnPtr driver);
void bhyveDriverUnlock(bhyveConnPtr driver);
--
1.8.4.2