[libvirt] [PATCH 1/2] ESX: Allow method calls for VI version > 2.5

Dawid Zamirski dzamirski at dattobackup.com
Thu Mar 27 22:24:23 UTC 2014


Currently, ESX driver can only issue VI method calls available in version
2.5. To send method calls available in newer versions, a SOAPAction
header needs to be set in the following format:

'SOAPAction: "urn:vim25/<version_number>"'

This patch modifies the Python code generator to optionally read
'apiVersion' token from .input file  which is then passed to the
ESX_VI_METHOD macro. If the apiVersion is not specified, "2.5" is passed
by default. Finally, the esx_VI_Context_Execute function takes this
argument and conditionally sets SOAPAction header, performs CURL
request, and then unsets it again so that any subsequest 2.5 call gets
2.5 formatted XML response.

In conclusion, this patch allows to make method calls for VI API greater
than v2.5 wthout braking existing v2.5 calls.
---
 src/esx/esx_vi.c            | 26 +++++++++++++++++++++++++-
 src/esx/esx_vi.h            |  2 +-
 src/esx/esx_vi_generator.py | 20 +++++++++++++++-----
 src/esx/esx_vi_methods.c    | 12 +++++++-----
 4 files changed, 48 insertions(+), 12 deletions(-)

diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index 6188139..393a009 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -1224,7 +1224,7 @@ esxVI_Context_LookupManagedObjectsByHostSystemIp(esxVI_Context *ctx,
 int
 esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName,
                       const char *request, esxVI_Response **response,
-                      esxVI_Occurrence occurrence)
+                      esxVI_Occurrence occurrence, const char *apiVersion)
 {
     int result = -1;
     virBuffer buffer = VIR_BUFFER_INITIALIZER;
@@ -1232,6 +1232,8 @@ esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName,
     char *xpathExpression = NULL;
     xmlXPathContextPtr xpathContext = NULL;
     xmlNodePtr responseNode = NULL;
+    char *versionHeader = NULL;
+    struct curl_slist *origHeader = NULL;
 
     if (!request || !response || *response) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
@@ -1251,8 +1253,29 @@ esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName,
     curl_easy_setopt(ctx->curl->handle, CURLOPT_POSTFIELDS, request);
     curl_easy_setopt(ctx->curl->handle, CURLOPT_POSTFIELDSIZE, strlen(request));
 
+    if (!STRPREFIX(apiVersion, "2.5")) {
+        origHeader = ctx->curl->headers;
+
+        virBufferAsprintf(&buffer, "SOAPAction: \"urn:vim25/%s\"", apiVersion);
+        versionHeader = virBufferContentAndReset(&buffer);
+
+        ctx->curl->headers = curl_slist_append(ctx->curl->headers,
+                                               versionHeader);
+        curl_easy_setopt(ctx->curl->handle, CURLOPT_HTTPHEADER,
+                         ctx->curl->headers);
+    }
+
     (*response)->responseCode = esxVI_CURL_Perform(ctx->curl, ctx->url);
 
+    if (origHeader) {
+        curl_slist_free_all(origHeader->next);
+        origHeader->next = NULL;
+
+        ctx->curl->headers = origHeader;
+        curl_easy_setopt(ctx->curl->handle, CURLOPT_HTTPHEADER,
+                         ctx->curl->headers);
+    }
+
     virMutexUnlock(&ctx->curl->lock);
 
     if ((*response)->responseCode < 0) {
@@ -1403,6 +1426,7 @@ esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName,
     }
 
     VIR_FREE(xpathExpression);
+    VIR_FREE(versionHeader);
     xmlXPathFreeContext(xpathContext);
 
     return result;
diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
index 7cc2f71..15c2529 100644
--- a/src/esx/esx_vi.h
+++ b/src/esx/esx_vi.h
@@ -245,7 +245,7 @@ int esxVI_Context_LookupManagedObjectsByHostSystemIp(esxVI_Context *ctx,
                                                      const char *hostSystemIpAddress);
 int esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName,
                           const char *request, esxVI_Response **response,
-                          esxVI_Occurrence occurrence);
+                          esxVI_Occurrence occurrence, const char *apiVersion);
 
 
 
diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py
index 0b75f18..f571b36 100755
--- a/src/esx/esx_vi_generator.py
+++ b/src/esx/esx_vi_generator.py
@@ -188,11 +188,12 @@ class Parameter(Member):
 
 
 class Method:
