[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH v2] esx: Add domain autostart support



---

v2:
 - Don't enable the general autostart option if this affects the autostart
   behavior of other domains.
 - Refactor the lookup code for AutoStartDefaults and AutoStartPowerInfo into
   functions.

 src/esx/esx_driver.c           |  183 +++++++++++++++++++++++++++++++++++++++-
 src/esx/esx_vi.c               |  126 +++++++++++++++++++++++++++-
 src/esx/esx_vi.h               |    6 ++
 src/esx/esx_vi_generator.input |   60 +++++++++++++
 src/esx/esx_vi_generator.py    |    5 +-
 src/esx/esx_vi_types.c         |    6 ++
 src/esx/esx_vi_types.h         |    1 +
 7 files changed, 382 insertions(+), 5 deletions(-)

diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index 2241532..67325de 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -3199,6 +3199,185 @@ esxDomainUndefine(virDomainPtr domain)
 
 
 
+static int
+esxDomainGetAutostart(virDomainPtr domain, int *autostart)
+{
+    int result = -1;
+    esxPrivate *priv = domain->conn->privateData;
+    esxVI_AutoStartDefaults *defaults = NULL;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_ObjectContent *hostAutoStartManager = NULL;
+    esxVI_AutoStartPowerInfo *powerInfo = NULL;
+    esxVI_AutoStartPowerInfo *powerInfoList = NULL;
+    esxVI_ObjectContent *virtualMachine = NULL;
+
+    *autostart = 0;
+
+    if (esxVI_EnsureSession(priv->primary) < 0) {
+        return -1;
+    }
+
+    /* Check general autostart config */
+    if (esxVI_LookupAutoStartDefaults(priv->primary, &defaults) < 0) {
+        goto cleanup;
+    }
+
+    if (defaults->enabled != esxVI_Boolean_True) {
+        /* Autostart is disabled in general, exit early here */
+        result = 0;
+        goto cleanup;
+    }
+
+    /* Check specific autostart config */
+    if (esxVI_LookupAutoStartPowerInfoList(priv->primary, &powerInfoList) < 0) {
+        goto cleanup;
+    }
+
+    if (powerInfoList == NULL) {
+        /* powerInfo list is empty, exit early here */
+        result = 0;
+        goto cleanup;
+    }
+
+    if (esxVI_LookupVirtualMachineByUuid(priv->primary, domain->uuid,
+                                         NULL, &virtualMachine,
+                                         esxVI_Occurrence_RequiredItem) < 0) {
+        goto cleanup;
+    }
+
+    for (powerInfo = powerInfoList; powerInfo != NULL;
+         powerInfo = powerInfo->_next) {
+        if (STREQ(powerInfo->key->value, virtualMachine->obj->value)) {
+            if (STRCASEEQ(powerInfo->startAction, "powerOn")) {
+                *autostart = 1;
+            }
+
+            break;
+        }
+    }
+
+    result = 0;
+
+  cleanup:
+    esxVI_String_Free(&propertyNameList);
+    esxVI_ObjectContent_Free(&hostAutoStartManager);
+    esxVI_AutoStartDefaults_Free(&defaults);
+    esxVI_AutoStartPowerInfo_Free(&powerInfoList);
+    esxVI_ObjectContent_Free(&virtualMachine);
+
+    return result;
+}
+
+
+
+static int
+esxDomainSetAutostart(virDomainPtr domain, int autostart)
+{
+    int result = -1;
+    esxPrivate *priv = domain->conn->privateData;
+    esxVI_ObjectContent *virtualMachine = NULL;
+    esxVI_HostAutoStartManagerConfig *spec = NULL;
+    esxVI_AutoStartDefaults *defaults = NULL;
+    esxVI_AutoStartPowerInfo *powerInfoList = NULL;
+    esxVI_AutoStartPowerInfo *powerInfo = NULL;
+    esxVI_AutoStartPowerInfo *newPowerInfo = NULL;
+
+    if (esxVI_EnsureSession(priv->primary) < 0) {
+        return -1;
+    }
+
+    if (esxVI_LookupVirtualMachineByUuid(priv->primary, domain->uuid,
+                                         NULL, &virtualMachine,
+                                         esxVI_Occurrence_RequiredItem) < 0 ||
+        esxVI_HostAutoStartManagerConfig_Alloc(&spec) < 0) {
+        goto cleanup;
+    }
+
+    if (autostart) {
+        /*
+         * There is a general autostart option that affects the autostart
+         * behavior of all domains. If it's disabled then no domain does
+         * autostart. If it's enabled then the autostart behavior depends on
+         * the per-domain autostart config.
+         */
+        if (esxVI_LookupAutoStartDefaults(priv->primary, &defaults) < 0) {
+            goto cleanup;
+        }
+
+        if (defaults->enabled != esxVI_Boolean_True) {
+            /*
+             * Autostart is disabled in general. Check if no other domain is
+             * in the list of autostarted domains, so it's safe to enable the
+             * general autostart option without affecting the autostart
+             * behavior of other domains.
+             */
+            if (esxVI_LookupAutoStartPowerInfoList(priv->primary,
+                                                   &powerInfoList) < 0) {
+                goto cleanup;
+            }
+
+            for (powerInfo = powerInfoList; powerInfo != NULL;
+                 powerInfo = powerInfo->_next) {
+                if (STRNEQ(powerInfo->key->value, virtualMachine->obj->value)) {
+                    ESX_ERROR(VIR_ERR_OPERATION_INVALID, "%s",
+                              _("Cannot enable general autostart option "
+                                "without affecting other domains"));
+                    goto cleanup;
+                }
+            }
+
+            /* Enable autostart in general */
+            if (esxVI_AutoStartDefaults_Alloc(&spec->defaults) < 0) {
+                goto cleanup;
+            }
+
+            spec->defaults->enabled = esxVI_Boolean_True;
+        }
+    }
+
+    if (esxVI_AutoStartPowerInfo_Alloc(&newPowerInfo) < 0 ||
+        esxVI_Int_Alloc(&newPowerInfo->startOrder) < 0 ||
+        esxVI_Int_Alloc(&newPowerInfo->startDelay) < 0 ||
+        esxVI_Int_Alloc(&newPowerInfo->stopDelay) < 0 ||
+        esxVI_AutoStartPowerInfo_AppendToList(&spec->powerInfo,
+                                              newPowerInfo) < 0) {
+        goto cleanup;
+    }
+
+    newPowerInfo->key = virtualMachine->obj;
+    newPowerInfo->startOrder->value = -1; /* no specific start order */
+    newPowerInfo->startDelay->value = -1; /* use system default */
+    newPowerInfo->waitForHeartbeat = esxVI_AutoStartWaitHeartbeatSetting_SystemDefault;
+    newPowerInfo->startAction = autostart ? (char *)"powerOn" : (char *)"none";
+    newPowerInfo->stopDelay->value = -1; /* use system default */
+    newPowerInfo->stopAction = (char *)"none";
+
+    if (esxVI_ReconfigureAutostart
+          (priv->primary,
+           priv->primary->hostSystem->configManager->autoStartManager,
+           spec) < 0) {
+        goto cleanup;
+    }
+
+    result = 0;
+
+  cleanup:
+    if (newPowerInfo != NULL) {
+        newPowerInfo->key = NULL;
+        newPowerInfo->startAction = NULL;
+        newPowerInfo->stopAction = NULL;
+    }
+
+    esxVI_ObjectContent_Free(&virtualMachine);
+    esxVI_HostAutoStartManagerConfig_Free(&spec);
+    esxVI_AutoStartDefaults_Free(&defaults);
+    esxVI_AutoStartPowerInfo_Free(&powerInfoList);
+
+    return result;
+}
+
+
+
 /*
  * The scheduler interface exposes basically the CPU ResourceAllocationInfo:
  *
@@ -4406,8 +4585,8 @@ static virDriver esxDriver = {
     NULL,                            /* domainDetachDevice */
     NULL,                            /* domainDetachDeviceFlags */
     NULL,                            /* domainUpdateDeviceFlags */
