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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list