提交 46e76e8b 编写于 作者: M Matthias Bolte 提交者: Daniel Veillard

ESX simplify SOAP request and response handling

* src/esx/esx_vi.[ch]: convert esxVI_RemoteRequest_Execute() to a
  simpler esxVI_Context_Execute() version, remove esxVI_RemoteRequest
  and convert esxVI_RemoteResponse to esxVI_Response
* src/esx/esx_vi_methods.c: update and simplify callers to use
  esxVI_Context_Execute() instead of esxVI_RemoteRequest_Execute()
上级 03d28d73
...@@ -461,39 +461,21 @@ esxVI_Context_Download(virConnectPtr conn, esxVI_Context *ctx, const char *url, ...@@ -461,39 +461,21 @@ esxVI_Context_Download(virConnectPtr conn, esxVI_Context *ctx, const char *url,
goto failure; goto failure;
} }
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* RemoteRequest
*/
/* esxVI_RemoteRequest_Alloc */
ESX_VI__TEMPLATE__ALLOC(RemoteRequest);
/* esxVI_RemoteRequest_Free */
ESX_VI__TEMPLATE__FREE(RemoteRequest,
{
VIR_FREE(item->request);
VIR_FREE(item->xpathExpression);
});
int int
esxVI_RemoteRequest_Execute(virConnectPtr conn, esxVI_Context *ctx, esxVI_Context_Execute(virConnectPtr conn, esxVI_Context *ctx,
esxVI_RemoteRequest *remoteRequest, const char *request, const char *xpathExpression,
esxVI_RemoteResponse **remoteResponse, esxVI_Response **response, esxVI_Boolean expectList)
esxVI_Boolean expectList)
{ {
virBuffer buffer = VIR_BUFFER_INITIALIZER; virBuffer buffer = VIR_BUFFER_INITIALIZER;
esxVI_Fault *fault = NULL; esxVI_Fault *fault = NULL;
CURLcode errorCode; CURLcode errorCode;
if (remoteRequest == NULL || remoteRequest->request == NULL || if (request == NULL || response == NULL || *response != NULL) {
remoteResponse == NULL || *remoteResponse != NULL) {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument"); ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
goto failure; goto failure;
} }
if (esxVI_RemoteResponse_Alloc(conn, remoteResponse) < 0) { if (esxVI_Response_Alloc(conn, response) < 0) {
goto failure; goto failure;
} }
...@@ -501,10 +483,8 @@ esxVI_RemoteRequest_Execute(virConnectPtr conn, esxVI_Context *ctx, ...@@ -501,10 +483,8 @@ esxVI_RemoteRequest_Execute(virConnectPtr conn, esxVI_Context *ctx,
curl_easy_setopt(ctx->curl_handle, CURLOPT_URL, ctx->url); curl_easy_setopt(ctx->curl_handle, CURLOPT_URL, ctx->url);
curl_easy_setopt(ctx->curl_handle, CURLOPT_WRITEDATA, &buffer); curl_easy_setopt(ctx->curl_handle, CURLOPT_WRITEDATA, &buffer);
curl_easy_setopt(ctx->curl_handle, CURLOPT_POSTFIELDS, curl_easy_setopt(ctx->curl_handle, CURLOPT_POSTFIELDS, request);
remoteRequest->request); curl_easy_setopt(ctx->curl_handle, CURLOPT_POSTFIELDSIZE, strlen(request));
curl_easy_setopt(ctx->curl_handle, CURLOPT_POSTFIELDSIZE,
strlen(remoteRequest->request));
errorCode = curl_easy_perform(ctx->curl_handle); errorCode = curl_easy_perform(ctx->curl_handle);
...@@ -516,7 +496,7 @@ esxVI_RemoteRequest_Execute(virConnectPtr conn, esxVI_Context *ctx, ...@@ -516,7 +496,7 @@ esxVI_RemoteRequest_Execute(virConnectPtr conn, esxVI_Context *ctx,
} }
errorCode = curl_easy_getinfo(ctx->curl_handle, CURLINFO_RESPONSE_CODE, errorCode = curl_easy_getinfo(ctx->curl_handle, CURLINFO_RESPONSE_CODE,
&(*remoteResponse)->responseCode); &(*response)->responseCode);
if (errorCode != CURLE_OK) { if (errorCode != CURLE_OK) {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
...@@ -532,66 +512,62 @@ esxVI_RemoteRequest_Execute(virConnectPtr conn, esxVI_Context *ctx, ...@@ -532,66 +512,62 @@ esxVI_RemoteRequest_Execute(virConnectPtr conn, esxVI_Context *ctx,
goto failure; goto failure;
} }
(*remoteResponse)->response = virBufferContentAndReset(&buffer); (*response)->content = virBufferContentAndReset(&buffer);
if ((*remoteResponse)->responseCode == 500 || if ((*response)->responseCode == 500 ||
(remoteRequest->xpathExpression != NULL && (xpathExpression != NULL && (*response)->responseCode == 200)) {
(*remoteResponse)->responseCode == 200)) { (*response)->document = xmlReadDoc(BAD_CAST (*response)->content, "",
(*remoteResponse)->document = NULL, XML_PARSE_NONET);
xmlReadDoc(BAD_CAST(*remoteResponse)->response, "", NULL,
XML_PARSE_NONET);
if ((*remoteResponse)->document == NULL) { if ((*response)->document == NULL) {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Could not parse XML response"); "Could not parse XML response");
goto failure; goto failure;
} }
if (xmlDocGetRootElement((*remoteResponse)->document) == NULL) { if (xmlDocGetRootElement((*response)->document) == NULL) {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"XML response is an empty document"); "XML response is an empty document");
goto failure; goto failure;
} }
(*remoteResponse)->xpathContext = (*response)->xpathContext = xmlXPathNewContext((*response)->document);
xmlXPathNewContext((*remoteResponse)->document);
if ((*remoteResponse)->xpathContext == NULL) { if ((*response)->xpathContext == NULL) {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Could not create XPath context"); "Could not create XPath context");
goto failure; goto failure;
} }
xmlXPathRegisterNs((*remoteResponse)->xpathContext, BAD_CAST "soapenv", xmlXPathRegisterNs((*response)->xpathContext, BAD_CAST "soapenv",
BAD_CAST "http://schemas.xmlsoap.org/soap/envelope/"); BAD_CAST "http://schemas.xmlsoap.org/soap/envelope/");
xmlXPathRegisterNs((*remoteResponse)->xpathContext, BAD_CAST "vim", xmlXPathRegisterNs((*response)->xpathContext, BAD_CAST "vim",
BAD_CAST "urn:vim25"); BAD_CAST "urn:vim25");
if ((*remoteResponse)->responseCode == 500) { if ((*response)->responseCode == 500) {
(*remoteResponse)->node = (*response)->node =
virXPathNode(conn, "/soapenv:Envelope/soapenv:Body/soapenv:Fault", virXPathNode(conn, "/soapenv:Envelope/soapenv:Body/soapenv:Fault",
(*remoteResponse)->xpathContext); (*response)->xpathContext);
if ((*remoteResponse)->node == NULL) { if ((*response)->node == NULL) {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"HTTP response code %d. VI Fault is unknown, " "HTTP response code %d. VI Fault is unknown, "
"XPath evaluation failed", "XPath evaluation failed",
(int)(*remoteResponse)->responseCode); (int)(*response)->responseCode);
goto failure; goto failure;
} }
if (esxVI_Fault_Deserialize(conn, (*remoteResponse)->node, if (esxVI_Fault_Deserialize(conn, (*response)->node, &fault) < 0) {
&fault) < 0) {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"HTTP response code %d. VI Fault is unknown, " "HTTP response code %d. VI Fault is unknown, "
"deserialization failed", "deserialization failed",
(int)(*remoteResponse)->responseCode); (int)(*response)->responseCode);
goto failure; goto failure;
} }
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"HTTP response code %d. VI Fault: %s - %s", "HTTP response code %d. VI Fault: %s - %s",
(int)(*remoteResponse)->responseCode, (int)(*response)->responseCode,
fault->faultcode, fault->faultstring); fault->faultcode, fault->faultstring);
goto failure; goto failure;
...@@ -599,38 +575,36 @@ esxVI_RemoteRequest_Execute(virConnectPtr conn, esxVI_Context *ctx, ...@@ -599,38 +575,36 @@ esxVI_RemoteRequest_Execute(virConnectPtr conn, esxVI_Context *ctx,
xmlNodePtr *nodeSet = NULL; xmlNodePtr *nodeSet = NULL;
int nodeSet_size; int nodeSet_size;
nodeSet_size = virXPathNodeSet(conn, remoteRequest->xpathExpression, nodeSet_size = virXPathNodeSet(conn, xpathExpression,
(*remoteResponse)->xpathContext, (*response)->xpathContext,
&nodeSet); &nodeSet);
if (nodeSet_size < 0) { if (nodeSet_size < 0) {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"XPath evaluation of '%s' failed", "XPath evaluation of '%s' failed",
remoteRequest->xpathExpression); xpathExpression);
goto failure; goto failure;
} else if (nodeSet_size == 0) { } else if (nodeSet_size == 0) {
(*remoteResponse)->node = NULL; (*response)->node = NULL;
} else { } else {
(*remoteResponse)->node = nodeSet[0]; (*response)->node = nodeSet[0];
} }
VIR_FREE(nodeSet); VIR_FREE(nodeSet);
} else { } else {
(*remoteResponse)->node = (*response)->node = virXPathNode(conn, xpathExpression,
virXPathNode(conn, remoteRequest->xpathExpression, (*response)->xpathContext);
(*remoteResponse)->xpathContext);
if ((*remoteResponse)->node == NULL) { if ((*response)->node == NULL) {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"XPath evaluation of '%s' failed", "XPath evaluation of '%s' failed",
remoteRequest->xpathExpression); xpathExpression);
goto failure; goto failure;
} }
} }
} else if ((*remoteResponse)->responseCode != 200) { } else if ((*response)->responseCode != 200) {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"HTTP response code %d", "HTTP response code %d", (int)(*response)->responseCode);
(int)(*remoteResponse)->responseCode);
goto failure; goto failure;
} }
...@@ -639,7 +613,7 @@ esxVI_RemoteRequest_Execute(virConnectPtr conn, esxVI_Context *ctx, ...@@ -639,7 +613,7 @@ esxVI_RemoteRequest_Execute(virConnectPtr conn, esxVI_Context *ctx,
failure: failure:
free(virBufferContentAndReset(&buffer)); free(virBufferContentAndReset(&buffer));
esxVI_RemoteResponse_Free(remoteResponse); esxVI_Response_Free(response);
esxVI_Fault_Free(&fault); esxVI_Fault_Free(&fault);
return -1; return -1;
...@@ -653,16 +627,16 @@ esxVI_RemoteRequest_Execute(virConnectPtr conn, esxVI_Context *ctx, ...@@ -653,16 +627,16 @@ esxVI_RemoteRequest_Execute(virConnectPtr conn, esxVI_Context *ctx,
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* RemoteResponse * Response
*/ */
/* esxVI_RemoteResponse_Alloc */ /* esxVI_Response_Alloc */
ESX_VI__TEMPLATE__ALLOC(RemoteResponse); ESX_VI__TEMPLATE__ALLOC(Response);
/* esxVI_RemoteResponse_Free */ /* esxVI_Response_Free */
ESX_VI__TEMPLATE__FREE(RemoteResponse, ESX_VI__TEMPLATE__FREE(Response,
{ {
VIR_FREE(item->response); VIR_FREE(item->content);
xmlXPathFreeContext(item->xpathContext); xmlXPathFreeContext(item->xpathContext);
...@@ -1584,39 +1558,25 @@ esxVI_StartVirtualMachineTask(virConnectPtr conn, esxVI_Context *ctx, ...@@ -1584,39 +1558,25 @@ esxVI_StartVirtualMachineTask(virConnectPtr conn, esxVI_Context *ctx,
esxVI_ManagedObjectReference **task) esxVI_ManagedObjectReference **task)
{ {
int result = 0; int result = 0;
esxVI_RemoteRequest *remoteRequest = NULL; char *xpathExpression = NULL;
esxVI_RemoteResponse *remoteResponse = NULL; esxVI_Response *response = NULL;
if (esxVI_RemoteRequest_Alloc(conn, &remoteRequest) < 0) {
goto failure;
}
remoteRequest->request = (char *)request; if (virAsprintf(&xpathExpression,
if (virAsprintf(&remoteRequest->xpathExpression,
ESX_VI__SOAP__RESPONSE_XPATH("%s_Task"), name) < 0) { ESX_VI__SOAP__RESPONSE_XPATH("%s_Task"), name) < 0) {
virReportOOMError(conn); virReportOOMError(conn);
goto failure; goto failure;
} }
if (esxVI_RemoteRequest_Execute(conn, ctx, remoteRequest, &remoteResponse, if (esxVI_Context_Execute(conn, ctx, request, xpathExpression, &response,
esxVI_Boolean_False) < 0 || esxVI_Boolean_False) < 0 ||
esxVI_ManagedObjectReference_Deserialize esxVI_ManagedObjectReference_Deserialize(conn, response->node, task,
(conn, remoteResponse->node, task, "Task") < 0) { "Task") < 0) {
goto failure; goto failure;
} }
cleanup: cleanup:
/* VIR_FREE(xpathExpression);
* Remove values given by the caller from the data structures to prevent esxVI_Response_Free(&response);
* them from being freed by the call to esxVI_RemoteRequest_Free().
*/
if (remoteRequest != NULL) {
remoteRequest->request = NULL;
}
esxVI_RemoteRequest_Free(&remoteRequest);
esxVI_RemoteResponse_Free(&remoteResponse);
return result; return result;
...@@ -1682,13 +1642,13 @@ esxVI_StartSimpleVirtualMachineTask ...@@ -1682,13 +1642,13 @@ esxVI_StartSimpleVirtualMachineTask
int int
esxVI_SimpleVirtualMachineMethod(virConnectPtr conn, esxVI_Context *ctx, esxVI_SimpleVirtualMachineMethod(virConnectPtr conn, esxVI_Context *ctx,
const char *name, const char *name,
esxVI_ManagedObjectReference *virtualMachine) esxVI_ManagedObjectReference *virtualMachine)
{ {
int result = 0; int result = 0;
esxVI_RemoteRequest *remoteRequest = NULL;
esxVI_RemoteResponse *remoteResponse = NULL;
virBuffer buffer = VIR_BUFFER_INITIALIZER; virBuffer buffer = VIR_BUFFER_INITIALIZER;
char *request = NULL;
esxVI_Response *response = NULL;
if (ctx->service == NULL) { if (ctx->service == NULL) {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument"); ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
...@@ -1700,8 +1660,7 @@ esxVI_SimpleVirtualMachineMethod(virConnectPtr conn, esxVI_Context *ctx, ...@@ -1700,8 +1660,7 @@ esxVI_SimpleVirtualMachineMethod(virConnectPtr conn, esxVI_Context *ctx,
virBufferAdd(&buffer, name, -1); virBufferAdd(&buffer, name, -1);
virBufferAddLit(&buffer, " xmlns=\"urn:vim25\">"); virBufferAddLit(&buffer, " xmlns=\"urn:vim25\">");
if (esxVI_RemoteRequest_Alloc(conn, &remoteRequest) < 0 || if (esxVI_ManagedObjectReference_Serialize(conn, virtualMachine, "_this",
esxVI_ManagedObjectReference_Serialize(conn, virtualMachine, "_this",
&buffer, &buffer,
esxVI_Boolean_True) < 0) { esxVI_Boolean_True) < 0) {
goto failure; goto failure;
...@@ -1717,21 +1676,23 @@ esxVI_SimpleVirtualMachineMethod(virConnectPtr conn, esxVI_Context *ctx, ...@@ -1717,21 +1676,23 @@ esxVI_SimpleVirtualMachineMethod(virConnectPtr conn, esxVI_Context *ctx,
goto failure; goto failure;
} }
remoteRequest->request = virBufferContentAndReset(&buffer); request = virBufferContentAndReset(&buffer);
if (esxVI_RemoteRequest_Execute(conn, ctx, remoteRequest, &remoteResponse, if (esxVI_Context_Execute(conn, ctx, request, NULL, &response,
esxVI_Boolean_False) < 0) { esxVI_Boolean_False) < 0) {
goto failure; goto failure;
} }
cleanup: cleanup:
esxVI_RemoteRequest_Free(&remoteRequest); VIR_FREE(request);
esxVI_RemoteResponse_Free(&remoteResponse); esxVI_Response_Free(&response);
return result; return result;
failure: failure:
free(virBufferContentAndReset(&buffer)); if (request == NULL) {
request = virBufferContentAndReset(&buffer);
}
result = -1; result = -1;
......
...@@ -34,8 +34,7 @@ ...@@ -34,8 +34,7 @@
typedef enum _esxVI_APIVersion esxVI_APIVersion; typedef enum _esxVI_APIVersion esxVI_APIVersion;
typedef enum _esxVI_ProductVersion esxVI_ProductVersion; typedef enum _esxVI_ProductVersion esxVI_ProductVersion;
typedef struct _esxVI_Context esxVI_Context; typedef struct _esxVI_Context esxVI_Context;
typedef struct _esxVI_RemoteResponse esxVI_RemoteResponse; typedef struct _esxVI_Response esxVI_Response;
typedef struct _esxVI_RemoteRequest esxVI_RemoteRequest;
typedef struct _esxVI_Enumeration esxVI_Enumeration; typedef struct _esxVI_Enumeration esxVI_Enumeration;
typedef struct _esxVI_EnumerationValue esxVI_EnumerationValue; typedef struct _esxVI_EnumerationValue esxVI_EnumerationValue;
typedef struct _esxVI_List esxVI_List; typedef struct _esxVI_List esxVI_List;
...@@ -88,43 +87,26 @@ int esxVI_Context_Connect(virConnectPtr conn, esxVI_Context *ctx, ...@@ -88,43 +87,26 @@ int esxVI_Context_Connect(virConnectPtr conn, esxVI_Context *ctx,
const char *password, int noVerify); const char *password, int noVerify);
int esxVI_Context_Download(virConnectPtr conn, esxVI_Context *ctx, int esxVI_Context_Download(virConnectPtr conn, esxVI_Context *ctx,
const char *url, char **content); const char *url, char **content);
int esxVI_Context_Execute(virConnectPtr conn, esxVI_Context *ctx,
const char *request, const char *xpathExpression,
esxVI_Response **response, esxVI_Boolean expectList);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* RemoteRequest * Response
*/ */
struct _esxVI_RemoteRequest { struct _esxVI_Response {
char *request; /* required */
char *xpathExpression; /* optional */
};
int esxVI_RemoteRequest_Alloc(virConnectPtr conn,
esxVI_RemoteRequest **remoteRequest);
void esxVI_RemoteRequest_Free(esxVI_RemoteRequest **remoteRequest);
int esxVI_RemoteRequest_Execute(virConnectPtr conn, esxVI_Context *ctx,
esxVI_RemoteRequest *remoteRequest,
esxVI_RemoteResponse **remoteResponse,
esxVI_Boolean expectList);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* RemoteResponse
*/
struct _esxVI_RemoteResponse {
long responseCode; /* required */ long responseCode; /* required */
char *response; /* required */ char *content; /* required */
xmlDocPtr document; /* optional */ xmlDocPtr document; /* optional */
xmlXPathContextPtr xpathContext; /* optional */ xmlXPathContextPtr xpathContext; /* optional */
xmlNodePtr node; /* optional, list */ xmlNodePtr node; /* optional, list */
}; };
int esxVI_RemoteResponse_Alloc(virConnectPtr conn, int esxVI_Response_Alloc(virConnectPtr conn, esxVI_Response **response);
esxVI_RemoteResponse **remoteResponse); void esxVI_Response_Free(esxVI_Response **response);
void esxVI_RemoteResponse_Free(esxVI_RemoteResponse **remoteResponse);
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册