On 08/09/2016 08:39 AM, Jason Miesionczek wrote: > also added ability to get/set auto start > --- > src/hyperv/hyperv_driver.c | 101 +++++++ > src/hyperv/hyperv_wmi.c | 670 ++++++++++++++++++++++++++++++++++++++++++++- > src/hyperv/hyperv_wmi.h | 58 ++++ > src/hyperv/openwsman.h | 4 + > 4 files changed, 827 insertions(+), 6 deletions(-) > > diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c > index 861d5ab..aea7837 100644 > --- a/src/hyperv/hyperv_driver.c > +++ b/src/hyperv/hyperv_driver.c > @@ -1604,6 +1604,105 @@ hypervNodeGetFreeMemory(virConnectPtr conn) > return res; > } > > +static int > +hypervDomainSetAutostart(virDomainPtr domain, int autostart) > +{ > + int result = -1; > + invokeXmlParam *params = NULL; > + hypervPrivate *priv = domain->conn->privateData; > + virBuffer query = VIR_BUFFER_INITIALIZER; > + virBuffer queryVssd = VIR_BUFFER_INITIALIZER; > + Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL; > + properties_t *tab_props = NULL; > + eprParam eprparam; > + embeddedParam embeddedparam; > + int nb_params; > + char uuid_string[VIR_UUID_STRING_BUFLEN]; > + const char *selector = "CreationClassName=Msvm_VirtualSystemManagementService"; This should be a #define somewhere I think > + > + virUUIDFormat(domain->uuid, uuid_string); > + > + /* Prepare EPR param */ > + virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT); > + virBufferAsprintf(&query, "where Name = \"%s\"", uuid_string); > + eprparam.query = &query; > + eprparam.wmiProviderURI = ROOT_VIRTUALIZATION; > + > + /* Prepare EMBEDDED param */ > + virBufferAsprintf(&queryVssd, > + "associators of " > + "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\"," > + "Name=\"%s\"} " > + "where AssocClass = Msvm_SettingsDefineState " > + "ResultClass = Msvm_VirtualSystemSettingData", > + uuid_string); Again seems like some sort of #define for all the syntax > + > + if (hypervGetMsvmVirtualSystemSettingDataList(priv, &queryVssd, &virtualSystemSettingData) < 0) Long line - try 80 chars > + goto cleanup; > + > + embeddedparam.nbProps = 2; > + if (VIR_ALLOC_N(tab_props, embeddedparam.nbProps) < 0) > + goto cleanup; > + (*tab_props).name = "AutomaticStartupAction"; > + (*tab_props).val = autostart ? "2" : "0"; > + (*(tab_props+1)).name = "InstanceID"; > + (*(tab_props+1)).val = virtualSystemSettingData->data->InstanceID; Odd construct (*(tab_props+1)) why not tab_props[0]->name = "..." and tab_props[1]->name = "..." Those names could be constants too. > + > + embeddedparam.instanceName = "Msvm_VirtualSystemGlobalSettingData"; > + embeddedparam.prop_t = tab_props; > + > + /* Create invokeXmlParam tab */ > + nb_params = 2; > + if (VIR_ALLOC_N(params, nb_params) < 0) > + goto cleanup; > + (*params).name = "ComputerSystem"; > + (*params).type = EPR_PARAM; > + (*params).param = &eprparam; > + (*(params+1)).name = "SystemSettingData"; > + (*(params+1)).type = EMBEDDED_PARAM; > + (*(params+1)).param = &embeddedparam; More of the same with (*params) > + > + result = hypervInvokeMethod(priv, params, nb_params, "ModifyVirtualSystem", > + MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector); long line - put selector); on it's own line > + > + cleanup: > + hypervFreeObject(priv, (hypervObject *) virtualSystemSettingData); > + VIR_FREE(tab_props); > + VIR_FREE(params); > + virBufferFreeAndReset(&query); > + virBufferFreeAndReset(&queryVssd); > + > + return result; > +} > + > + > + > +static int > +hypervDomainGetAutostart(virDomainPtr domain, int *autostart) > +{ > + int result = -1; > + char uuid_string[VIR_UUID_STRING_BUFLEN]; > + hypervPrivate *priv = domain->conn->privateData; > + virBuffer query = VIR_BUFFER_INITIALIZER; > + Msvm_VirtualSystemGlobalSettingData *vsgsd = NULL; > + > + virUUIDFormat(domain->uuid, uuid_string); > + virBufferAddLit(&query, MSVM_VIRTUALSYSTEMGLOBALSETTINGDATA_WQL_SELECT); > + virBufferAsprintf(&query, "where SystemName = \"%s\"", uuid_string); > + > + if (hypervGetMsvmVirtualSystemGlobalSettingDataList(priv, &query, &vsgsd) < 0) Long line > + goto cleanup; > + > + *autostart = vsgsd->data->AutomaticStartupAction; > + result = 0; > + > + cleanup: > + hypervFreeObject(priv, (hypervObject *) vsgsd); > + virBufferFreeAndReset(&query); > + > + return result; > +} > + > static virHypervisorDriver hypervHypervisorDriver = { > .name = "Hyper-V", > .connectOpen = hypervConnectOpen, /* 0.9.5 */ > @@ -1645,6 +1744,8 @@ static virHypervisorDriver hypervHypervisorDriver = { > .domainGetMaxVcpus = hypervDomainGetMaxVcpus, /* 1.2.10 */ > .domainGetVcpusFlags = hypervDomainGetVcpusFlags, /* 1.2.10 */ > .domainGetVcpus = hypervDomainGetVcpus, /* 1.2.10 */ > + .domainSetAutostart = hypervDomainSetAutostart, /* 1.2.10 */ > + .domainGetAutostart = hypervDomainGetAutostart, /* 1.2.10 */ 2.3.0 at the earliest > }; > FWIW: It "feels" as if the hunks above should be separate from the hunks below. I believe above depends on below and below could be any patch before above. Although I assume this is what Matthias was referring to in his comments from patch 2. If that's the case, then this could be closer to patch 2 if it's kept. > /* Retrieves host system UUID */ > diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c > index 13acd09..51d9b43 100644 > --- a/src/hyperv/hyperv_wmi.c > +++ b/src/hyperv/hyperv_wmi.c > @@ -23,6 +23,7 @@ > */ > > #include <config.h> > +#include <wsman-soap.h> /* Where struct _WsXmlDoc is defined (necessary to dereference WsXmlDocH type) */ > > #include "internal.h" > #include "virerror.h" > @@ -33,15 +34,10 @@ > #include "hyperv_private.h" > #include "hyperv_wmi.h" > #include "virstring.h" > +#include "hyperv_wmi_cimtypes.generated.h" > > #define WS_SERIALIZER_FREE_MEM_WORKS 0 > > -#define ROOT_CIMV2 \ > - "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*" > - > -#define ROOT_VIRTUALIZATION \ > - "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/virtualization/*" > - > #define VIR_FROM_THIS VIR_FROM_HYPERV > > > @@ -667,6 +663,668 @@ hypervMsvmComputerSystemFromDomain(virDomainPtr domain, > return 0; > } > > +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * > + * hypervInvokeMethod > + * Function to invoke WSMAN request with simple, EPR or embedded parameters > + */ > + > +/* Create XML structure */ > +static int > +hypervCreateXmlStruct(const char *methodName, const char *classURI, > + WsXmlDocH *xmlDocRoot, WsXmlNodeH *xmlNodeMethod) > +{ > + virBuffer method_buff = VIR_BUFFER_INITIALIZER; > + char *methodNameInput = NULL; > + > + virBufferAsprintf(&method_buff, "%s_INPUT", methodName); > + methodNameInput = virBufferContentAndReset(&method_buff); > + > + if (methodNameInput == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + "%s", > + _("Could not create Xml Doc")); Overkill on the extra lines... Could put the "%s", on the same line as ReportError > + goto cleanup; > + } > + > + *xmlDocRoot = ws_xml_create_doc(NULL, methodNameInput); > + if (*xmlDocRoot == NULL) { Could go with "if (!(*xmlDocRoot = ws_xml_create_doc(...))) {" > + virReportError(VIR_ERR_INTERNAL_ERROR, > + "%s", > + _("Could not create Xml Doc with given parameter xmlDocRoot")); Likewise > + goto cleanup; > + } > + > + *xmlNodeMethod = xml_parser_get_root(*xmlDocRoot); > + if (*xmlNodeMethod == NULL) { Similar if construct > + virReportError(VIR_ERR_INTERNAL_ERROR, > + "%s", > + _("Could not get xmlDocRoot root node")); Likewise > + goto cleanup; > + } > + > + /* Add namespace to xmlNodeMethode */ > + ws_xml_set_ns(*xmlNodeMethod, classURI, "p"); > + > + VIR_FREE(methodNameInput); > + return 0; > + > + cleanup: > + > + virBufferFreeAndReset(&method_buff); > + VIR_FREE(methodNameInput); > + if (*xmlDocRoot != NULL) { > + ws_xml_destroy_doc(*xmlDocRoot); > + *xmlDocRoot = NULL; > + } > + > + return -1; > +} > + > + > +/* Look for the type of a given property class and specifies if it is an array */ > +static int > +hypervGetPropType(const char *className, const char *propName, const char **propType, bool *isArray) Long line - split args over multiple lines > +{ > + int i, y; Use 'size_t' not 'int' for loop variables Typically we use loop variables of i, j, k... I think taking this method tricks the checker though. > + > + i = 0; > + while (cimClasses[i].name[0] != '\0') { So I guess we're guaranteed this is a never ending loop by some other means? My question being - how is cimClasses constructed such that we know 'i' won't go beyond the number of elements in the array? BTW: Check out STREQ_NULLABLE > + if (STREQ(cimClasses[i].name, className)){ s/)){/)) {/ - syntax-check > + y = 0; > + while (cimClasses[i].cimTypesPtr[y].name[0] != '\0') { > + if (STREQ(cimClasses[i].cimTypesPtr[y].name, propName)){ s/)){/)) {/ - syntax-check Similar comment to above regarding how do we know 'y' will never go beyond the bounds such that cimTypesPtr[y] isn't valid? And of course STREQ_NULLABLE applies here as well > + *propType = cimClasses[i].cimTypesPtr[y].type; > + *isArray = cimClasses[i].cimTypesPtr[y].isArray; > + return 0; > + } > + y++; > + } > + break; break? so we never get to i++ once we find a matching className?, but if we don't find a matching className we can go for a while can't we... > + } > + i++; > + } > + > + return -1; > +} > + > + > +/* Adding an Simple param node to a parent node given in parameter */ > +static int > +hypervAddSimpleParam(const char *paramName, const char* value, > + const char *classURI, WsXmlNodeH *parentNode) > +{ > + int result = -1; > + WsXmlNodeH xmlNodeParam = NULL; > + > + xmlNodeParam = ws_xml_add_child(*parentNode, classURI, paramName, value); > + if (xmlNodeParam == NULL) { Consider "if (!(xmlNodeParam = ws*(...))) {" It's a long line, but should be split across 2 in any case. > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Could not create simple param")); > + goto cleanup; Just return -1 > + } > + > + result = 0; just return 0; > + > + cleanup: > + return result; Removing pointless cleanup since there is no cleanup > +} > + > + > +/* Adding EPR param node to a parent node given in parameter */ > +static int > +hypervAddEprParam(const char *paramName, virBufferPtr query, const char *root, > + const char *classURI, WsXmlNodeH *parentNode, WsXmlDocH doc, hypervPrivate *priv) > +{ > + > + int result = -1; > + WsXmlNodeH xmlNodeParam = NULL; > + WsXmlNodeH xmlNodTemp = NULL; > + WsXmlNodeH xmlNodeAdr = NULL; > + WsXmlNodeH xmlNodeRef = NULL; > + xmlNodePtr xmlNodeAdrPtr = NULL; > + xmlNodePtr xmlNodeRefPtr = NULL; > + WsXmlDocH xmlDocResponse = NULL; > + xmlDocPtr docPtr = (xmlDocPtr) doc->parserDoc; > + WsXmlNsH ns = NULL; > + client_opt_t *options = NULL; > + filter_t *filter = NULL; > + char *enumContext = NULL; > + char *query_string = NULL; > + > + /* Request options and filter */ > + options = wsmc_options_init(); > + > + if (options == NULL) { if (!(options = wsmc*())) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Could not initialize options")); > + goto cleanup; > + } > + > + wsmc_set_action_option(options, FLAG_ENUMERATION_ENUM_EPR); > + > + query_string = virBufferContentAndReset(query); > + filter = filter_create_simple(WSM_WQL_FILTER_DIALECT, query_string); > + if (filter == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Could not create filter")); > + goto cleanup; > + } > + > + /* Invoke enumerate action*/ > + xmlDocResponse = wsmc_action_enumerate(priv->client,root, options, filter); s/client,root/client, root/ (from syntax-check) > + > + /* Check return value */ > + if (hyperyVerifyResponse(priv->client, xmlDocResponse, "enumeration") < 0) { > + goto cleanup; > + } Brackets - syntax-check > + > + /* Get enumerate conext*/ > + enumContext = wsmc_get_enum_context(xmlDocResponse); > + > + ws_xml_destroy_doc(xmlDocResponse); > + One less empty line > + > + /* Invoke pull action*/ > + xmlDocResponse = wsmc_action_pull(priv->client, classURI, options, filter, enumContext); > + > + /* Check return value */ > + if (hyperyVerifyResponse(priv->client, xmlDocResponse, "pull") < 0) { > + goto cleanup; > + } brackets - syntax-check > + > + /* Extract EPR nodes childs */ > + xmlNodTemp = ws_xml_get_soap_body(xmlDocResponse); > + if (xmlNodTemp == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Could not lookup SOAP body")); > + goto cleanup; > + } > + > + xmlNodTemp = ws_xml_get_child(xmlNodTemp, 0, XML_NS_ENUMERATION, WSENUM_PULL_RESP); > + if (xmlNodTemp == NULL) { Long line above, consider combining if stmt. Repeats numerous times below > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Could not lookup pull response")); > + goto cleanup; > + } > + > + xmlNodTemp = ws_xml_get_child(xmlNodTemp, 0, XML_NS_ENUMERATION, WSENUM_ITEMS); > + if (xmlNodTemp == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Could not lookup pull response items")); > + goto cleanup; > + } > + > + xmlNodTemp = ws_xml_get_child(xmlNodTemp, 0, XML_NS_ADDRESSING, WSA_EPR); > + if (xmlNodTemp == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Could not lookup pull response item EPR")); > + goto cleanup; > + } > + > + xmlNodeAdr = ws_xml_get_child(xmlNodTemp, 0, XML_NS_ADDRESSING, WSA_ADDRESS); > + if (xmlNodeAdr == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Could not lookup pull response item ADDRESS")); > + goto cleanup; > + } > + xmlNodeAdrPtr = xmlDocCopyNode((xmlNodePtr) xmlNodeAdr, docPtr, 1); > + if (xmlNodeAdrPtr == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Could not copy item ADDRESS")); > + goto cleanup; > + } > + > + xmlNodeRef = ws_xml_get_child(xmlNodTemp, 0, XML_NS_ADDRESSING, WSA_REFERENCE_PARAMETERS); > + if (xmlNodeRef == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Could not lookup pull response item REFERENCE PARAMETERS")); > + goto cleanup; > + } > + xmlNodeRefPtr = xmlDocCopyNode((xmlNodePtr) xmlNodeRef, docPtr, 1); > + if (xmlNodeRefPtr == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Could not copy item REFERENCE PARAMETERS")); > + goto cleanup; > + } > + > + /* Build XmlDoc with adding previous EPR nodes childs */ > + xmlNodeParam = ws_xml_add_child(*parentNode, classURI, paramName, NULL); > + if (xmlNodeParam == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Could not add child node to xmlNodeParam")); > + goto cleanup; > + } > + > +/* > + The folowing line has been commented because of a memory corruption issue reported in the openwsman library > + [ issue #43 - xml_parser_ns_add: alloc item size, not pointer size ] > + xmlNodeSetLang((xmlNodePtr) xmlNodeParam, BAD_CAST "en-US"); > +*/ Comments should be : /* * text line 1 * text line 2 */ and they should be in line with the indention as well as be less the 80 chars on the line > + ns = ws_xml_ns_add(xmlNodeParam, "http://schemas.xmlsoap.org/ws/2004/08/addressing", "a"); > + if (ns == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Could not set namespace adressing to xmlNodeParam")); > + goto cleanup; > + } > + > + ns = NULL; > + ns = ws_xml_ns_add(xmlNodeParam, "http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd", "w"); > + if (ns == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Could not set namespace wsman to xmlNodeParam")); > + goto cleanup; > + } > + > + if (xmlAddChild((xmlNodePtr) *parentNode,(xmlNodePtr) xmlNodeParam) == NULL) { s/Node,(/Node, (/ - syntax-check > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Could not add child to xml parent node")); > + goto cleanup; > + } > + > + if (xmlAddChild((xmlNodePtr) xmlNodeParam, xmlNodeAdrPtr) == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Could not add child to xml parent node")); > + goto cleanup; > + } > + > + if (xmlAddChild((xmlNodePtr) xmlNodeParam, xmlNodeRefPtr) == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Could not add child to xml parent node")); > + goto cleanup; > + } > + > + result = 0; > + > + cleanup: > + if (options != NULL) { > + wsmc_options_destroy(options); > + } > + if (filter != NULL) { > + filter_destroy(filter); > + } Both - brackets - syntax-check > + ws_xml_destroy_doc(xmlDocResponse); > + VIR_FREE(enumContext); > + VIR_FREE(query_string); > + > + return result; > +} > + > + > +/* Adding an Embedded Instance node to a parent node given in parameter */ > +static int > +hypervAddEmbeddedParam(properties_t *prop_t, int nbProps, const char *paramName, > + const char *instanceName, const char *classURI, WsXmlNodeH *parentNode) > +{ > + > + int result = -1; > + WsXmlNodeH xmlNodeInstance = NULL; > + WsXmlNodeH xmlNodeProperty = NULL; > + WsXmlNodeH xmlNodeParam = NULL; > + WsXmlNodeH xmlNodeArray = NULL; > + WsXmlDocH xmlDocTemp = NULL; > + WsXmlDocH xmlDocCdata = NULL; > + xmlBufferPtr xmlBufferNode = NULL; > + const xmlChar *xmlCharCdataContent = NULL; > + xmlNodePtr xmlNodeCdata = NULL; > + const char *type = NULL; > + bool isArray = false; > + int len = 0; > + int i = 0; > + > + /* Add child to given parent node*/ > + xmlNodeParam = ws_xml_add_child(*parentNode, classURI, paramName, NULL); > + if (xmlNodeParam == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Could not add child node to xmlNodeParam")); > + goto cleanup; > + } > + > + /* Create temp Xml doc */ > + /* INSTANCE node */ > + xmlDocTemp = ws_xml_create_doc(NULL, "INSTANCE"); > + if (xmlDocTemp == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + "%s", > + _("Could not create temporary Xml doc")); > + goto cleanup; > + } > + > + xmlNodeInstance = xml_parser_get_root(xmlDocTemp); > + if (xmlNodeInstance == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + "%s", > + _("Could not get root of temporary Xml doc")); > + goto cleanup; > + } > + > + /* Add CLASSNAME node to INSTANCE node */ > + if (ws_xml_add_node_attr(xmlNodeInstance, NULL, "CLASSNAME", instanceName) == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + "%s", > + _("Could not add attribute to node ")); > + goto cleanup; > + } > + > + /* Property nodes */ > + while (i < nbProps) { > + > + if (prop_t[i].name == NULL && prop_t[i].val == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + "%s", > + _("Could not get properties from array")); > + goto cleanup; > + } > + > + if (hypervGetPropType(instanceName, prop_t[i].name, &type, &isArray) < 0) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + "%s", > + _("Could not get properties from array")); > + goto cleanup; > + } > + > + xmlNodeProperty = ws_xml_add_child(xmlNodeInstance, NULL, > + isArray ? "PROPERTY.ARRAY" : "PROPERTY", NULL); > + if (xmlNodeProperty == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + "%s", > + _("Could not add child to node")); > + goto cleanup; > + } > + > + if (ws_xml_add_node_attr(xmlNodeProperty, NULL, "NAME", prop_t[i].name) == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + "%s", > + _("Could not add attribute to node")); > + goto cleanup; > + } > + > + if (ws_xml_add_node_attr(xmlNodeProperty, NULL, "TYPE", type) == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + "%s", > + _("Could not add attribute to node")); > + goto cleanup; > + } > + > + /* Add the node VALUE.ARRAY if the attribute is an array */ > + if (isArray) { > + xmlNodeArray = ws_xml_add_child(xmlNodeProperty, NULL, "VALUE.ARRAY", NULL); > + if (xmlNodeArray == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + "%s", > + _("Could not add child to node")); > + goto cleanup; > + } > + } > + > + if (ws_xml_add_child(isArray ? xmlNodeArray : xmlNodeProperty, NULL, "VALUE", prop_t[i].val) == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + "%s", > + _("Could not add child to node")); > + goto cleanup; > + } > + > + xmlNodeArray = NULL; > + xmlNodeProperty = NULL; > + i++; > + } > + > + /* Create CDATA node */ > + xmlBufferNode = xmlBufferCreate(); > + if (xmlNodeDump(xmlBufferNode, (xmlDocPtr) xmlDocTemp->parserDoc, (xmlNodePtr) xmlNodeInstance, 0, 0) < 0) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + "%s", > + _("Could not get root of temporary Xml doc")); > + goto cleanup; > + } > + > + len = xmlBufferLength(xmlBufferNode); > + xmlCharCdataContent = xmlBufferContent(xmlBufferNode); > + xmlNodeCdata = xmlNewCDataBlock((xmlDocPtr) xmlDocCdata, xmlCharCdataContent, len); > + if (xmlNodeCdata == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + "%s", > + _("Could not get root of temporary Xml doc")); > + goto cleanup; > + } > + /* Add CDATA node child to the root node of the main doc given */ > + if (xmlAddChild((xmlNodePtr) xmlNodeParam, xmlNodeCdata) == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + "%s", > + _("Could not get root of temporary Xml doc")); > + goto cleanup; > + } > + > + result = 0; > + > + cleanup: > + ws_xml_destroy_doc(xmlDocCdata); > + ws_xml_destroy_doc(xmlDocTemp); > + if (xmlBufferNode != NULL) > + xmlBufferFree(xmlBufferNode); Syntax-check says "if (xmlBufferNode != NULL)" is unecessary > + > + return result; > +} > + > + > +/* Call wsmc_action_invoke() function of OpenWsman API with XML tree given in parameters*/ > +static int > +hypervInvokeMethodXml(hypervPrivate *priv, WsXmlDocH xmlDocRoot, > + const char *methodName, const char *ressourceURI, const char *selector) > +{ > + int result = -1; > + int returnCode; > + char *instanceID = NULL; > + char *xpath_expr_string = NULL; > + char *returnValue = NULL; > + virBuffer query = VIR_BUFFER_INITIALIZER; > + virBuffer xpath_expr_buff = VIR_BUFFER_INITIALIZER; > + client_opt_t *options = NULL; > + WsXmlDocH response = NULL; > + Msvm_ConcreteJob *concreteJob = NULL; > + bool completed = false; > + > + options = wsmc_options_init(); > + > + if (options == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Could not initialize options")); > + goto cleanup; > + } > + > + wsmc_add_selectors_from_str(options, selector); > + > + /* Invoke action */ > + response = wsmc_action_invoke(priv->client, ressourceURI, options, methodName, xmlDocRoot); > + > + virBufferAsprintf(&xpath_expr_buff, "/s:Envelope/s:Body/p:%s_OUTPUT/p:ReturnValue", methodName); > + xpath_expr_string = virBufferContentAndReset(&xpath_expr_buff); > + > + if (xpath_expr_string == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Could not lookup %s for %s invocation"), > + "ReturnValue", "RequestStateChange"); > + goto cleanup; > + } > + > + /* Check return value */ > + returnValue = ws_xml_get_xpath_value(response, xpath_expr_string); > + > + VIR_FREE(xpath_expr_string); > + xpath_expr_string = NULL; > + > + if (returnValue == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Could not lookup %s for %s invocation"), > + "ReturnValue", "RequestStateChange"); > + goto cleanup; > + } > + > + if (virStrToLong_i(returnValue, NULL, 10, &returnCode) < 0) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Could not parse return code from '%s'"), returnValue); > + goto cleanup; > + } > + > + if (returnCode == CIM_RETURNCODE_TRANSITION_STARTED) { > + virBufferAsprintf(&xpath_expr_buff, "/s:Envelope/s:Body/p:%s_OUTPUT/p:Job/a:ReferenceParameters/w:SelectorSet/w:Selector[ Name='InstanceID']", methodName); > + xpath_expr_string = virBufferContentAndReset(&xpath_expr_buff); > + if (xpath_expr_string == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Could not lookup %s for %s invocation"), > + "InstanceID", "RequestStateChange"); > + goto cleanup; > + } > + > + /* Get concrete job object */ > + instanceID = ws_xml_get_xpath_value(response, xpath_expr_string); > + if (instanceID == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Could not lookup %s for %s invocation"), > + "InstanceID", "RequestStateChange"); > + goto cleanup; > + } > + > + /* FIXME: Poll every 100ms until the job completes or fails. > + * There seems to be no other way than polling. */ > + while (!completed) { > + virBufferAddLit(&query, MSVM_CONCRETEJOB_WQL_SELECT); > + virBufferAsprintf(&query, "where InstanceID = \"%s\"", instanceID); > + > + if (hypervGetMsvmConcreteJobList(priv, &query, &concreteJob) < 0) { > + goto cleanup; > + } brackets - syntax-check > + if (concreteJob == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Could not lookup %s for %s invocation"), > + "Msvm_ConcreteJob", "RequestStateChange"); > + goto cleanup; > + } > + > + switch (concreteJob->data->JobState) { > + case MSVM_CONCRETEJOB_JOBSTATE_NEW: > + case MSVM_CONCRETEJOB_JOBSTATE_STARTING: > + case MSVM_CONCRETEJOB_JOBSTATE_RUNNING: > + case MSVM_CONCRETEJOB_JOBSTATE_SHUTTING_DOWN: > + hypervFreeObject(priv, (hypervObject *) concreteJob); > + concreteJob = NULL; > + usleep(100 * 1000); /* Wait 100 ms */ Is there a reason for the usleep? Might be good to know why... That 100 ms microsleep may work on a non busy system, but what about a busy one? I'm just pointing an area ripe for some sort of timing issue. > + continue; > + > + case MSVM_CONCRETEJOB_JOBSTATE_COMPLETED: > + completed = true; > + break; > + > + case MSVM_CONCRETEJOB_JOBSTATE_TERMINATED: > + case MSVM_CONCRETEJOB_JOBSTATE_KILLED: > + case MSVM_CONCRETEJOB_JOBSTATE_EXCEPTION: > + case MSVM_CONCRETEJOB_JOBSTATE_SERVICE: > + goto cleanup; > + > + default: > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Concrete job for %s invocation is in unknown state"), > + "RequestStateChange"); > + goto cleanup; > + } > + } > + } > + else if (returnCode != CIM_RETURNCODE_COMPLETED_WITH_NO_ERROR) { move the "else if" after the closing }; otherwise, syntax-check declares both sides of if-then-else-if need open/close braces > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Invocation of %s returned an error: %s (%d)"), > + "RequestStateChange", hypervReturnCodeToString(returnCode), > + returnCode); > + goto cleanup; > + } > + > + result = 0; > + > + cleanup: > + if (options != NULL) > + wsmc_options_destroy(options); > + if (response != NULL) > + ws_xml_destroy_doc(response); > + VIR_FREE(returnValue); > + VIR_FREE(instanceID); > + VIR_FREE(xpath_expr_string); > + hypervFreeObject(priv, (hypervObject *) concreteJob); > + virBufferFreeAndReset(&query); > + virBufferFreeAndReset(&xpath_expr_buff); > + > + return result; > +} > + > + > +/* Calls the invoke method by passing provided parameters as an XML tree */ > +int > +hypervInvokeMethod(hypervPrivate *priv, invokeXmlParam *param_t, int nbParameters, > + const char* methodName, const char* providerURI, const char *selector) > +{ > + int result = -1; > + WsXmlDocH doc = NULL; > + WsXmlNodeH methodNode = NULL; > + simpleParam *simple; > + eprParam *epr; > + embeddedParam *embedded; > + int i =0; s/int/size_t - syntax-check s/=0/= 0 - syntax-check > + > + if (hypervCreateXmlStruct(methodName,providerURI,&doc,&methodNode) < 0) { s/,/, / syntax-check (3 instances) > + virReportError(VIR_ERR_INTERNAL_ERROR, > + "%s", > + _("Could not create xml base structure")); > + goto cleanup; > + } > + > + /* Process parameters among the three allowed types */ > + while ( i < nbParameters) { s/( i/(i - syntax-check > + switch (param_t[i].type) { > + case SIMPLE_PARAM: > + simple = (simpleParam *) param_t[i].param; > + if (hypervAddSimpleParam(param_t[i].name,simple->value, providerURI, &methodNode) < 0) { s/name,simple/name, simple - syntax-check > + virReportError(VIR_ERR_INTERNAL_ERROR, > + "%s", > + _("Could not add embedded instance param to xml base structure")); > + goto cleanup; > + } > + break; > + case EPR_PARAM: > + epr = (eprParam *) param_t[i].param; > + if (hypervAddEprParam(param_t[i].name, epr->query, epr->wmiProviderURI, providerURI, &methodNode, doc, priv) < 0) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + "%s", > + _("Could not add EPR param to xml base structure")); > + goto cleanup; > + } > + break; > + case EMBEDDED_PARAM: > + embedded = (embeddedParam *) param_t[i].param; > + if (hypervAddEmbeddedParam(embedded->prop_t, embedded->nbProps, param_t[i].name, embedded->instanceName, providerURI, &methodNode) < 0) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + "%s", > + _("Could not add embedded instance param to xml base structure")); > + goto cleanup; > + } > + break; > + } > + i++; > + } > + > + /* Call the invoke method */ > + if (hypervInvokeMethodXml(priv, doc, methodName, providerURI, selector) < 0) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + "%s", The "%s", could be on previous line > + _("Error during invocation action")); > + goto cleanup; > + } > + > + result = 0; > + > + cleanup: > + if (doc != NULL) > + ws_xml_destroy_doc(doc); > + > + return result; > +} > + > > > #include "hyperv_wmi.generated.c" > diff --git a/src/hyperv/hyperv_wmi.h b/src/hyperv/hyperv_wmi.h > index 5fbbbac..c14d229 100644 > --- a/src/hyperv/hyperv_wmi.h > +++ b/src/hyperv/hyperv_wmi.h > @@ -29,7 +29,11 @@ > # include "hyperv_wmi_classes.h" > # include "openwsman.h" > > +#define ROOT_CIMV2 \ s/#define/# define/ - syntax-check > + "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*" > > +#define ROOT_VIRTUALIZATION \ s/#define/# define/ - syntax-check > + "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/virtualization/*" > > typedef struct _hypervObject hypervObject; > > @@ -38,6 +42,8 @@ int hyperyVerifyResponse(WsManClient *client, WsXmlDocH response, > > > > + > + > /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * > * Object > */ > @@ -91,6 +97,58 @@ enum _Msvm_ReturnCode { > > const char *hypervReturnCodeToString(int returnCode); > > +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * > + * hypervInvokeMethod > + * Function to invoke WSMAN request with simple, EPR or embedded parameters > + */ > + > +enum _PARAM_Type { > + SIMPLE_PARAM = 0, > + EPR_PARAM = 1, > + EMBEDDED_PARAM = 2, > +}; > + > +typedef struct _invokeXmlParam invokeXmlParam; > +struct _invokeXmlParam{ > + const char *name; > + int type; > + void *param; Using a <tab> instead of spaces - syntax-check > +}; > + > +typedef struct _eprParam eprParam; > +struct _eprParam{ > + virBufferPtr query; > + const char *wmiProviderURI; Using <tab> instead of spaces > +}; > + > +typedef struct _simpleParam simpleParam; > +struct _simpleParam{ > + const char *value; <tab> > +}; > + > +typedef struct _properties_t properties_t; > +struct _properties_t{ > + const char *name; > + const char *val; > +}; > + > +typedef struct _embeddedParam embeddedParam; > +struct _embeddedParam{ > + const char *instanceName; > + properties_t *prop_t; > + int nbProps; All 3 have <tab> instead of spaces John > +}; > + > + > +int > +hypervInvokeMethod(hypervPrivate *priv, > + invokeXmlParam *parameters, > + int nbParameters, > + const char* methodName, > + const char* providerURI, > + const char *selector); > + > + > > > /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * > diff --git a/src/hyperv/openwsman.h b/src/hyperv/openwsman.h > index f66ed86..27029e7 100644 > --- a/src/hyperv/openwsman.h > +++ b/src/hyperv/openwsman.h > @@ -43,4 +43,8 @@ > # define SER_NS_INT64(ns, n, x) SER_NS_INT64_FLAGS(ns, n, x, 0) > # endif > > +/* wsman-xml.h */ > +WsXmlDocH ws_xml_create_doc( const char *rootNsUri, const char *rootName); > +WsXmlNodeH xml_parser_get_root(WsXmlDocH doc); > + > #endif /* __OPENWSMAN_H__ */ > -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list