-    NULL,                            /* domainGetAutostart */
-    NULL,                            /* domainSetAutostart */
+    esxDomainGetAutostart,           /* domainGetAutostart */
+    esxDomainSetAutostart,           /* domainSetAutostart */
     esxDomainGetSchedulerType,       /* domainGetSchedulerType */
     esxDomainGetSchedulerParameters, /* domainGetSchedulerParameters */
     esxDomainSetSchedulerParameters, /* domainSetSchedulerParameters */
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index 5dbf744..62b28a2 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -606,7 +606,8 @@ esxVI_Context_LookupObjectsByPath(esxVI_Context *ctx,
     esxVI_String_Free(&propertyNameList);
 
     if (esxVI_String_AppendValueListToList(&propertyNameList,
-                                           "name\0") < 0 ||
+                                           "name\0"
+                                           "configManager\0") < 0 ||
         esxVI_LookupObjectContentByType(ctx, ctx->computeResource->_reference,
                                         "HostSystem", propertyNameList,
                                         &hostSystemList) < 0) {
@@ -680,7 +681,8 @@ esxVI_Context_LookupObjectsByHostSystemIp(esxVI_Context *ctx,
 
     /* Lookup HostSystem */
     if (esxVI_String_AppendValueListToList(&propertyNameList,
-                                           "name\0") < 0 ||
+                                           "name\0"
+                                           "configManager\0") < 0 ||
         esxVI_FindByIp(ctx, NULL, hostSystemIpAddress, esxVI_Boolean_False,
                        &managedObjectReference) < 0 ||
         esxVI_LookupObjectContentByType(ctx, managedObjectReference,
@@ -3375,6 +3377,126 @@ esxVI_LookupStorageVolumeKeyByDatastorePath(esxVI_Context *ctx,
 
 
 int
+esxVI_LookupAutoStartDefaults(esxVI_Context *ctx,
+                              esxVI_AutoStartDefaults **defaults)
+{
+    int result = -1;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_ObjectContent *hostAutoStartManager = NULL;
+    esxVI_DynamicProperty *dynamicProperty = NULL;
+
+    if (defaults == NULL || *defaults != NULL) {
+        ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
+        return -1;
+    }
+
+    /*
+     * Lookup HostAutoStartManagerConfig from the HostAutoStartManager because
+     * for some reason this is much faster than looking up the same info from
+     * the HostSystem config.
+     */
+    if (esxVI_String_AppendValueToList(&propertyNameList,
+                                       "config.defaults") < 0 ||
+        esxVI_LookupObjectContentByType
+          (ctx, ctx->hostSystem->configManager->autoStartManager,
+           "HostAutoStartManager", propertyNameList,
+           &hostAutoStartManager) < 0) {
+        goto cleanup;
+    }
+
+    if (hostAutoStartManager == NULL) {
+        ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+                     _("Could not retrieve the HostAutoStartManager object"));
+        goto cleanup;
+    }
+
+    for (dynamicProperty = hostAutoStartManager->propSet;
+         dynamicProperty != NULL; dynamicProperty = dynamicProperty->_next) {
+        if (STREQ(dynamicProperty->name, "config.defaults")) {
+            if (esxVI_AutoStartDefaults_CastFromAnyType(dynamicProperty->val,
+                                                        defaults) < 0) {
+                goto cleanup;
+            }
+
+            break;
+        }
+    }
+
+    if (*defaults == NULL) {
+        ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+                     _("Could not retrieve the AutoStartDefaults object"));
+        goto cleanup;
+    }
+
+    result = 0;
+
+  cleanup:
+    esxVI_String_Free(&propertyNameList);
+    esxVI_ObjectContent_Free(&hostAutoStartManager);
+
+    return result;
+}
+
+
+
+int
+esxVI_LookupAutoStartPowerInfoList(esxVI_Context *ctx,
+                                   esxVI_AutoStartPowerInfo **powerInfoList)
+{
+    int result = -1;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_ObjectContent *hostAutoStartManager = NULL;
+    esxVI_DynamicProperty *dynamicProperty = NULL;
+
+    if (powerInfoList == NULL || *powerInfoList != NULL) {
+        ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
+        return -1;
+    }
+
+    /*
+     * Lookup HostAutoStartManagerConfig from the HostAutoStartManager because
+     * for some reason this is much faster than looking up the same info from
+     * the HostSystem config.
+     */
+    if (esxVI_String_AppendValueToList(&propertyNameList,
+                                       "config.powerInfo") < 0 ||
+        esxVI_LookupObjectContentByType
+          (ctx, ctx->hostSystem->configManager->autoStartManager,
+           "HostAutoStartManager", propertyNameList,
+           &hostAutoStartManager) < 0) {
+        goto cleanup;
+    }
+
+    if (hostAutoStartManager == NULL) {
+        ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+                     _("Could not retrieve the HostAutoStartManager object"));
+        goto cleanup;
+    }
+
+    for (dynamicProperty = hostAutoStartManager->propSet;
+         dynamicProperty != NULL; dynamicProperty = dynamicProperty->_next) {
+        if (STREQ(dynamicProperty->name, "config.powerInfo")) {
+            if (esxVI_AutoStartPowerInfo_CastListFromAnyType
+                  (dynamicProperty->val, powerInfoList) < 0) {
+                goto cleanup;
+            }
+
+            break;
+        }
+    }
+
+    result = 0;
+
+  cleanup:
+    esxVI_String_Free(&propertyNameList);
+    esxVI_ObjectContent_Free(&hostAutoStartManager);
+
+    return result;
+}
+
+
+
+int
 esxVI_HandleVirtualMachineQuestion
   (esxVI_Context *ctx, esxVI_ManagedObjectReference *virtualMachine,
    esxVI_VirtualMachineQuestionInfo *questionInfo,
diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
index 553967b..b071c6c 100644
--- a/src/esx/esx_vi.h
+++ b/src/esx/esx_vi.h
@@ -418,6 +418,12 @@ int esxVI_LookupStorageVolumeKeyByDatastorePath(esxVI_Context *ctx,
                                                 const char *datastorePath,
                                                 char **key);
 
+int esxVI_LookupAutoStartDefaults(esxVI_Context *ctx,
+                                  esxVI_AutoStartDefaults **defaults);
+
+int esxVI_LookupAutoStartPowerInfoList(esxVI_Context *ctx,
+                                       esxVI_AutoStartPowerInfo **powerInfoList);
+
 int esxVI_HandleVirtualMachineQuestion
       (esxVI_Context *ctx,
        esxVI_ManagedObjectReference *virtualMachine,
diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input
index 2d903e4..44d1d9b 100644
--- a/src/esx/esx_vi_generator.input
+++ b/src/esx/esx_vi_generator.input
@@ -51,6 +51,13 @@
 # Enumerations
 #
 
+enum AutoStartWaitHeartbeatSetting
+    yes
+    no
+    systemDefault
+end
+
+
 enum ManagedEntityStatus
     gray
     green
@@ -140,6 +147,26 @@ object AboutInfo
 end
 
 
+object AutoStartDefaults
+    Boolean                                  enabled                        o
+    Int                                      startDelay                     o
+    Int                                      stopDelay                      o
+    Boolean                                  waitForHeartbeat               o
+    String                                   stopAction                     o
+end
+
+
+object AutoStartPowerInfo
+    ManagedObjectReference                   key                            r
+    Int                                      startOrder                     r
+    Int                                      startDelay                     r
+    AutoStartWaitHeartbeatSetting            waitForHeartbeat               r
+    String                                   startAction                    r
+    Int                                      stopDelay                      r
+    String                                   stopAction                     r
+end
+
+
 object ChoiceOption extends OptionType
     ElementDescription                       choiceInfo                     rl
     Int                                      defaultIndex                   o
@@ -234,6 +261,33 @@ object FolderFileQuery extends FileQuery
 end
 
 
+object HostAutoStartManagerConfig
+    AutoStartDefaults                        defaults                       o
+    AutoStartPowerInfo                       powerInfo                      ol
+end
+
+
+object HostConfigManager
+    ManagedObjectReference                   cpuScheduler                   o
+    ManagedObjectReference                   datastoreSystem                o
+    ManagedObjectReference                   memoryManager                  o
+    ManagedObjectReference                   storageSystem                  o
+    ManagedObjectReference                   networkSystem                  o
+    ManagedObjectReference                   vmotionSystem                  o
+    ManagedObjectReference                   serviceSystem                  o
+    ManagedObjectReference                   firewallSystem                 o
+    ManagedObjectReference                   advancedOption                 o
+    ManagedObjectReference                   diagnosticSystem               o
+    ManagedObjectReference                   autoStartManager               o
+    ManagedObjectReference                   snmpSystem                     o
+    ManagedObjectReference                   dateTimeSystem                 o
+    ManagedObjectReference                   patchManager                   o
+    ManagedObjectReference                   bootDeviceSystem               o
+    ManagedObjectReference                   firmwareSystem                 o
+    ManagedObjectReference                   healthStatusSystem             o
+end
+
+
 object HostCpuIdInfo
     Int                                      level                          r
     String                                   vendor                         o
@@ -843,6 +897,12 @@ method ReconfigVM_Task returns ManagedObjectReference r
 end
 
 
+method ReconfigureAutostart
+    ManagedObjectReference                   _this                          r
+    HostAutoStartManagerConfig               spec                           r
+end
+
+
 method RefreshDatastore
     ManagedObjectReference                   _this                          r
 end
diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py
index 4a8a9dc..3d068f3 100755
--- a/src/esx/esx_vi_generator.py
+++ b/src/esx/esx_vi_generator.py
@@ -1148,11 +1148,14 @@ additional_enum_features = { "ManagedEntityStatus"      : Enum.FEATURE__ANY_TYPE
                              "VirtualMachinePowerState" : Enum.FEATURE__ANY_TYPE }
 
 
-additional_object_features = { "DatastoreHostMount"         : Object.FEATURE__DEEP_COPY | Object.FEATURE__LIST | Object.FEATURE__ANY_TYPE,
+additional_object_features = { "AutoStartDefaults"          : Object.FEATURE__ANY_TYPE,
+                               "AutoStartPowerInfo"         : Object.FEATURE__ANY_TYPE | Object.FEATURE__LIST,
+                               "DatastoreHostMount"         : Object.FEATURE__DEEP_COPY | Object.FEATURE__LIST | Object.FEATURE__ANY_TYPE,
                                "DatastoreInfo"              : Object.FEATURE__ANY_TYPE | Object.FEATURE__DYNAMIC_CAST,
                                "Event"                      : Object.FEATURE__LIST,
                                "FileInfo"                   : Object.FEATURE__DYNAMIC_CAST,
                                "FileQuery"                  : Object.FEATURE__DYNAMIC_CAST,
+                               "HostConfigManager"          : Object.FEATURE__ANY_TYPE,
                                "HostCpuIdInfo"              : Object.FEATURE__ANY_TYPE | Object.FEATURE__LIST,
                                "HostDatastoreBrowserSearchResults" : Object.FEATURE__LIST | Object.FEATURE__ANY_TYPE,
                                "ManagedObjectReference"     : Object.FEATURE__ANY_TYPE,
diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c
index a70e1e0..4ee4110 100644
--- a/src/esx/esx_vi_types.c
+++ b/src/esx/esx_vi_types.c
@@ -1815,6 +1815,7 @@ ESX_VI__TEMPLATE__VALIDATE(HostSystem,
     ESX_VI__TEMPLATE__PROPERTY__REQUIRE(name);
 
     /* HostSystem */
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRE(configManager);
 })
 
 int
@@ -1851,6 +1852,11 @@ esxVI_HostSystem_CastFromObjectContent(esxVI_ObjectContent *objectContent,
                 virReportOOMError();
                 goto failure;
             }
+        } else if (STREQ(dynamicProperty->name, "configManager")) {
+            if (esxVI_HostConfigManager_CastFromAnyType
+                  (dynamicProperty->val, &(*hostSystem)->configManager) < 0) {
+                goto failure;
+            }
         }
     }
 
diff --git a/src/esx/esx_vi_types.h b/src/esx/esx_vi_types.h
index 64bf2dc..1ab39da 100644
--- a/src/esx/esx_vi_types.h
+++ b/src/esx/esx_vi_types.h
@@ -412,6 +412,7 @@ struct _esxVI_HostSystem {
     char *name;                                            /* required */
 
     /* HostSystem */
+    esxVI_HostConfigManager *configManager;                /* required */
 };
 
 int esxVI_HostSystem_Alloc(esxVI_HostSystem **hostSystem);
-- 
1.7.0.4


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]