-    def __init__(self, name, parameters, returns):
+    def __init__(self, name, parameters, returns, apiVersion):
         self.name = name
         self.parameters = []
         self.autobind_parameter = None
         self.returns = returns
+        self.apiVersion = apiVersion
 
         for parameter in parameters:
             if parameter.autobind_name is None:
@@ -282,7 +283,7 @@ class Method:
         for parameter in self.parameters:
             source += parameter.generate_serialize_code()
 
-        source += "})\n\n\n\n"
+        source += "}, %s)\n\n\n\n" % self.apiVersion
 
         return source
 
@@ -1276,6 +1277,8 @@ def parse_method(block):
     # expected format: method <name> [returns <type> <occurrence>]
     header_items = block[0][1].split()
 
+    apiVersion = 2.5
+
     if len(header_items) < 2:
         report_error("line %d: invalid block header" % (number))
 
@@ -1285,11 +1288,18 @@ def parse_method(block):
     returns = None
 
     if len(header_items) > 2:
-        if header_items[2] != "returns":
+        if header_items[2] not in ["returns", "apiVersion"]:
             report_error("line %d: invalid block header" % (number))
-        else:
+        elif header_items[2] == "returns":
             returns = Parameter(type=header_items[3], name="output",
                                 occurrence=header_items[4])
+            if len(header_items) > 5:
+              if header_items[5] != "apiVersion":
+                report_error("line %d: invalid block header" % (number))
+              else:
+                apiVersion = header_items[6]
+        else:
+            apiVersion = header_items[3]
 
     parameters = []
 
@@ -1306,7 +1316,7 @@ def parse_method(block):
         parameters.append(Parameter(type=items[0], name=items[1],
                                     occurrence=items[2]))
 
-    return Method(name=name, parameters=parameters, returns=returns)
+    return Method(name=name, parameters=parameters, returns=returns, apiVersion=apiVersion)
 
 
 
diff --git a/src/esx/esx_vi_methods.c b/src/esx/esx_vi_methods.c
index 0fdd0cd..f7d30d0 100644
--- a/src/esx/esx_vi_methods.c
+++ b/src/esx/esx_vi_methods.c
@@ -83,7 +83,6 @@
     }
 
 
-
 #define ESX_VI__METHOD__DESERIALIZE_OUTPUT__OptionalItem(_type, _suffix)      \
     if (response->node &&                                                     \
         esxVI_##_type##_Deserialize##_suffix(response->node, output) < 0) {   \
@@ -102,12 +101,13 @@
 
 #define ESX_VI__METHOD(_name, _this_from_service, _parameters, _output_type,  \
                        _deserialize_suffix, _occurrence, _validate,           \
-                       _serialize)                                            \
+                       _serialize, _apiVersion)                               \
     int                                                                       \
     esxVI_##_name _parameters                                                 \
     {                                                                         \
         int result = -1;                                                      \
         const char *methodName = #_name;                                      \
+        const char *apiVersion = #_apiVersion;                                \
         virBuffer buffer = VIR_BUFFER_INITIALIZER;                            \
         char *request = NULL;                                                 \
         esxVI_Response *response = NULL;                                      \
@@ -134,7 +134,8 @@
         request = virBufferContentAndReset(&buffer);                          \
                                                                               \
         if (esxVI_Context_Execute(ctx, methodName, request, &response,        \
-                                  esxVI_Occurrence_##_occurrence) < 0) {      \
+                                  esxVI_Occurrence_##_occurrence,             \
+                                  apiVersion) < 0) {                          \
             goto cleanup;                                                     \
         }                                                                     \
                                                                               \
@@ -240,7 +241,8 @@ esxVI_RetrieveServiceContent(esxVI_Context *ctx,
     }
 
     if (esxVI_Context_Execute(ctx, "RetrieveServiceContent", request,
-                              &response, esxVI_Occurrence_RequiredItem) < 0 ||
+                              &response, esxVI_Occurrence_RequiredItem,
+                              "2.5") < 0 ||
         esxVI_ServiceContent_Deserialize(response->node, serviceContent) < 0) {
         goto cleanup;
     }
@@ -279,7 +281,7 @@ ESX_VI__METHOD(ValidateMigration, /* special _this */,
     ESX_VI__METHOD__PARAMETER__SERIALIZE_LIST(String, testType)
     ESX_VI__METHOD__PARAMETER__SERIALIZE(ManagedObjectReference, pool)
     ESX_VI__METHOD__PARAMETER__SERIALIZE(ManagedObjectReference, host)
-})
+}, 2.5)
 
 
 
-- 
1.9.0




More information about the libvir-list mailing list