[libvirt] [PATCH] hyperv: Correct number of milliseconds in five minutes

2017-07-28 Thread Sri Ramanujam
---
 src/hyperv/hyperv_wmi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index 57125ae..33ad964 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -42,7 +42,7 @@
 
 #define VIR_FROM_THIS VIR_FROM_HYPERV
 
-#define HYPERV_JOB_TIMEOUT_MS 5000
+#define HYPERV_JOB_TIMEOUT_MS 30
 
 VIR_LOG_INIT("hyperv.hyperv_wmi");
 
-- 
2.9.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH] hyperv: Reduce usage of libxml API functions

2017-07-28 Thread Sri Ramanujam
Slight refactor of the WMI serialization code to minimize mixing
openwsman and libxml2 APIs. The only usage of libxml2 APIs now is in
creating CDATA blocks, because the openwsman API does not provide that
functionality.
---
 src/hyperv/hyperv_wmi.c | 65 -
 1 file changed, 16 insertions(+), 49 deletions(-)

diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index 57125ae..99efa1c 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -489,17 +489,14 @@ hypervSerializeSimpleParam(hypervParamPtr p, const char 
*resourceUri,
 
 static int
 hypervSerializeEprParam(hypervParamPtr p, hypervPrivate *priv,
-const char *resourceUri, WsXmlDocH doc, WsXmlNodeH *methodNode)
+const char *resourceUri, WsXmlNodeH *methodNode)
 {
 int result = -1;
 WsXmlNodeH xmlNodeParam = NULL,
xmlNodeTemp = NULL,
xmlNodeAddr = NULL,
xmlNodeRef = NULL;
-xmlNodePtr xmlNodeAddrPtr = NULL,
-   xmlNodeRefPtr = NULL;
 WsXmlDocH xmlDocResponse = NULL;
-xmlDocPtr docPtr = (xmlDocPtr) doc->parserDoc;
 WsXmlNsH ns = NULL;
 client_opt_t *options = NULL;
 filter_t *filter = NULL;
@@ -573,11 +570,6 @@ hypervSerializeEprParam(hypervParamPtr p, hypervPrivate 
*priv,
 goto cleanup;
 }
 
-if (!(xmlNodeAddrPtr = xmlDocCopyNode((xmlNodePtr) xmlNodeAddr, docPtr, 
1))) {
-virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not copy EPR 
address"));
-goto cleanup;
-}
-
 if (!(xmlNodeRef = ws_xml_get_child(xmlNodeTemp, 0, XML_NS_ADDRESSING,
 WSA_REFERENCE_PARAMETERS))) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -585,17 +577,11 @@ hypervSerializeEprParam(hypervParamPtr p, hypervPrivate 
*priv,
 goto cleanup;
 }
 
-if (!(xmlNodeRefPtr = xmlDocCopyNode((xmlNodePtr) xmlNodeRef, docPtr, 1))) 
{
-virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-_("Could not copy EPR item reference parameters"));
-goto cleanup;
-}
-
 /* now build a new xml doc with the EPR node children */
 if (!(xmlNodeParam = ws_xml_add_child(*methodNode, resourceUri,
 p->epr.name, NULL))) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-_("Could not add child node to xmlNodeParam"));
+_("Could not add child node to methodNode"));
 goto cleanup;
 }
 
@@ -613,23 +599,8 @@ hypervSerializeEprParam(hypervParamPtr p, hypervPrivate 
*priv,
 goto cleanup;
 }
 
-if (xmlAddChild((xmlNodePtr) *methodNode, (xmlNodePtr) xmlNodeParam) == 
NULL) {
-virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-_("Could not add child to xml parent node"));
-goto cleanup;
-}
-
-if (xmlAddChild((xmlNodePtr) xmlNodeParam, xmlNodeAddrPtr) == 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;
-}
+ws_xml_duplicate_tree(xmlNodeParam, xmlNodeAddr);
+ws_xml_duplicate_tree(xmlNodeParam, xmlNodeRef);
 
 /* we did it! */
 result = 0;
@@ -656,8 +627,7 @@ hypervSerializeEmbeddedParam(hypervParamPtr p, const char 
*resourceUri,
xmlNodeArray = NULL;
 WsXmlDocH xmlDocTemp = NULL,
   xmlDocCdata = NULL;
-xmlBufferPtr xmlBufferNode = NULL;
-const xmlChar *xmlCharCdataContent = NULL;
+char *xmlCharCdataContent = NULL;
 xmlNodePtr xmlNodeCdata = NULL;
 hypervWmiClassInfoPtr classInfo = p->embedded.info;
 virHashKeyValuePairPtr items = NULL;
@@ -761,25 +731,22 @@ hypervSerializeEmbeddedParam(hypervParamPtr p, const char 
*resourceUri,
 }
 
 /* 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 temp XML doc"));
-goto cleanup;
-}
+ws_xml_dump_memory_node_tree(xmlNodeInstance, &xmlCharCdataContent, &len);
 
-len = xmlBufferLength(xmlBufferNode);
-xmlCharCdataContent = xmlBufferContent(xmlBufferNode);
 if (!(xmlNodeCdata = xmlNewCDataBlock((xmlDocPtr) xmlDocCdata,
-xmlCharCdataContent, len))) {
+(xmlChar *)xmlCharCdataContent, len))) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
 _("Could not create CDATA element"));
 goto cleanup;
 }
 
-/* Add CDATA node to the doc root */
-if (!(xmlAddChild((xmlNodePtr) xmlNodeParam, xmlNodeCdata))) {
+/*
+ * Add CDATA node to the doc root
+

Re: [libvirt] [PATCH v7 3/6] hyperv: add hypervInvokeMethod

2017-07-19 Thread Sri Ramanujam
Just tested this patch quickly, and it causes invalid free()s when the
codepath is invoked against a Hyper-V 2008 system, and causes the
operation to fail (but does not crash virsh) against Hyper-V 2012. I'm
away from my usual setup atm (on vacation), so I can help look into
this further next week when I'm back.

On Wed, Jul 19, 2017 at 1:21 AM, Matthias Bolte
 wrote:
> 2017-07-18 18:54 GMT+02:00 Andrea Bolognani :
>> On Tue, 2017-06-27 at 15:13 -0400, Sri Ramanujam wrote:
>>> This commit adds support for invoking methods on remote objects
>>> via hypervInvokeMethod.
>>> ---
>>>  src/hyperv/hyperv_wmi.c | 590 
>>> 
>>>  src/hyperv/hyperv_wmi.h |   8 +-
>>>  src/hyperv/openwsman.h  |   4 +
>>>  3 files changed, 600 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
>>> index 2732db3..f944b14 100644
>>> --- a/src/hyperv/hyperv_wmi.c
>>> +++ b/src/hyperv/hyperv_wmi.c
>> [...]
>>> +static int
>>> +hypervSerializeEprParam(hypervParamPtr p, hypervPrivate *priv,
>>> +const char *resourceUri, WsXmlDocH doc, WsXmlNodeH *methodNode)
>>> +{
>>> +int result = -1;
>>> +WsXmlNodeH xmlNodeParam = NULL,
>>> +   xmlNodeTemp = NULL,
>>> +   xmlNodeAddr = NULL,
>>> +   xmlNodeRef = NULL;
>>> +xmlNodePtr xmlNodeAddrPtr = NULL,
>>> +   xmlNodeRefPtr = NULL;
>> [...]
>>> +if (!(xmlNodeAddrPtr = xmlDocCopyNode((xmlNodePtr) xmlNodeAddr, 
>>> docPtr, 1))) {
>>
>> Here you're casting a WsXmlNodeH to a xmlNodePtr, and clang
>> doesn't like it one bit:
>>
>>   hyperv/hyperv_wmi.c:576:43: error:
>> cast from 'WsXmlNodeH' (aka 'struct __WsXmlNode *')
>> to 'xmlNodePtr' (aka 'struct _xmlNode *')
>> increases required alignment from 4 to 8
>> [-Werror,-Wcast-align]
>>
>> Any idea how to unbreak it?
>
> The problem here is that the driver is mixing direct libxml2 calls
> with calls to the libxml2 wrapper of openwsman. The openwsman wrapper
> type WsXmlNodeH is actually a xmlNodePtr, but that is hidden to the
> compiler.
>
> I checked if the openwsman libxml2 wrapper is complete enough to get
> rid of this API mixing. I could replace all direct libxml2 calls with
> openwsman wrapper call except xmlNewCDataBlock. A hack for this last
> offender is to cast to a void pointer first, instead of a direct cast.
> See attached patch for a quick fix, compile-tested only.
>
> Another possibility is to do all the XML building using direct libxml2
> calls, format the XML document and reparse it with the openwsman
> wrapper. But I don't have time to work on that at the moment.
>
> --
> Matthias Bolte
> http://photron.blogspot.com



-- 
Sri Ramanujam
Software Engineer
Datto, Inc.

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v7 4/6] hyperv: support virDomainSendKey

2017-06-27 Thread Sri Ramanujam
This commit adds support for virDomainSendKey. It also serves as an
example of how to use the new method invocation APIs with a single
"simple" type parameter.
---
 src/hyperv/hyperv_driver.c| 123 ++
 src/hyperv/hyperv_wmi.c   |   7 ++
 src/hyperv/hyperv_wmi.h   |   3 +-
 src/hyperv/hyperv_wmi_generator.input |  86 
 4 files changed, 218 insertions(+), 1 deletion(-)

diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index 0ca5971..7ee3d9a 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -35,6 +35,8 @@
 #include "hyperv_wmi.h"
 #include "openwsman.h"
 #include "virstring.h"
+#include "virkeycode.h"
+#include "intprops.h"
 
 #define VIR_FROM_THIS VIR_FROM_HYPERV
 
@@ -1373,6 +1375,126 @@ hypervConnectListAllDomains(virConnectPtr conn,
 #undef MATCH
 
 
+static int
+hypervDomainSendKey(virDomainPtr domain, unsigned int codeset,
+unsigned int holdtime, unsigned int *keycodes, int nkeycodes,
+unsigned int flags)
+{
+int result = -1;
+size_t i = 0;
+int keycode = 0;
+int *translatedKeycodes = NULL;
+hypervPrivate *priv = domain->conn->privateData;
+char uuid_string[VIR_UUID_STRING_BUFLEN];
+char *selector = NULL;
+Msvm_ComputerSystem *computerSystem = NULL;
+Msvm_Keyboard *keyboard = NULL;
+virBuffer query = VIR_BUFFER_INITIALIZER;
+hypervInvokeParamsListPtr params = NULL;
+char keycodeStr[INT_BUFSIZE_BOUND(int)];
+
+virCheckFlags(0, -1);
+
+virUUIDFormat(domain->uuid, uuid_string);
+
+if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
+goto cleanup;
+
+virBufferAsprintf(&query,
+"associators of "
+"{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+"Name=\"%s\"} "
+"where ResultClass = Msvm_Keyboard",
+uuid_string);
+
+if (hypervGetMsvmKeyboardList(priv, &query, &keyboard) < 0)
+goto cleanup;
+
+if (VIR_ALLOC_N(translatedKeycodes, nkeycodes) < 0)
+goto cleanup;
+
+/* translate keycodes to win32 and generate keyup scancodes. */
+for (i = 0; i < nkeycodes; i++) {
+if (codeset != VIR_KEYCODE_SET_WIN32) {
+keycode = virKeycodeValueTranslate(codeset, VIR_KEYCODE_SET_WIN32,
+keycodes[i]);
+
+if (keycode < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not translate keycode"));
+goto cleanup;
+}
+translatedKeycodes[i] = keycode;
+}
+}
+
+if (virAsprintf(&selector,
+"CreationClassName=Msvm_Keyboard&DeviceID=%s&"
+"SystemCreationClassName=Msvm_ComputerSystem&"
+"SystemName=%s", keyboard->data.common->DeviceID, uuid_string) 
< 0)
+goto cleanup;
+
+/* press the keys */
+for (i = 0; i < nkeycodes; i++) {
+snprintf(keycodeStr, sizeof(keycodeStr), "%d", translatedKeycodes[i]);
+
+params = hypervCreateInvokeParamsList(priv, "PressKey", selector,
+Msvm_Keyboard_WmiInfo);
+
+if (!params) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create 
param"));
+goto cleanup;
+}
+
+if (hypervAddSimpleParam(params, "keyCode", keycodeStr) < 0) {
+hypervFreeInvokeParams(params);
+goto cleanup;
+}
+
+if (hypervInvokeMethod(priv, params, NULL) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not press key %d"),
+   translatedKeycodes[i]);
+goto cleanup;
+}
+}
+
+/* simulate holdtime by sleeping */
+if (holdtime > 0)
+usleep(holdtime * 1000);
+
+/* release the keys */
+for (i = 0; i < nkeycodes; i++) {
+snprintf(keycodeStr, sizeof(keycodeStr), "%d", translatedKeycodes[i]);
+params = hypervCreateInvokeParamsList(priv, "ReleaseKey", selector,
+Msvm_Keyboard_WmiInfo);
+
+if (!params) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create 
param"));
+goto cleanup;
+}
+
+if (hypervAddSimpleParam(params, "keyCode", keycodeStr) < 0) {
+hypervFreeInvokeParams(params);
+goto cleanup;
+}
+
+if (hypervInvokeMethod(priv, params, NULL) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not release key 
%s"),
+keycodeStr);
+goto cleanup;
+}
+}
+
+result = 0;
+
+ cleanup:
+VIR_FREE(translatedKeycodes);
+VIR_FREE(selector);
+hypervFreeObject(priv, (hypervObject *) keyboard);
+hypervFreeObject(priv, (hypervObject *) computerSystem);
+virBufferFreeAndReset(&query);
+return result;
+}
 
 
 static virHypervisorDriver hypervHypervisorDriver = {
@@ -1408,6 +153

[libvirt] [PATCH v7 6/6] news: Update news for new Hyper-V APIs

2017-06-27 Thread Sri Ramanujam
---
 docs/news.xml | 5 +
 1 file changed, 5 insertions(+)

diff --git a/docs/news.xml b/docs/news.xml
index 27562e1..77d167c 100644
--- a/docs/news.xml
+++ b/docs/news.xml
@@ -48,6 +48,11 @@
   
 
 
+  
+
+  hyperv: Implement virDomainSetMemory and virDomainSendKey APIs
+
+  
 
 
 
-- 
2.9.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v7 1/6] hyperv: Functions to work with invocation parameters.

2017-06-27 Thread Sri Ramanujam
This commit introduces functionality for creating and working with
invoke parameters. This commit does not include any code for serializing
and actually performing the method invocations; it merely defines the
functions and API for using invocation parameters in driver code.

HYPERV_DEFAULT_PARAM_COUNT was chosen because almost no method
invocations have more than 4 parameters.

Functions added:
* hypervInitInvokeParamsList
* hypervFreeInvokeParams
* hypervAddSimpleParam
* hypervAddEprParam
* hypervCreateEmbeddedParam
* hypervSetEmbeddedProperty
* hypervAddEmbeddedParam
* hypervFreeEmbeddedParam
---
 src/hyperv/hyperv_wmi.c | 262 
 src/hyperv/hyperv_wmi.h |  79 ++-
 2 files changed, 340 insertions(+), 1 deletion(-)

diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index a3c7dc0..2732db3 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -2,6 +2,7 @@
  * hyperv_wmi.c: general WMI over WSMAN related functions and structures for
  *   managing Microsoft Hyper-V hosts
  *
+ * Copyright (C) 2017 Datto Inc
  * Copyright (C) 2014 Red Hat, Inc.
  * Copyright (C) 2011 Matthias Bolte 
  * Copyright (C) 2009 Michael Sievers 
@@ -142,6 +143,267 @@ hypervVerifyResponse(WsManClient *client, WsXmlDocH 
response,
 }
 
 
+/*
+ * Methods to work with method invocation parameters
+ */
+
+/*
+ * hypervCreateInvokeParamsList:
+ * @priv: hypervPrivate object associated with the connection.
+ * @method: The name of the method you are calling
+ * @selector: The selector for the object you are invoking the method on
+ * @obj: The WmiInfo of the object class you are invoking the method on.
+ *
+ * Create a new InvokeParamsList object for the method call.
+ *
+ * Returns a pointer to the newly instantiated object on success, which should
+ * be freed by hypervInvokeMethod. Otherwise returns NULL.
+ */
+hypervInvokeParamsListPtr
+hypervCreateInvokeParamsList(hypervPrivate *priv, const char *method,
+const char *selector, hypervWmiClassInfoListPtr obj)
+{
+hypervInvokeParamsListPtr params = NULL;
+hypervWmiClassInfoPtr info = NULL;
+
+if (hypervGetWmiClassInfo(priv, obj, &info) < 0)
+goto cleanup;
+
+if (VIR_ALLOC(params) < 0)
+goto cleanup;
+
+if (VIR_ALLOC_N(params->params,
+HYPERV_DEFAULT_PARAM_COUNT) < 0) {
+VIR_FREE(params);
+goto cleanup;
+}
+
+params->method = method;
+params->ns = info->rootUri;
+params->resourceUri = info->resourceUri;
+params->selector = selector;
+params->nbParams = 0;
+params->nbAvailParams = HYPERV_DEFAULT_PARAM_COUNT;
+
+ cleanup:
+return params;
+}
+
+/*
+ * hypervFreeInvokeParams:
+ * @params: Params object to be freed
+ *
+ */
+void
+hypervFreeInvokeParams(hypervInvokeParamsListPtr params)
+{
+hypervParamPtr p = NULL;
+size_t i = 0;
+
+if (params == NULL)
+return;
+
+for (i = 0; i < params->nbParams; i++) {
+p = &(params->params[i]);
+
+switch (p->type) {
+case HYPERV_SIMPLE_PARAM:
+break;
+case HYPERV_EPR_PARAM:
+virBufferFreeAndReset(p->epr.query);
+break;
+case HYPERV_EMBEDDED_PARAM:
+hypervFreeEmbeddedParam(p->embedded.table);
+break;
+default:
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Invalid parameter type passed to free"));
+}
+}
+
+VIR_DISPOSE_N(params->params, params->nbAvailParams);
+VIR_FREE(params);
+}
+
+static inline int
+hypervCheckParams(hypervInvokeParamsListPtr params)
+{
+if (params->nbParams + 1 > params->nbAvailParams) {
+if (VIR_EXPAND_N(params->params, params->nbAvailParams, 5) < 0)
+return -1;
+}
+
+return 0;
+}
+
+/*
+ * hypervAddSimpleParam:
+ * @params: Params object to add to
+ * @name: Name of the parameter
+ * @value: Value of the parameter
+ *
+ * Add a param of type HYPERV_SIMPLE_PARAM, which is essentially a serialized
+ * key/value pair.
+ *
+ * Returns -1 on failure, 0 on success.
+ */
+int
+hypervAddSimpleParam(hypervInvokeParamsListPtr params, const char *name,
+const char *value)
+{
+int result = -1;
+hypervParamPtr p = NULL;
+
+if (hypervCheckParams(params) < 0)
+goto cleanup;
+
+p = ¶ms->params[params->nbParams];
+p->type = HYPERV_SIMPLE_PARAM;
+
+p->simple.name = name;
+p->simple.value = value;
+
+params->nbParams++;
+
+result = 0;
+
+ cleanup:
+return result;
+}
+
+/*
+ * hypervAddEprParam:
+ * @params: Params object to add to
+ * @name: Parameter name
+ * @priv: hypervPrivate object associated with the connection
+ * @query: WQL filter
+ * @eprInfo: WmiInfo of the object being filtered
+ *
+ * Adds an EPR param to the params list. Returns -1 on failure, 0 on success.
+ */
+int
+hypervAddEprParam(hypervInvokeParamsListPtr params, con

[libvirt] [PATCH v7 2/6] hyperv: Generate object property type information.

2017-06-27 Thread Sri Ramanujam
Update the generator to generate basic property type information for
each CIM object representation. Right now, it generates arrays of
hypervCimType structs:

struct _hypervCimType {
const char *name;
const char *type;
bool isArray;
};
---
 src/hyperv/hyperv_wmi_classes.h| 19 +++
 src/hyperv/hyperv_wmi_generator.py | 15 ++-
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/src/hyperv/hyperv_wmi_classes.h b/src/hyperv/hyperv_wmi_classes.h
index f7d596f..ce4643e 100644
--- a/src/hyperv/hyperv_wmi_classes.h
+++ b/src/hyperv/hyperv_wmi_classes.h
@@ -1,6 +1,7 @@
 /*
  * hyperv_wmi_classes.h: WMI classes for managing Microsoft Hyper-V hosts
  *
+ * Copyright (C) 2017 Datto Inc
  * Copyright (C) 2011 Matthias Bolte 
  * Copyright (C) 2009 Michael Sievers 
  *
@@ -23,6 +24,7 @@
 #ifndef __HYPERV_WMI_CLASSES_H__
 # define __HYPERV_WMI_CLASSES_H__
 
+# include "internal.h"
 # include "openwsman.h"
 
 # include "hyperv_wmi_classes.generated.typedef"
@@ -96,6 +98,21 @@ enum _Msvm_ConcreteJob_JobState {
 };
 
 
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * WMI
+ */
+
+typedef struct _hypervCimType hypervCimType;
+typedef hypervCimType *hypervCimTypePtr;
+struct _hypervCimType {
+/* Parameter name */
+const char *name;
+/* Parameter type */
+const char *type;
+/* whether parameter is an array type */
+bool isArray;
+};
+
 typedef struct _hypervWmiClassInfo hypervWmiClassInfo;
 typedef hypervWmiClassInfo *hypervWmiClassInfoPtr;
 struct _hypervWmiClassInfo {
@@ -109,6 +126,8 @@ struct _hypervWmiClassInfo {
 const char *resourceUri;
 /* The wsman serializer info - one of the *_TypeInfo structs */
 XmlSerializerInfo *serializerInfo;
+/* Property type information */
+hypervCimTypePtr propertyInfo;
 };
 
 
diff --git a/src/hyperv/hyperv_wmi_generator.py 
b/src/hyperv/hyperv_wmi_generator.py
index 9aee0b9..9c0acce 100755
--- a/src/hyperv/hyperv_wmi_generator.py
+++ b/src/hyperv/hyperv_wmi_generator.py
@@ -122,6 +122,14 @@ class WmiClass:
 
 source += "SER_END_ITEMS(%s_Data);\n\n" % cls.name
 
+# also generate typemap data while we're here
+source += "hypervCimType %s_Typemap[] = {\n" % cls.name
+
+for property in cls.properties:
+source += property.generate_typemap()
+source += '{ "", "", 0 },\n' # null terminated
+source += '};\n\n'
+
 
 source += self._define_WmiInfo_struct()
 source += "\n\n"
@@ -222,7 +230,8 @@ class WmiClass:
 source += ".version = NULL,\n"
 source += ".rootUri = %s,\n" % cls.uri_info.rootUri
 source += ".resourceUri = %s_RESOURCE_URI,\n" % 
cls.name.upper()
-source += ".serializerInfo = %s_Data_TypeInfo\n" % 
cls.name
+source += ".serializerInfo = %s_Data_TypeInfo,\n" % 
cls.name
+source += ".propertyInfo = %s_Typemap\n" % cls.name
 source += "},\n"
 
 source += "}\n"
@@ -374,6 +383,10 @@ class Property:
% (Property.typemap[self.type], class_name.upper(), 
self.name)
 
 
+def generate_typemap(self):
+return '{ "%s", "%s", %s },\n' % (self.name, self.type.lower(), 
str(self.is_array).lower())
+
+
 
 def open_and_print(filename):
 if filename.startswith("./"):
-- 
2.9.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v7 5/6] hyperv: Add support for virDomainSetMemory

2017-06-27 Thread Sri Ramanujam
Introduces support for virDomainSetMemory. This also serves an an
example for how to use the new method invocation API with a more
complicated method, this time including an EPR and embedded param.
---
 src/hyperv/hyperv_driver.c| 114 ++
 src/hyperv/hyperv_wmi.c   |  51 +++
 src/hyperv/hyperv_wmi.h   |  11 
 src/hyperv/hyperv_wmi_generator.input |  30 +
 4 files changed, 206 insertions(+)

diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index 7ee3d9a..a069afd 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -1497,6 +1497,118 @@ hypervDomainSendKey(virDomainPtr domain, unsigned int 
codeset,
 }
 
 
+static int
+hypervDomainSetMemoryFlags(virDomainPtr domain, unsigned long memory,
+unsigned int flags)
+{
+int result = -1;
+char uuid_string[VIR_UUID_STRING_BUFLEN];
+hypervPrivate *priv = domain->conn->privateData;
+char *memory_str = NULL;
+hypervInvokeParamsListPtr params = NULL;
+unsigned long memory_mb = VIR_ROUND_UP(VIR_DIV_UP(memory, 1024), 2);
+Msvm_VirtualSystemSettingData *vssd = NULL;
+Msvm_MemorySettingData *memsd = NULL;
+virBuffer eprQuery = VIR_BUFFER_INITIALIZER;
+virHashTablePtr memResource = NULL;
+
+virCheckFlags(0, -1);
+
+if (virAsprintf(&memory_str, "%lu", memory_mb) < 0)
+goto cleanup;
+
+virUUIDFormat(domain->uuid, uuid_string);
+
+if (hypervGetMsvmVirtualSystemSettingDataFromUUID(priv, uuid_string, 
&vssd) < 0)
+goto cleanup;
+
+if (hypervGetMsvmMemorySettingDataFromVSSD(priv, 
vssd->data.common->InstanceID,
+&memsd) < 0)
+goto cleanup;
+
+if (priv->wmiVersion == HYPERV_WMI_VERSION_V1) {
+params = hypervCreateInvokeParamsList(priv, 
"ModifyVirtualSystemResources",
+MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_SELECTOR,
+Msvm_VirtualSystemManagementService_WmiInfo);
+
+if (!params) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create 
params"));
+goto cleanup;
+}
+
+virBufferAddLit(&eprQuery, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+virBufferAsprintf(&eprQuery, "where Name = \"%s\"", uuid_string);
+
+if (hypervAddEprParam(params, "ComputerSystem", priv, &eprQuery,
+Msvm_ComputerSystem_WmiInfo) < 0)
+goto params_cleanup;
+} else if (priv->wmiVersion == HYPERV_WMI_VERSION_V2) {
+params = hypervCreateInvokeParamsList(priv, "ModifyResourceSettings",
+MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_SELECTOR,
+Msvm_VirtualSystemManagementService_WmiInfo);
+
+if (!params) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create 
params"));
+goto cleanup;
+}
+}
+
+memResource = hypervCreateEmbeddedParam(priv, 
Msvm_MemorySettingData_WmiInfo);
+if (!memResource)
+goto params_cleanup;
+
+if (hypervSetEmbeddedProperty(memResource, "VirtualQuantity", memory_str) 
< 0) {
+hypervFreeEmbeddedParam(memResource);
+goto params_cleanup;
+}
+
+if (hypervSetEmbeddedProperty(memResource, "InstanceID",
+memsd->data.common->InstanceID) < 0) {
+hypervFreeEmbeddedParam(memResource);
+goto params_cleanup;
+}
+
+if (priv->wmiVersion == HYPERV_WMI_VERSION_V1) {
+if (hypervAddEmbeddedParam(params, priv, "ResourceSettingData",
+memResource, Msvm_MemorySettingData_WmiInfo) < 0) {
+hypervFreeEmbeddedParam(memResource);
+goto params_cleanup;
+}
+
+} else if (priv->wmiVersion == HYPERV_WMI_VERSION_V2) {
+if (hypervAddEmbeddedParam(params, priv, "ResourceSettings",
+memResource, Msvm_MemorySettingData_WmiInfo) < 0) {
+hypervFreeEmbeddedParam(memResource);
+goto params_cleanup;
+}
+}
+
+if (hypervInvokeMethod(priv, params, NULL) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not set 
memory"));
+goto cleanup;
+}
+
+result = 0;
+goto cleanup;
+
+ params_cleanup:
+hypervFreeInvokeParams(params);
+virBufferFreeAndReset(&eprQuery);
+ cleanup:
+VIR_FREE(memory_str);
+hypervFreeObject(priv, (hypervObject *) vssd);
+hypervFreeObject(priv, (hypervObject *) memsd);
+return result;
+}
+
+
+static int
+hypervDomainSetMemory(virDomainPtr domain, unsigned long memory)
+{
+return hypervDomainSetMemoryFlags(domain, memory, 0);
+}
+
+
 static virHypervisorDriver hypervHypervisorDriver = {
 .name = "Hyper-V",
 .connectOpen = hypervConnectOpen, /* 0.9.5 */
@@ -1531,6 +1643,8 @@ static virHypervisorDriver hypervHypervisorDriver = {
 .domainHasManagedSaveImage = hypervDomainHasManagedSaveImage, /* 0.9.5 */
 .domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */
 

[libvirt] [PATCH v7 3/6] hyperv: add hypervInvokeMethod

2017-06-27 Thread Sri Ramanujam
This commit adds support for invoking methods on remote objects
via hypervInvokeMethod.
---
 src/hyperv/hyperv_wmi.c | 590 
 src/hyperv/hyperv_wmi.h |   8 +-
 src/hyperv/openwsman.h  |   4 +
 3 files changed, 600 insertions(+), 2 deletions(-)

diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index 2732db3..f944b14 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -24,6 +24,7 @@
  */
 
 #include 
+#include 
 
 #include "internal.h"
 #include "virerror.h"
@@ -34,11 +35,16 @@
 #include "hyperv_private.h"
 #include "hyperv_wmi.h"
 #include "virstring.h"
+#include "openwsman.h"
+#include "virlog.h"
 
 #define WS_SERIALIZER_FREE_MEM_WORKS 0
 
 #define VIR_FROM_THIS VIR_FROM_HYPERV
 
+#define HYPERV_JOB_TIMEOUT_MS 5000
+
+VIR_LOG_INIT("hyperv.hyperv_wmi");
 
 static int
 hypervGetWmiClassInfo(hypervPrivate *priv, hypervWmiClassInfoListPtr list,
@@ -405,6 +411,590 @@ hypervFreeEmbeddedParam(virHashTablePtr p)
 virHashFree(p);
 }
 
+/*
+ * Serializing parameters to XML and invoking methods
+ */
+
+static int
+hypervGetCimTypeInfo(hypervCimTypePtr typemap, const char *name,
+hypervCimTypePtr *property)
+{
+size_t i = 0;
+while (typemap[i].name[0] != '\0') {
+if (STREQ(typemap[i].name, name)) {
+*property = &typemap[i];
+return 0;
+}
+i++;
+}
+
+return -1;
+}
+
+
+static int
+hypervCreateInvokeXmlDoc(hypervInvokeParamsListPtr params, WsXmlDocH *docRoot)
+{
+int result = -1;
+char *method = NULL;
+WsXmlNodeH xmlNodeMethod = NULL;
+
+if (virAsprintf(&method, "%s_INPUT", params->method) < 0)
+goto cleanup;
+
+*docRoot = ws_xml_create_doc(NULL, method);
+if (*docRoot == NULL) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not instantiate XML document"));
+goto cleanup;
+}
+
+xmlNodeMethod = xml_parser_get_root(*docRoot);
+if (xmlNodeMethod == NULL) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not get root node of XML document"));
+goto cleanup;
+}
+
+/* add resource URI as namespace */
+ws_xml_set_ns(xmlNodeMethod, params->resourceUri, "p");
+
+result = 0;
+
+ cleanup:
+if (result < 0 && *docRoot != NULL) {
+ws_xml_destroy_doc(*docRoot);
+*docRoot = NULL;
+}
+VIR_FREE(method);
+return result;
+}
+
+static int
+hypervSerializeSimpleParam(hypervParamPtr p, const char *resourceUri,
+WsXmlNodeH *methodNode)
+{
+WsXmlNodeH xmlNodeParam = NULL;
+
+xmlNodeParam = ws_xml_add_child(*methodNode, resourceUri,
+p->simple.name, p->simple.value);
+if (xmlNodeParam == NULL) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not create simple param"));
+return -1;
+}
+
+return 0;
+}
+
+static int
+hypervSerializeEprParam(hypervParamPtr p, hypervPrivate *priv,
+const char *resourceUri, WsXmlDocH doc, WsXmlNodeH *methodNode)
+{
+int result = -1;
+WsXmlNodeH xmlNodeParam = NULL,
+   xmlNodeTemp = NULL,
+   xmlNodeAddr = NULL,
+   xmlNodeRef = NULL;
+xmlNodePtr xmlNodeAddrPtr = NULL,
+   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;
+
+/* init and set up options */
+options = wsmc_options_init();
+if (!options) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not init 
options"));
+goto cleanup;
+}
+wsmc_set_action_option(options, FLAG_ENUMERATION_ENUM_EPR);
+
+/* Get query and create filter based on it */
+if (virBufferCheckError(p->epr.query) < 0) {
+virBufferFreeAndReset(p->epr.query);
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid query"));
+goto cleanup;
+}
+query_string = virBufferContentAndReset(p->epr.query);
+
+filter = filter_create_simple(WSM_WQL_FILTER_DIALECT, query_string);
+if (!filter) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create WQL 
filter"));
+goto cleanup;
+}
+
+/* enumerate based on the filter from this query */
+xmlDocResponse = wsmc_action_enumerate(priv->client, p->epr.info->rootUri,
+options, filter);
+if (hypervVerifyResponse(priv->client, xmlDocResponse, "enumeration") < 0)
+goto cleanup;
+
+/* Get context */
+enumContext = wsmc_get_enum_context(xmlDocResponse);
+ws_xml_destroy_doc(xmlDocResponse);
+
+/* Pull using filter and enum context */
+xmlDocResponse = wsmc_action_pull(priv->client, resourceUri, options,
+filter, enumContext);
+
+if (hypervVerifyResponse(priv->client, xmlDocResponse, "pull") < 0)
+go

[libvirt] [PATCH v7 0/6] Hyper-V method invocation

2017-06-27 Thread Sri Ramanujam
Changes from v6:
  * Added news entry

Sri Ramanujam (6):
  hyperv: Functions to work with invocation parameters.
  hyperv: Generate object property type information.
  hyperv: add hypervInvokeMethod
  hyperv: support virDomainSendKey
  hyperv: Add support for virDomainSetMemory
  news: Update news for new Hyper-V APIs

 docs/news.xml |   5 +
 src/hyperv/hyperv_driver.c| 237 +
 src/hyperv/hyperv_wmi.c   | 910 ++
 src/hyperv/hyperv_wmi.h   |  95 +++-
 src/hyperv/hyperv_wmi_classes.h   |  19 +
 src/hyperv/hyperv_wmi_generator.input | 116 +
 src/hyperv/hyperv_wmi_generator.py|  15 +-
 src/hyperv/openwsman.h|   4 +
 8 files changed, 1399 insertions(+), 2 deletions(-)

-- 
2.9.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v6 2/5] hyperv: Generate object property type information.

2017-06-26 Thread Sri Ramanujam
Update the generator to generate basic property type information for
each CIM object representation. Right now, it generates arrays of
hypervCimType structs:

struct _hypervCimType {
const char *name;
const char *type;
bool isArray;
};
---
 src/hyperv/hyperv_wmi_classes.h| 19 +++
 src/hyperv/hyperv_wmi_generator.py | 15 ++-
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/src/hyperv/hyperv_wmi_classes.h b/src/hyperv/hyperv_wmi_classes.h
index f7d596f..ce4643e 100644
--- a/src/hyperv/hyperv_wmi_classes.h
+++ b/src/hyperv/hyperv_wmi_classes.h
@@ -1,6 +1,7 @@
 /*
  * hyperv_wmi_classes.h: WMI classes for managing Microsoft Hyper-V hosts
  *
+ * Copyright (C) 2017 Datto Inc
  * Copyright (C) 2011 Matthias Bolte 
  * Copyright (C) 2009 Michael Sievers 
  *
@@ -23,6 +24,7 @@
 #ifndef __HYPERV_WMI_CLASSES_H__
 # define __HYPERV_WMI_CLASSES_H__
 
+# include "internal.h"
 # include "openwsman.h"
 
 # include "hyperv_wmi_classes.generated.typedef"
@@ -96,6 +98,21 @@ enum _Msvm_ConcreteJob_JobState {
 };
 
 
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * WMI
+ */
+
+typedef struct _hypervCimType hypervCimType;
+typedef hypervCimType *hypervCimTypePtr;
+struct _hypervCimType {
+/* Parameter name */
+const char *name;
+/* Parameter type */
+const char *type;
+/* whether parameter is an array type */
+bool isArray;
+};
+
 typedef struct _hypervWmiClassInfo hypervWmiClassInfo;
 typedef hypervWmiClassInfo *hypervWmiClassInfoPtr;
 struct _hypervWmiClassInfo {
@@ -109,6 +126,8 @@ struct _hypervWmiClassInfo {
 const char *resourceUri;
 /* The wsman serializer info - one of the *_TypeInfo structs */
 XmlSerializerInfo *serializerInfo;
+/* Property type information */
+hypervCimTypePtr propertyInfo;
 };
 
 
diff --git a/src/hyperv/hyperv_wmi_generator.py 
b/src/hyperv/hyperv_wmi_generator.py
index 9aee0b9..9c0acce 100755
--- a/src/hyperv/hyperv_wmi_generator.py
+++ b/src/hyperv/hyperv_wmi_generator.py
@@ -122,6 +122,14 @@ class WmiClass:
 
 source += "SER_END_ITEMS(%s_Data);\n\n" % cls.name
 
+# also generate typemap data while we're here
+source += "hypervCimType %s_Typemap[] = {\n" % cls.name
+
+for property in cls.properties:
+source += property.generate_typemap()
+source += '{ "", "", 0 },\n' # null terminated
+source += '};\n\n'
+
 
 source += self._define_WmiInfo_struct()
 source += "\n\n"
@@ -222,7 +230,8 @@ class WmiClass:
 source += ".version = NULL,\n"
 source += ".rootUri = %s,\n" % cls.uri_info.rootUri
 source += ".resourceUri = %s_RESOURCE_URI,\n" % 
cls.name.upper()
-source += ".serializerInfo = %s_Data_TypeInfo\n" % 
cls.name
+source += ".serializerInfo = %s_Data_TypeInfo,\n" % 
cls.name
+source += ".propertyInfo = %s_Typemap\n" % cls.name
 source += "},\n"
 
 source += "}\n"
@@ -374,6 +383,10 @@ class Property:
% (Property.typemap[self.type], class_name.upper(), 
self.name)
 
 
+def generate_typemap(self):
+return '{ "%s", "%s", %s },\n' % (self.name, self.type.lower(), 
str(self.is_array).lower())
+
+
 
 def open_and_print(filename):
 if filename.startswith("./"):
-- 
2.9.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v6 1/5] hyperv: Functions to work with invocation parameters.

2017-06-26 Thread Sri Ramanujam
This commit introduces functionality for creating and working with
invoke parameters. This commit does not include any code for serializing
and actually performing the method invocations; it merely defines the
functions and API for using invocation parameters in driver code.

HYPERV_DEFAULT_PARAM_COUNT was chosen because almost no method
invocations have more than 4 parameters.

Functions added:
* hypervInitInvokeParamsList
* hypervFreeInvokeParams
* hypervAddSimpleParam
* hypervAddEprParam
* hypervCreateEmbeddedParam
* hypervSetEmbeddedProperty
* hypervAddEmbeddedParam
* hypervFreeEmbeddedParam
---
 src/hyperv/hyperv_wmi.c | 262 
 src/hyperv/hyperv_wmi.h |  79 ++-
 2 files changed, 340 insertions(+), 1 deletion(-)

diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index a3c7dc0..2732db3 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -2,6 +2,7 @@
  * hyperv_wmi.c: general WMI over WSMAN related functions and structures for
  *   managing Microsoft Hyper-V hosts
  *
+ * Copyright (C) 2017 Datto Inc
  * Copyright (C) 2014 Red Hat, Inc.
  * Copyright (C) 2011 Matthias Bolte 
  * Copyright (C) 2009 Michael Sievers 
@@ -142,6 +143,267 @@ hypervVerifyResponse(WsManClient *client, WsXmlDocH 
response,
 }
 
 
+/*
+ * Methods to work with method invocation parameters
+ */
+
+/*
+ * hypervCreateInvokeParamsList:
+ * @priv: hypervPrivate object associated with the connection.
+ * @method: The name of the method you are calling
+ * @selector: The selector for the object you are invoking the method on
+ * @obj: The WmiInfo of the object class you are invoking the method on.
+ *
+ * Create a new InvokeParamsList object for the method call.
+ *
+ * Returns a pointer to the newly instantiated object on success, which should
+ * be freed by hypervInvokeMethod. Otherwise returns NULL.
+ */
+hypervInvokeParamsListPtr
+hypervCreateInvokeParamsList(hypervPrivate *priv, const char *method,
+const char *selector, hypervWmiClassInfoListPtr obj)
+{
+hypervInvokeParamsListPtr params = NULL;
+hypervWmiClassInfoPtr info = NULL;
+
+if (hypervGetWmiClassInfo(priv, obj, &info) < 0)
+goto cleanup;
+
+if (VIR_ALLOC(params) < 0)
+goto cleanup;
+
+if (VIR_ALLOC_N(params->params,
+HYPERV_DEFAULT_PARAM_COUNT) < 0) {
+VIR_FREE(params);
+goto cleanup;
+}
+
+params->method = method;
+params->ns = info->rootUri;
+params->resourceUri = info->resourceUri;
+params->selector = selector;
+params->nbParams = 0;
+params->nbAvailParams = HYPERV_DEFAULT_PARAM_COUNT;
+
+ cleanup:
+return params;
+}
+
+/*
+ * hypervFreeInvokeParams:
+ * @params: Params object to be freed
+ *
+ */
+void
+hypervFreeInvokeParams(hypervInvokeParamsListPtr params)
+{
+hypervParamPtr p = NULL;
+size_t i = 0;
+
+if (params == NULL)
+return;
+
+for (i = 0; i < params->nbParams; i++) {
+p = &(params->params[i]);
+
+switch (p->type) {
+case HYPERV_SIMPLE_PARAM:
+break;
+case HYPERV_EPR_PARAM:
+virBufferFreeAndReset(p->epr.query);
+break;
+case HYPERV_EMBEDDED_PARAM:
+hypervFreeEmbeddedParam(p->embedded.table);
+break;
+default:
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Invalid parameter type passed to free"));
+}
+}
+
+VIR_DISPOSE_N(params->params, params->nbAvailParams);
+VIR_FREE(params);
+}
+
+static inline int
+hypervCheckParams(hypervInvokeParamsListPtr params)
+{
+if (params->nbParams + 1 > params->nbAvailParams) {
+if (VIR_EXPAND_N(params->params, params->nbAvailParams, 5) < 0)
+return -1;
+}
+
+return 0;
+}
+
+/*
+ * hypervAddSimpleParam:
+ * @params: Params object to add to
+ * @name: Name of the parameter
+ * @value: Value of the parameter
+ *
+ * Add a param of type HYPERV_SIMPLE_PARAM, which is essentially a serialized
+ * key/value pair.
+ *
+ * Returns -1 on failure, 0 on success.
+ */
+int
+hypervAddSimpleParam(hypervInvokeParamsListPtr params, const char *name,
+const char *value)
+{
+int result = -1;
+hypervParamPtr p = NULL;
+
+if (hypervCheckParams(params) < 0)
+goto cleanup;
+
+p = ¶ms->params[params->nbParams];
+p->type = HYPERV_SIMPLE_PARAM;
+
+p->simple.name = name;
+p->simple.value = value;
+
+params->nbParams++;
+
+result = 0;
+
+ cleanup:
+return result;
+}
+
+/*
+ * hypervAddEprParam:
+ * @params: Params object to add to
+ * @name: Parameter name
+ * @priv: hypervPrivate object associated with the connection
+ * @query: WQL filter
+ * @eprInfo: WmiInfo of the object being filtered
+ *
+ * Adds an EPR param to the params list. Returns -1 on failure, 0 on success.
+ */
+int
+hypervAddEprParam(hypervInvokeParamsListPtr params, con

[libvirt] [PATCH v6 3/5] hyperv: add hypervInvokeMethod

2017-06-26 Thread Sri Ramanujam
This commit adds support for invoking methods on remote objects
via hypervInvokeMethod.
---
 src/hyperv/hyperv_wmi.c | 590 
 src/hyperv/hyperv_wmi.h |   8 +-
 src/hyperv/openwsman.h  |   4 +
 3 files changed, 600 insertions(+), 2 deletions(-)

diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index 2732db3..f944b14 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -24,6 +24,7 @@
  */
 
 #include 
+#include 
 
 #include "internal.h"
 #include "virerror.h"
@@ -34,11 +35,16 @@
 #include "hyperv_private.h"
 #include "hyperv_wmi.h"
 #include "virstring.h"
+#include "openwsman.h"
+#include "virlog.h"
 
 #define WS_SERIALIZER_FREE_MEM_WORKS 0
 
 #define VIR_FROM_THIS VIR_FROM_HYPERV
 
+#define HYPERV_JOB_TIMEOUT_MS 5000
+
+VIR_LOG_INIT("hyperv.hyperv_wmi");
 
 static int
 hypervGetWmiClassInfo(hypervPrivate *priv, hypervWmiClassInfoListPtr list,
@@ -405,6 +411,590 @@ hypervFreeEmbeddedParam(virHashTablePtr p)
 virHashFree(p);
 }
 
+/*
+ * Serializing parameters to XML and invoking methods
+ */
+
+static int
+hypervGetCimTypeInfo(hypervCimTypePtr typemap, const char *name,
+hypervCimTypePtr *property)
+{
+size_t i = 0;
+while (typemap[i].name[0] != '\0') {
+if (STREQ(typemap[i].name, name)) {
+*property = &typemap[i];
+return 0;
+}
+i++;
+}
+
+return -1;
+}
+
+
+static int
+hypervCreateInvokeXmlDoc(hypervInvokeParamsListPtr params, WsXmlDocH *docRoot)
+{
+int result = -1;
+char *method = NULL;
+WsXmlNodeH xmlNodeMethod = NULL;
+
+if (virAsprintf(&method, "%s_INPUT", params->method) < 0)
+goto cleanup;
+
+*docRoot = ws_xml_create_doc(NULL, method);
+if (*docRoot == NULL) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not instantiate XML document"));
+goto cleanup;
+}
+
+xmlNodeMethod = xml_parser_get_root(*docRoot);
+if (xmlNodeMethod == NULL) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not get root node of XML document"));
+goto cleanup;
+}
+
+/* add resource URI as namespace */
+ws_xml_set_ns(xmlNodeMethod, params->resourceUri, "p");
+
+result = 0;
+
+ cleanup:
+if (result < 0 && *docRoot != NULL) {
+ws_xml_destroy_doc(*docRoot);
+*docRoot = NULL;
+}
+VIR_FREE(method);
+return result;
+}
+
+static int
+hypervSerializeSimpleParam(hypervParamPtr p, const char *resourceUri,
+WsXmlNodeH *methodNode)
+{
+WsXmlNodeH xmlNodeParam = NULL;
+
+xmlNodeParam = ws_xml_add_child(*methodNode, resourceUri,
+p->simple.name, p->simple.value);
+if (xmlNodeParam == NULL) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not create simple param"));
+return -1;
+}
+
+return 0;
+}
+
+static int
+hypervSerializeEprParam(hypervParamPtr p, hypervPrivate *priv,
+const char *resourceUri, WsXmlDocH doc, WsXmlNodeH *methodNode)
+{
+int result = -1;
+WsXmlNodeH xmlNodeParam = NULL,
+   xmlNodeTemp = NULL,
+   xmlNodeAddr = NULL,
+   xmlNodeRef = NULL;
+xmlNodePtr xmlNodeAddrPtr = NULL,
+   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;
+
+/* init and set up options */
+options = wsmc_options_init();
+if (!options) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not init 
options"));
+goto cleanup;
+}
+wsmc_set_action_option(options, FLAG_ENUMERATION_ENUM_EPR);
+
+/* Get query and create filter based on it */
+if (virBufferCheckError(p->epr.query) < 0) {
+virBufferFreeAndReset(p->epr.query);
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid query"));
+goto cleanup;
+}
+query_string = virBufferContentAndReset(p->epr.query);
+
+filter = filter_create_simple(WSM_WQL_FILTER_DIALECT, query_string);
+if (!filter) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create WQL 
filter"));
+goto cleanup;
+}
+
+/* enumerate based on the filter from this query */
+xmlDocResponse = wsmc_action_enumerate(priv->client, p->epr.info->rootUri,
+options, filter);
+if (hypervVerifyResponse(priv->client, xmlDocResponse, "enumeration") < 0)
+goto cleanup;
+
+/* Get context */
+enumContext = wsmc_get_enum_context(xmlDocResponse);
+ws_xml_destroy_doc(xmlDocResponse);
+
+/* Pull using filter and enum context */
+xmlDocResponse = wsmc_action_pull(priv->client, resourceUri, options,
+filter, enumContext);
+
+if (hypervVerifyResponse(priv->client, xmlDocResponse, "pull") < 0)
+go

[libvirt] [PATCH v6 5/5] hyperv: Add support for virDomainSetMemory

2017-06-26 Thread Sri Ramanujam
Introduces support for virDomainSetMemory. This also serves an an
example for how to use the new method invocation API with a more
complicated method, this time including an EPR and embedded param.
---
 src/hyperv/hyperv_driver.c| 114 ++
 src/hyperv/hyperv_wmi.c   |  51 +++
 src/hyperv/hyperv_wmi.h   |  11 
 src/hyperv/hyperv_wmi_generator.input |  30 +
 4 files changed, 206 insertions(+)

diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index 7ee3d9a..a069afd 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -1497,6 +1497,118 @@ hypervDomainSendKey(virDomainPtr domain, unsigned int 
codeset,
 }
 
 
+static int
+hypervDomainSetMemoryFlags(virDomainPtr domain, unsigned long memory,
+unsigned int flags)
+{
+int result = -1;
+char uuid_string[VIR_UUID_STRING_BUFLEN];
+hypervPrivate *priv = domain->conn->privateData;
+char *memory_str = NULL;
+hypervInvokeParamsListPtr params = NULL;
+unsigned long memory_mb = VIR_ROUND_UP(VIR_DIV_UP(memory, 1024), 2);
+Msvm_VirtualSystemSettingData *vssd = NULL;
+Msvm_MemorySettingData *memsd = NULL;
+virBuffer eprQuery = VIR_BUFFER_INITIALIZER;
+virHashTablePtr memResource = NULL;
+
+virCheckFlags(0, -1);
+
+if (virAsprintf(&memory_str, "%lu", memory_mb) < 0)
+goto cleanup;
+
+virUUIDFormat(domain->uuid, uuid_string);
+
+if (hypervGetMsvmVirtualSystemSettingDataFromUUID(priv, uuid_string, 
&vssd) < 0)
+goto cleanup;
+
+if (hypervGetMsvmMemorySettingDataFromVSSD(priv, 
vssd->data.common->InstanceID,
+&memsd) < 0)
+goto cleanup;
+
+if (priv->wmiVersion == HYPERV_WMI_VERSION_V1) {
+params = hypervCreateInvokeParamsList(priv, 
"ModifyVirtualSystemResources",
+MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_SELECTOR,
+Msvm_VirtualSystemManagementService_WmiInfo);
+
+if (!params) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create 
params"));
+goto cleanup;
+}
+
+virBufferAddLit(&eprQuery, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+virBufferAsprintf(&eprQuery, "where Name = \"%s\"", uuid_string);
+
+if (hypervAddEprParam(params, "ComputerSystem", priv, &eprQuery,
+Msvm_ComputerSystem_WmiInfo) < 0)
+goto params_cleanup;
+} else if (priv->wmiVersion == HYPERV_WMI_VERSION_V2) {
+params = hypervCreateInvokeParamsList(priv, "ModifyResourceSettings",
+MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_SELECTOR,
+Msvm_VirtualSystemManagementService_WmiInfo);
+
+if (!params) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create 
params"));
+goto cleanup;
+}
+}
+
+memResource = hypervCreateEmbeddedParam(priv, 
Msvm_MemorySettingData_WmiInfo);
+if (!memResource)
+goto params_cleanup;
+
+if (hypervSetEmbeddedProperty(memResource, "VirtualQuantity", memory_str) 
< 0) {
+hypervFreeEmbeddedParam(memResource);
+goto params_cleanup;
+}
+
+if (hypervSetEmbeddedProperty(memResource, "InstanceID",
+memsd->data.common->InstanceID) < 0) {
+hypervFreeEmbeddedParam(memResource);
+goto params_cleanup;
+}
+
+if (priv->wmiVersion == HYPERV_WMI_VERSION_V1) {
+if (hypervAddEmbeddedParam(params, priv, "ResourceSettingData",
+memResource, Msvm_MemorySettingData_WmiInfo) < 0) {
+hypervFreeEmbeddedParam(memResource);
+goto params_cleanup;
+}
+
+} else if (priv->wmiVersion == HYPERV_WMI_VERSION_V2) {
+if (hypervAddEmbeddedParam(params, priv, "ResourceSettings",
+memResource, Msvm_MemorySettingData_WmiInfo) < 0) {
+hypervFreeEmbeddedParam(memResource);
+goto params_cleanup;
+}
+}
+
+if (hypervInvokeMethod(priv, params, NULL) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not set 
memory"));
+goto cleanup;
+}
+
+result = 0;
+goto cleanup;
+
+ params_cleanup:
+hypervFreeInvokeParams(params);
+virBufferFreeAndReset(&eprQuery);
+ cleanup:
+VIR_FREE(memory_str);
+hypervFreeObject(priv, (hypervObject *) vssd);
+hypervFreeObject(priv, (hypervObject *) memsd);
+return result;
+}
+
+
+static int
+hypervDomainSetMemory(virDomainPtr domain, unsigned long memory)
+{
+return hypervDomainSetMemoryFlags(domain, memory, 0);
+}
+
+
 static virHypervisorDriver hypervHypervisorDriver = {
 .name = "Hyper-V",
 .connectOpen = hypervConnectOpen, /* 0.9.5 */
@@ -1531,6 +1643,8 @@ static virHypervisorDriver hypervHypervisorDriver = {
 .domainHasManagedSaveImage = hypervDomainHasManagedSaveImage, /* 0.9.5 */
 .domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */
 

[libvirt] [PATCH v6 4/5] hyperv: support virDomainSendKey

2017-06-26 Thread Sri Ramanujam
This commit adds support for virDomainSendKey. It also serves as an
example of how to use the new method invocation APIs with a single
"simple" type parameter.
---
 src/hyperv/hyperv_driver.c| 123 ++
 src/hyperv/hyperv_wmi.c   |   7 ++
 src/hyperv/hyperv_wmi.h   |   3 +-
 src/hyperv/hyperv_wmi_generator.input |  86 
 4 files changed, 218 insertions(+), 1 deletion(-)

diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index 0ca5971..7ee3d9a 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -35,6 +35,8 @@
 #include "hyperv_wmi.h"
 #include "openwsman.h"
 #include "virstring.h"
+#include "virkeycode.h"
+#include "intprops.h"
 
 #define VIR_FROM_THIS VIR_FROM_HYPERV
 
@@ -1373,6 +1375,126 @@ hypervConnectListAllDomains(virConnectPtr conn,
 #undef MATCH
 
 
+static int
+hypervDomainSendKey(virDomainPtr domain, unsigned int codeset,
+unsigned int holdtime, unsigned int *keycodes, int nkeycodes,
+unsigned int flags)
+{
+int result = -1;
+size_t i = 0;
+int keycode = 0;
+int *translatedKeycodes = NULL;
+hypervPrivate *priv = domain->conn->privateData;
+char uuid_string[VIR_UUID_STRING_BUFLEN];
+char *selector = NULL;
+Msvm_ComputerSystem *computerSystem = NULL;
+Msvm_Keyboard *keyboard = NULL;
+virBuffer query = VIR_BUFFER_INITIALIZER;
+hypervInvokeParamsListPtr params = NULL;
+char keycodeStr[INT_BUFSIZE_BOUND(int)];
+
+virCheckFlags(0, -1);
+
+virUUIDFormat(domain->uuid, uuid_string);
+
+if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
+goto cleanup;
+
+virBufferAsprintf(&query,
+"associators of "
+"{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+"Name=\"%s\"} "
+"where ResultClass = Msvm_Keyboard",
+uuid_string);
+
+if (hypervGetMsvmKeyboardList(priv, &query, &keyboard) < 0)
+goto cleanup;
+
+if (VIR_ALLOC_N(translatedKeycodes, nkeycodes) < 0)
+goto cleanup;
+
+/* translate keycodes to win32 and generate keyup scancodes. */
+for (i = 0; i < nkeycodes; i++) {
+if (codeset != VIR_KEYCODE_SET_WIN32) {
+keycode = virKeycodeValueTranslate(codeset, VIR_KEYCODE_SET_WIN32,
+keycodes[i]);
+
+if (keycode < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not translate keycode"));
+goto cleanup;
+}
+translatedKeycodes[i] = keycode;
+}
+}
+
+if (virAsprintf(&selector,
+"CreationClassName=Msvm_Keyboard&DeviceID=%s&"
+"SystemCreationClassName=Msvm_ComputerSystem&"
+"SystemName=%s", keyboard->data.common->DeviceID, uuid_string) 
< 0)
+goto cleanup;
+
+/* press the keys */
+for (i = 0; i < nkeycodes; i++) {
+snprintf(keycodeStr, sizeof(keycodeStr), "%d", translatedKeycodes[i]);
+
+params = hypervCreateInvokeParamsList(priv, "PressKey", selector,
+Msvm_Keyboard_WmiInfo);
+
+if (!params) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create 
param"));
+goto cleanup;
+}
+
+if (hypervAddSimpleParam(params, "keyCode", keycodeStr) < 0) {
+hypervFreeInvokeParams(params);
+goto cleanup;
+}
+
+if (hypervInvokeMethod(priv, params, NULL) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not press key %d"),
+   translatedKeycodes[i]);
+goto cleanup;
+}
+}
+
+/* simulate holdtime by sleeping */
+if (holdtime > 0)
+usleep(holdtime * 1000);
+
+/* release the keys */
+for (i = 0; i < nkeycodes; i++) {
+snprintf(keycodeStr, sizeof(keycodeStr), "%d", translatedKeycodes[i]);
+params = hypervCreateInvokeParamsList(priv, "ReleaseKey", selector,
+Msvm_Keyboard_WmiInfo);
+
+if (!params) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create 
param"));
+goto cleanup;
+}
+
+if (hypervAddSimpleParam(params, "keyCode", keycodeStr) < 0) {
+hypervFreeInvokeParams(params);
+goto cleanup;
+}
+
+if (hypervInvokeMethod(priv, params, NULL) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not release key 
%s"),
+keycodeStr);
+goto cleanup;
+}
+}
+
+result = 0;
+
+ cleanup:
+VIR_FREE(translatedKeycodes);
+VIR_FREE(selector);
+hypervFreeObject(priv, (hypervObject *) keyboard);
+hypervFreeObject(priv, (hypervObject *) computerSystem);
+virBufferFreeAndReset(&query);
+return result;
+}
 
 
 static virHypervisorDriver hypervHypervisorDriver = {
@@ -1408,6 +153

[libvirt] [PATCH v6 0/5] Hyper-V method invocation

2017-06-26 Thread Sri Ramanujam
Changes from v5:
  * Changes from review
  * Fixed memory leak in hypervDomainSetMemory where params would leak in 
failure case

Sri Ramanujam (5):
  hyperv: Functions to work with invocation parameters.
  hyperv: Generate object property type information.
  hyperv: add hypervInvokeMethod
  hyperv: support virDomainSendKey
  hyperv: Add support for virDomainSetMemory

 src/hyperv/hyperv_driver.c| 237 +
 src/hyperv/hyperv_wmi.c   | 910 ++
 src/hyperv/hyperv_wmi.h   |  95 +++-
 src/hyperv/hyperv_wmi_classes.h   |  19 +
 src/hyperv/hyperv_wmi_generator.input | 116 +
 src/hyperv/hyperv_wmi_generator.py|  15 +-
 src/hyperv/openwsman.h|   4 +
 7 files changed, 1394 insertions(+), 2 deletions(-)

-- 
2.9.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v5 1/5] hyperv: Functions to work with invocation parameters.

2017-06-12 Thread Sri Ramanujam
This commit introduces functionality for creating and working with
invoke parameters. This commit does not include any code for serializing
and actually performing the method invocations; it merely defines the
functions and API for using invocation parameters in driver code.

HYPERV_DEFAULT_PARAM_COUNT was chosen because almost no method
invocations have more than 4 parameters.

Functions added:
* hypervInitInvokeParamsList
* hypervFreeInvokeParams
* hypervAddSimpleParam
* hypervAddEprParam
* hypervCreateEmbeddedParam
* hypervSetEmbeddedProperty
* hypervAddEmbeddedParam
* hypervFreeEmbeddedParam
---
 src/hyperv/hyperv_wmi.c | 262 
 src/hyperv/hyperv_wmi.h |  79 ++-
 2 files changed, 340 insertions(+), 1 deletion(-)

diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index a3c7dc0..2732db3 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -2,6 +2,7 @@
  * hyperv_wmi.c: general WMI over WSMAN related functions and structures for
  *   managing Microsoft Hyper-V hosts
  *
+ * Copyright (C) 2017 Datto Inc
  * Copyright (C) 2014 Red Hat, Inc.
  * Copyright (C) 2011 Matthias Bolte 
  * Copyright (C) 2009 Michael Sievers 
@@ -142,6 +143,267 @@ hypervVerifyResponse(WsManClient *client, WsXmlDocH 
response,
 }
 
 
+/*
+ * Methods to work with method invocation parameters
+ */
+
+/*
+ * hypervCreateInvokeParamsList:
+ * @priv: hypervPrivate object associated with the connection.
+ * @method: The name of the method you are calling
+ * @selector: The selector for the object you are invoking the method on
+ * @obj: The WmiInfo of the object class you are invoking the method on.
+ *
+ * Create a new InvokeParamsList object for the method call.
+ *
+ * Returns a pointer to the newly instantiated object on success, which should
+ * be freed by hypervInvokeMethod. Otherwise returns NULL.
+ */
+hypervInvokeParamsListPtr
+hypervCreateInvokeParamsList(hypervPrivate *priv, const char *method,
+const char *selector, hypervWmiClassInfoListPtr obj)
+{
+hypervInvokeParamsListPtr params = NULL;
+hypervWmiClassInfoPtr info = NULL;
+
+if (hypervGetWmiClassInfo(priv, obj, &info) < 0)
+goto cleanup;
+
+if (VIR_ALLOC(params) < 0)
+goto cleanup;
+
+if (VIR_ALLOC_N(params->params,
+HYPERV_DEFAULT_PARAM_COUNT) < 0) {
+VIR_FREE(params);
+goto cleanup;
+}
+
+params->method = method;
+params->ns = info->rootUri;
+params->resourceUri = info->resourceUri;
+params->selector = selector;
+params->nbParams = 0;
+params->nbAvailParams = HYPERV_DEFAULT_PARAM_COUNT;
+
+ cleanup:
+return params;
+}
+
+/*
+ * hypervFreeInvokeParams:
+ * @params: Params object to be freed
+ *
+ */
+void
+hypervFreeInvokeParams(hypervInvokeParamsListPtr params)
+{
+hypervParamPtr p = NULL;
+size_t i = 0;
+
+if (params == NULL)
+return;
+
+for (i = 0; i < params->nbParams; i++) {
+p = &(params->params[i]);
+
+switch (p->type) {
+case HYPERV_SIMPLE_PARAM:
+break;
+case HYPERV_EPR_PARAM:
+virBufferFreeAndReset(p->epr.query);
+break;
+case HYPERV_EMBEDDED_PARAM:
+hypervFreeEmbeddedParam(p->embedded.table);
+break;
+default:
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Invalid parameter type passed to free"));
+}
+}
+
+VIR_DISPOSE_N(params->params, params->nbAvailParams);
+VIR_FREE(params);
+}
+
+static inline int
+hypervCheckParams(hypervInvokeParamsListPtr params)
+{
+if (params->nbParams + 1 > params->nbAvailParams) {
+if (VIR_EXPAND_N(params->params, params->nbAvailParams, 5) < 0)
+return -1;
+}
+
+return 0;
+}
+
+/*
+ * hypervAddSimpleParam:
+ * @params: Params object to add to
+ * @name: Name of the parameter
+ * @value: Value of the parameter
+ *
+ * Add a param of type HYPERV_SIMPLE_PARAM, which is essentially a serialized
+ * key/value pair.
+ *
+ * Returns -1 on failure, 0 on success.
+ */
+int
+hypervAddSimpleParam(hypervInvokeParamsListPtr params, const char *name,
+const char *value)
+{
+int result = -1;
+hypervParamPtr p = NULL;
+
+if (hypervCheckParams(params) < 0)
+goto cleanup;
+
+p = ¶ms->params[params->nbParams];
+p->type = HYPERV_SIMPLE_PARAM;
+
+p->simple.name = name;
+p->simple.value = value;
+
+params->nbParams++;
+
+result = 0;
+
+ cleanup:
+return result;
+}
+
+/*
+ * hypervAddEprParam:
+ * @params: Params object to add to
+ * @name: Parameter name
+ * @priv: hypervPrivate object associated with the connection
+ * @query: WQL filter
+ * @eprInfo: WmiInfo of the object being filtered
+ *
+ * Adds an EPR param to the params list. Returns -1 on failure, 0 on success.
+ */
+int
+hypervAddEprParam(hypervInvokeParamsListPtr params, con

[libvirt] [PATCH v5 3/5] hyperv: add hypervInvokeMethod

2017-06-12 Thread Sri Ramanujam
This commit adds support for invoking methods on remote objects
via hypervInvokeMethod.
---
 src/hyperv/hyperv_wmi.c | 591 
 src/hyperv/hyperv_wmi.h |   8 +-
 src/hyperv/openwsman.h  |   4 +
 3 files changed, 601 insertions(+), 2 deletions(-)

diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index 2732db3..3b65f60 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -24,6 +24,7 @@
  */
 
 #include 
+#include 
 
 #include "internal.h"
 #include "virerror.h"
@@ -34,11 +35,16 @@
 #include "hyperv_private.h"
 #include "hyperv_wmi.h"
 #include "virstring.h"
+#include "openwsman.h"
+#include "virlog.h"
 
 #define WS_SERIALIZER_FREE_MEM_WORKS 0
 
 #define VIR_FROM_THIS VIR_FROM_HYPERV
 
+#define HYPERV_JOB_TIMEOUT_MS 5000
+
+VIR_LOG_INIT("hyperv.hyperv_wmi");
 
 static int
 hypervGetWmiClassInfo(hypervPrivate *priv, hypervWmiClassInfoListPtr list,
@@ -334,6 +340,7 @@ hypervCreateEmbeddedParam(hypervPrivate *priv, 
hypervWmiClassInfoListPtr info)
 for (i = 0; typeinfo[i].name != NULL; i++) {}
 count = i;
 
+count = i + 1;
 table = virHashCreate(count, NULL);
 if (table == NULL)
 goto error;
@@ -405,6 +412,590 @@ hypervFreeEmbeddedParam(virHashTablePtr p)
 virHashFree(p);
 }
 
+/*
+ * Serializing parameters to XML and invoking methods
+ */
+
+static int
+hypervGetCimTypeInfo(hypervCimTypePtr typemap, const char *name,
+hypervCimTypePtr *property)
+{
+size_t i = 0;
+while (typemap[i].name[0] != '\0') {
+if (STREQ(typemap[i].name, name)) {
+*property = &typemap[i];
+return 0;
+}
+i++;
+}
+
+return -1;
+}
+
+
+static int
+hypervCreateInvokeXmlDoc(hypervInvokeParamsListPtr params, WsXmlDocH *docRoot)
+{
+int result = -1;
+char *method = NULL;
+WsXmlNodeH xmlNodeMethod = NULL;
+
+if (virAsprintf(&method, "%s_INPUT", params->method) < 0)
+goto cleanup;
+
+*docRoot = ws_xml_create_doc(NULL, method);
+if (*docRoot == NULL) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not instantiate XML document"));
+goto cleanup;
+}
+
+xmlNodeMethod = xml_parser_get_root(*docRoot);
+if (xmlNodeMethod == NULL) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not get root node of XML document"));
+goto cleanup;
+}
+
+/* add resource URI as namespace */
+ws_xml_set_ns(xmlNodeMethod, params->resourceUri, "p");
+
+result = 0;
+
+ cleanup:
+if (result < 0 && *docRoot != NULL) {
+ws_xml_destroy_doc(*docRoot);
+*docRoot = NULL;
+}
+VIR_FREE(method);
+return result;
+}
+
+static int
+hypervSerializeSimpleParam(hypervParamPtr p, const char *resourceUri,
+WsXmlNodeH *methodNode)
+{
+WsXmlNodeH xmlNodeParam = NULL;
+
+xmlNodeParam = ws_xml_add_child(*methodNode, resourceUri,
+p->simple.name, p->simple.value);
+if (xmlNodeParam == NULL) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not create simple param"));
+return -1;
+}
+
+return 0;
+}
+
+static int
+hypervSerializeEprParam(hypervParamPtr p, hypervPrivate *priv,
+const char *resourceUri, WsXmlDocH doc, WsXmlNodeH *methodNode)
+{
+int result = -1;
+WsXmlNodeH xmlNodeParam = NULL,
+   xmlNodeTemp = NULL,
+   xmlNodeAddr = NULL,
+   xmlNodeRef = NULL;
+xmlNodePtr xmlNodeAddrPtr = NULL,
+   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;
+
+/* init and set up options */
+options = wsmc_options_init();
+if (!options) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not init 
options"));
+goto cleanup;
+}
+wsmc_set_action_option(options, FLAG_ENUMERATION_ENUM_EPR);
+
+/* Get query and create filter based on it */
+if (virBufferCheckError(p->epr.query) < 0) {
+virBufferFreeAndReset(p->epr.query);
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid query"));
+goto cleanup;
+}
+query_string = virBufferContentAndReset(p->epr.query);
+
+filter = filter_create_simple(WSM_WQL_FILTER_DIALECT, query_string);
+if (!filter) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create WQL 
filter"));
+goto cleanup;
+}
+
+/* enumerate based on the filter from this query */
+xmlDocResponse = wsmc_action_enumerate(priv->client, p->epr.info->rootUri,
+options, filter);
+if (hypervVerifyResponse(priv->client, xmlDocResponse, "enumeration") < 0)
+goto cleanup;
+
+/* Get context */
+enumContext = wsmc_get_enum_context(xmlDocResponse);
+ws_xm

[libvirt] [PATCH v5 4/5] hyperv: support virDomainSendKey

2017-06-12 Thread Sri Ramanujam
This commit adds support for virDomainSendKey. It also serves as an
example of how to use the new method invocation APIs with a single
"simple" type parameter.
---
 src/hyperv/hyperv_driver.c| 123 ++
 src/hyperv/hyperv_wmi.c   |   7 ++
 src/hyperv/hyperv_wmi.h   |   3 +-
 src/hyperv/hyperv_wmi_generator.input |  86 
 4 files changed, 218 insertions(+), 1 deletion(-)

diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index 0ca5971..3f5b94e 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -35,6 +35,8 @@
 #include "hyperv_wmi.h"
 #include "openwsman.h"
 #include "virstring.h"
+#include "virkeycode.h"
+#include "intprops.h"
 
 #define VIR_FROM_THIS VIR_FROM_HYPERV
 
@@ -1373,6 +1375,126 @@ hypervConnectListAllDomains(virConnectPtr conn,
 #undef MATCH
 
 
+static int
+hypervDomainSendKey(virDomainPtr domain, unsigned int codeset,
+unsigned int holdtime, unsigned int *keycodes, int nkeycodes,
+unsigned int flags)
+{
+int result = -1;
+size_t i = 0;
+int keycode = 0;
+int *translatedKeycodes = NULL;
+hypervPrivate *priv = domain->conn->privateData;
+char uuid_string[VIR_UUID_STRING_BUFLEN];
+char *selector = NULL;
+Msvm_ComputerSystem *computerSystem = NULL;
+Msvm_Keyboard *keyboard = NULL;
+virBuffer query = VIR_BUFFER_INITIALIZER;
+hypervInvokeParamsListPtr params = NULL;
+char keycodeStr[INT_BUFSIZE_BOUND(int)];
+
+virCheckFlags(0, -1);
+
+virUUIDFormat(domain->uuid, uuid_string);
+
+if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
+goto cleanup;
+
+virBufferAsprintf(&query,
+"associators of "
+"{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+"Name=\"%s\"} "
+"where ResultClass = Msvm_Keyboard",
+uuid_string);
+
+if (hypervGetMsvmKeyboardList(priv, &query, &keyboard) < 0)
+goto cleanup;
+
+if (VIR_ALLOC_N(translatedKeycodes, nkeycodes) < 0)
+goto cleanup;
+
+/* translate keycodes to win32 and generate keyup scancodes. */
+for (i = 0; i < nkeycodes; i++) {
+if (codeset != VIR_KEYCODE_SET_WIN32) {
+keycode = virKeycodeValueTranslate(codeset, VIR_KEYCODE_SET_WIN32,
+keycodes[i]);
+
+if (keycode < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not translate keycode"));
+goto cleanup;
+}
+translatedKeycodes[i] = keycode;
+}
+}
+
+if (virAsprintf(&selector,
+"CreationClassName=Msvm_Keyboard&DeviceID=%s&"
+"SystemCreationClassName=Msvm_ComputerSystem&"
+"SystemName=%s", keyboard->data.common->DeviceID, uuid_string) 
< 0)
+goto cleanup;
+
+/* press the keys */
+for (i = 0; i < nkeycodes; i++) {
+params = NULL;
+
+snprintf(keycodeStr, sizeof(keycodeStr), "%d", translatedKeycodes[i]);
+
+params = hypervCreateInvokeParamsList(priv, "PressKey", selector,
+Msvm_Keyboard_WmiInfo);
+
+if (!params) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create 
param"));
+goto cleanup;
+}
+
+if (hypervAddSimpleParam(params, "keyCode", keycodeStr) < 0)
+goto cleanup;
+
+if (hypervInvokeMethod(priv, params, NULL) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not press key %d"),
+   translatedKeycodes[i]);
+goto cleanup;
+}
+}
+
+/* simulate holdtime by sleeping */
+if (holdtime > 0)
+usleep(holdtime * 1000);
+
+/* release the keys */
+for (i = 0; i < nkeycodes; i++) {
+params = NULL;
+
+snprintf(keycodeStr, sizeof(keycodeStr), "%d", translatedKeycodes[i]);
+params = hypervCreateInvokeParamsList(priv, "ReleaseKey", selector,
+Msvm_Keyboard_WmiInfo);
+
+if (!params) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create 
param"));
+goto cleanup;
+}
+
+if (hypervAddSimpleParam(params, "keyCode", keycodeStr) < 0)
+goto cleanup;
+
+if (hypervInvokeMethod(priv, params, NULL) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not release key 
%s"),
+keycodeStr);
+goto cleanup;
+}
+}
+
+result = 0;
+
+ cleanup:
+VIR_FREE(translatedKeycodes);
+VIR_FREE(selector);
+hypervFreeObject(priv, (hypervObject *) keyboard);
+hypervFreeObject(priv, (hypervObject *) computerSystem);
+virBufferFreeAndReset(&query);
+return result;
+}
 
 
 static virHypervisorDriver hypervHypervisorDriver = {
@@ -1408,6 +1530,7 @@ static virHypervisorDriver hypervHypervisorDriver = {
   

[libvirt] [PATCH v5 5/5] hyperv: Add support for virDomainSetMemory

2017-06-12 Thread Sri Ramanujam
Introduces support for virDomainSetMemory. This also serves an an
example for how to use the new method invocation API with a more
complicated method, this time including an EPR and embedded param.
---
 src/hyperv/hyperv_driver.c| 105 ++
 src/hyperv/hyperv_wmi.c   |  51 +
 src/hyperv/hyperv_wmi.h   |  11 
 src/hyperv/hyperv_wmi_generator.input |  30 ++
 4 files changed, 197 insertions(+)

diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index 3f5b94e..f557408 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -1497,6 +1497,109 @@ hypervDomainSendKey(virDomainPtr domain, unsigned int 
codeset,
 }
 
 
+static int
+hypervDomainSetMemoryFlags(virDomainPtr domain, unsigned long memory,
+unsigned int flags)
+{
+int result = -1;
+char uuid_string[VIR_UUID_STRING_BUFLEN];
+hypervPrivate *priv = domain->conn->privateData;
+char *memory_str = NULL;
+hypervInvokeParamsListPtr params = NULL;
+unsigned long memory_mb = VIR_ROUND_UP(VIR_DIV_UP(memory, 1024), 2);
+Msvm_VirtualSystemSettingData *vssd = NULL;
+Msvm_MemorySettingData *memsd = NULL;
+virBuffer eprQuery = VIR_BUFFER_INITIALIZER;
+virHashTablePtr memResource = NULL;
+
+virCheckFlags(0, -1);
+
+if (virAsprintf(&memory_str, "%lu", memory_mb) < 0)
+goto cleanup;
+
+virUUIDFormat(domain->uuid, uuid_string);
+
+if (hypervGetMsvmVirtualSystemSettingDataFromUUID(priv, uuid_string, 
&vssd) < 0)
+goto cleanup;
+
+if (hypervGetMsvmMemorySettingDataFromVSSD(priv, 
vssd->data.common->InstanceID,
+&memsd) < 0)
+goto cleanup;
+
+if (priv->wmiVersion == HYPERV_WMI_VERSION_V1) {
+params = hypervCreateInvokeParamsList(priv, 
"ModifyVirtualSystemResources",
+MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_SELECTOR,
+Msvm_VirtualSystemManagementService_WmiInfo);
+
+if (!params) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create 
params"));
+goto cleanup;
+}
+
+virBufferAddLit(&eprQuery, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+virBufferAsprintf(&eprQuery, "where Name = \"%s\"", uuid_string);
+
+if (hypervAddEprParam(params, "ComputerSystem", priv, &eprQuery,
+Msvm_ComputerSystem_WmiInfo) < 0)
+goto cleanup;
+} else if (priv->wmiVersion == HYPERV_WMI_VERSION_V2) {
+params = hypervCreateInvokeParamsList(priv, "ModifyResourceSettings",
+MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_SELECTOR,
+Msvm_VirtualSystemManagementService_WmiInfo);
+
+if (!params) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create 
params"));
+goto cleanup;
+}
+}
+
+memResource = hypervCreateEmbeddedParam(priv, 
Msvm_MemorySettingData_WmiInfo);
+if (!memResource)
+goto cleanup;
+
+if (hypervSetEmbeddedProperty(memResource, "VirtualQuantity", memory_str) 
< 0)
+goto cleanup;
+
+if (hypervSetEmbeddedProperty(memResource, "InstanceID",
+memsd->data.common->InstanceID) < 0)
+goto cleanup;
+
+if (priv->wmiVersion == HYPERV_WMI_VERSION_V1) {
+if (hypervAddEmbeddedParam(params, priv, "ResourceSettingData",
+memResource, Msvm_MemorySettingData_WmiInfo) < 0)
+goto cleanup;
+
+} else if (priv->wmiVersion == HYPERV_WMI_VERSION_V2) {
+if (hypervAddEmbeddedParam(params, priv, "ResourceSettings",
+memResource, Msvm_MemorySettingData_WmiInfo) < 0)
+goto cleanup;
+}
+
+if (hypervInvokeMethod(priv, params, NULL) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not set 
memory"));
+goto cleanup;
+}
+
+/* set embedded param to NULL on success to avoid double-free in cleanup */
+memResource = NULL;
+
+result = 0;
+ cleanup:
+VIR_FREE(memory_str);
+hypervFreeEmbeddedParam(memResource);
+hypervFreeObject(priv, (hypervObject *) vssd);
+hypervFreeObject(priv, (hypervObject *) memsd);
+return result;
+}
+
+
+static int
+hypervDomainSetMemory(virDomainPtr domain, unsigned long memory)
+{
+return hypervDomainSetMemoryFlags(domain, memory, 0);
+}
+
+
 static virHypervisorDriver hypervHypervisorDriver = {
 .name = "Hyper-V",
 .connectOpen = hypervConnectOpen, /* 0.9.5 */
@@ -1531,6 +1634,8 @@ static virHypervisorDriver hypervHypervisorDriver = {
 .domainHasManagedSaveImage = hypervDomainHasManagedSaveImage, /* 0.9.5 */
 .domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */
 .domainSendKey = hypervDomainSendKey, /* TODO: version */
+.domainSetMemory = hypervDomainSetMemory, /* TODO: version */
+.domainSetMemoryFlags = hypervDomainSetMemoryFlags, /* TODO: version */
 .connectIsAlive = hypervConnectIsAli

[libvirt] [PATCH v5 0/5] Hyper-V method invocation

2017-06-12 Thread Sri Ramanujam
Changes from v4:
 * Changes from review
 * Added hypervFreeEmbeddedParam

Sri Ramanujam (5):
  hyperv: Functions to work with invocation parameters.
  hyperv: Generate object property type information.
  hyperv: add hypervInvokeMethod
  hyperv: support virDomainSendKey
  hyperv: Add support for virDomainSetMemory

 src/hyperv/hyperv_driver.c| 228 +
 src/hyperv/hyperv_wmi.c   | 911 ++
 src/hyperv/hyperv_wmi.h   |  95 +++-
 src/hyperv/hyperv_wmi_classes.h   |  19 +
 src/hyperv/hyperv_wmi_generator.input | 116 +
 src/hyperv/hyperv_wmi_generator.py|  15 +-
 src/hyperv/openwsman.h|   4 +
 7 files changed, 1386 insertions(+), 2 deletions(-)

-- 
2.9.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v5 2/5] hyperv: Generate object property type information.

2017-06-12 Thread Sri Ramanujam
Update the generator to generate basic property type information for
each CIM object representation. Right now, it generates arrays of
hypervCimType structs:

struct _hypervCimType {
const char *name;
const char *type;
bool isArray;
};
---
 src/hyperv/hyperv_wmi_classes.h| 19 +++
 src/hyperv/hyperv_wmi_generator.py | 15 ++-
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/src/hyperv/hyperv_wmi_classes.h b/src/hyperv/hyperv_wmi_classes.h
index f7d596f..ce4643e 100644
--- a/src/hyperv/hyperv_wmi_classes.h
+++ b/src/hyperv/hyperv_wmi_classes.h
@@ -1,6 +1,7 @@
 /*
  * hyperv_wmi_classes.h: WMI classes for managing Microsoft Hyper-V hosts
  *
+ * Copyright (C) 2017 Datto Inc
  * Copyright (C) 2011 Matthias Bolte 
  * Copyright (C) 2009 Michael Sievers 
  *
@@ -23,6 +24,7 @@
 #ifndef __HYPERV_WMI_CLASSES_H__
 # define __HYPERV_WMI_CLASSES_H__
 
+# include "internal.h"
 # include "openwsman.h"
 
 # include "hyperv_wmi_classes.generated.typedef"
@@ -96,6 +98,21 @@ enum _Msvm_ConcreteJob_JobState {
 };
 
 
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * WMI
+ */
+
+typedef struct _hypervCimType hypervCimType;
+typedef hypervCimType *hypervCimTypePtr;
+struct _hypervCimType {
+/* Parameter name */
+const char *name;
+/* Parameter type */
+const char *type;
+/* whether parameter is an array type */
+bool isArray;
+};
+
 typedef struct _hypervWmiClassInfo hypervWmiClassInfo;
 typedef hypervWmiClassInfo *hypervWmiClassInfoPtr;
 struct _hypervWmiClassInfo {
@@ -109,6 +126,8 @@ struct _hypervWmiClassInfo {
 const char *resourceUri;
 /* The wsman serializer info - one of the *_TypeInfo structs */
 XmlSerializerInfo *serializerInfo;
+/* Property type information */
+hypervCimTypePtr propertyInfo;
 };
 
 
diff --git a/src/hyperv/hyperv_wmi_generator.py 
b/src/hyperv/hyperv_wmi_generator.py
index 9aee0b9..9c0acce 100755
--- a/src/hyperv/hyperv_wmi_generator.py
+++ b/src/hyperv/hyperv_wmi_generator.py
@@ -122,6 +122,14 @@ class WmiClass:
 
 source += "SER_END_ITEMS(%s_Data);\n\n" % cls.name
 
+# also generate typemap data while we're here
+source += "hypervCimType %s_Typemap[] = {\n" % cls.name
+
+for property in cls.properties:
+source += property.generate_typemap()
+source += '{ "", "", 0 },\n' # null terminated
+source += '};\n\n'
+
 
 source += self._define_WmiInfo_struct()
 source += "\n\n"
@@ -222,7 +230,8 @@ class WmiClass:
 source += ".version = NULL,\n"
 source += ".rootUri = %s,\n" % cls.uri_info.rootUri
 source += ".resourceUri = %s_RESOURCE_URI,\n" % 
cls.name.upper()
-source += ".serializerInfo = %s_Data_TypeInfo\n" % 
cls.name
+source += ".serializerInfo = %s_Data_TypeInfo,\n" % 
cls.name
+source += ".propertyInfo = %s_Typemap\n" % cls.name
 source += "},\n"
 
 source += "}\n"
@@ -374,6 +383,10 @@ class Property:
% (Property.typemap[self.type], class_name.upper(), 
self.name)
 
 
+def generate_typemap(self):
+return '{ "%s", "%s", %s },\n' % (self.name, self.type.lower(), 
str(self.is_array).lower())
+
+
 
 def open_and_print(filename):
 if filename.startswith("./"):
-- 
2.9.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v4 4/5] hyperv: support virDomainSendKey

2017-05-19 Thread Sri Ramanujam
This commit adds support for virDomainSendKey. It also serves as an
example of how to use the new method invocation APIs with a single
"simple" type parameter.
---
 src/hyperv/hyperv_driver.c| 107 ++
 src/hyperv/hyperv_wmi.c   |   7 +++
 src/hyperv/hyperv_wmi.h   |   3 +-
 src/hyperv/hyperv_wmi_generator.input |  86 +++
 4 files changed, 202 insertions(+), 1 deletion(-)

diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index 0ca5971..a01515a 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -35,6 +35,8 @@
 #include "hyperv_wmi.h"
 #include "openwsman.h"
 #include "virstring.h"
+#include "virkeycode.h"
+#include "intprops.h"
 
 #define VIR_FROM_THIS VIR_FROM_HYPERV
 
@@ -1373,6 +1375,110 @@ hypervConnectListAllDomains(virConnectPtr conn,
 #undef MATCH
 
 
+static int
+hypervDomainSendKey(virDomainPtr domain, unsigned int codeset,
+unsigned int holdtime, unsigned int *keycodes, int nkeycodes,
+unsigned int flags)
+{
+int result = -1;
+size_t i = 0;
+int keycode = 0;
+int *translatedKeycodes = NULL;
+hypervPrivate *priv = domain->conn->privateData;
+char uuid_string[VIR_UUID_STRING_BUFLEN];
+char *selector = NULL;
+Msvm_ComputerSystem *computerSystem = NULL;
+Msvm_Keyboard *keyboard = NULL;
+virBuffer query = VIR_BUFFER_INITIALIZER;
+hypervInvokeParamsListPtr params = NULL;
+char keycodeStr[INT_BUFSIZE_BOUND(int)];
+
+virCheckFlags(0, -1);
+
+virUUIDFormat(domain->uuid, uuid_string);
+
+if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
+goto cleanup;
+
+virBufferAsprintf(&query,
+"associators of "
+"{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+"Name=\"%s\"} "
+"where ResultClass = Msvm_Keyboard",
+uuid_string);
+
+if (hypervGetMsvmKeyboardList(priv, &query, &keyboard) < 0)
+goto cleanup;
+
+if (VIR_ALLOC_N(translatedKeycodes, nkeycodes) < 0)
+goto cleanup;
+
+/* translate keycodes to win32 and generate keyup scancodes. */
+for (i = 0; i < nkeycodes; i++) {
+if (codeset != VIR_KEYCODE_SET_WIN32) {
+keycode = virKeycodeValueTranslate(codeset, VIR_KEYCODE_SET_WIN32,
+keycodes[i]);
+
+if (keycode < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not translate keycode"));
+goto cleanup;
+}
+translatedKeycodes[i] = keycode;
+}
+}
+
+if (virAsprintf(&selector,
+"CreationClassName=Msvm_Keyboard&DeviceID=%s&"
+"SystemCreationClassName=Msvm_ComputerSystem&"
+"SystemName=%s", keyboard->data.common->DeviceID, uuid_string) 
< 0)
+goto cleanup;
+
+/* press the keys */
+for (i = 0; i < nkeycodes; i++) {
+snprintf(keycodeStr, sizeof(keycodeStr), "%d", translatedKeycodes[i]);
+
+params = hypervCreateInvokeParamsList(priv, "PressKey", selector,
+Msvm_Keyboard_WmiInfo);
+if (hypervAddSimpleParam(params, "keyCode", keycodeStr) < 0)
+goto cleanup;
+
+if (hypervInvokeMethod(priv, params, NULL) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not press key %d"),
+   translatedKeycodes[i]);
+goto cleanup;
+}
+}
+
+/* simulate holdtime by sleeping */
+if (holdtime > 0)
+usleep(holdtime * 1000);
+
+/* release the keys */
+for (i = 0; i < nkeycodes; i++) {
+snprintf(keycodeStr, sizeof(keycodeStr), "%d", translatedKeycodes[i]);
+params = hypervCreateInvokeParamsList(priv, "ReleaseKey", selector,
+Msvm_Keyboard_WmiInfo);
+if (hypervAddSimpleParam(params, "keyCode", keycodeStr) < 0)
+goto cleanup;
+
+if (hypervInvokeMethod(priv, params, NULL) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not release key 
%s"),
+keycodeStr);
+goto cleanup;
+}
+}
+
+result = 0;
+
+ cleanup:
+VIR_FREE(translatedKeycodes);
+VIR_FREE(selector);
+hypervFreeObject(priv, (hypervObject *) keyboard);
+hypervFreeObject(priv, (hypervObject *) computerSystem);
+virBufferFreeAndReset(&query);
+return result;
+}
 
 
 static virHypervisorDriver hypervHypervisorDriver = {
@@ -1408,6 +1514,7 @@ static virHypervisorDriver hypervHypervisorDriver = {
 .domainManagedSave = hypervDomainManagedSave, /* 0.9.5 */
 .domainHasManagedSaveImage = hypervDomainHasManagedSaveImage, /* 0.9.5 */
 .domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */
+.domainSendKey = hypervDomainSendKey, /* TODO: version */
 .connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */
 };
 
diff --git a/src/h

[libvirt] [PATCH v4 5/5] hyperv: Add support for virDomainSetMemory

2017-05-19 Thread Sri Ramanujam
Introduces support for virDomainSetMemory. This also serves an an
example for how to use the new method invocation API with a more
complicated method, this time including an EPR and embedded param.
---
 src/hyperv/hyperv_driver.c| 94 +++
 src/hyperv/hyperv_wmi.c   | 51 +++
 src/hyperv/hyperv_wmi.h   | 11 
 src/hyperv/hyperv_wmi_generator.input | 30 +++
 4 files changed, 186 insertions(+)

diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index a01515a..455e1cd 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -1481,6 +1481,98 @@ hypervDomainSendKey(virDomainPtr domain, unsigned int 
codeset,
 }
 
 
+static int
+hypervDomainSetMemoryFlags(virDomainPtr domain, unsigned long memory,
+unsigned int flags)
+{
+int result = -1;
+char uuid_string[VIR_UUID_STRING_BUFLEN];
+hypervPrivate *priv = domain->conn->privateData;
+char *memory_str = NULL;
+hypervInvokeParamsListPtr params = NULL;
+unsigned long memory_mb = memory / 1024;
+Msvm_VirtualSystemSettingData *vssd = NULL;
+Msvm_MemorySettingData *memsd = NULL;
+virBuffer eprQuery = VIR_BUFFER_INITIALIZER;
+virHashTablePtr memResource = NULL;
+
+virCheckFlags(0, -1);
+
+/* memory has to be a multiple of 2; round up if necessary */
+if (memory_mb % 2) memory_mb++;
+
+if (virAsprintf(&memory_str, "%lu", memory_mb) < 0)
+goto cleanup;
+
+virUUIDFormat(domain->uuid, uuid_string);
+
+if (hypervGetMsvmVirtualSystemSettingDataFromUUID(priv, uuid_string, 
&vssd) < 0)
+goto cleanup;
+
+if (hypervGetMsvmMemorySettingDataFromVSSD(priv, 
vssd->data.common->InstanceID,
+&memsd) < 0)
+goto cleanup;
+
+if (priv->wmiVersion == HYPERV_WMI_VERSION_V1) {
+params = hypervCreateInvokeParamsList(priv, 
"ModifyVirtualSystemResources",
+MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_SELECTOR,
+Msvm_VirtualSystemManagementService_WmiInfo);
+
+virBufferAddLit(&eprQuery, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+virBufferAsprintf(&eprQuery, "where Name = \"%s\"", uuid_string);
+
+if (hypervAddEprParam(params, "ComputerSystem", priv, &eprQuery,
+Msvm_ComputerSystem_WmiInfo) < 0)
+goto cleanup;
+} else if (priv->wmiVersion == HYPERV_WMI_VERSION_V2) {
+params = hypervCreateInvokeParamsList(priv, "ModifyResourceSettings",
+MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_SELECTOR,
+Msvm_VirtualSystemManagementService_WmiInfo);
+}
+
+memResource = hypervCreateEmbeddedParam(priv, 
Msvm_MemorySettingData_WmiInfo);
+if (memResource == NULL)
+goto cleanup;
+
+if (hypervSetEmbeddedProperty(memResource, "VirtualQuantity", memory_str) 
< 0)
+goto cleanup;
+
+if (hypervSetEmbeddedProperty(memResource, "InstanceID",
+memsd->data.common->InstanceID) < 0)
+goto cleanup;
+
+if (priv->wmiVersion == HYPERV_WMI_VERSION_V1) {
+if (hypervAddEmbeddedParam(params, priv, "ResourceSettingData",
+memResource, Msvm_MemorySettingData_WmiInfo) < 0)
+goto cleanup;
+
+} else if (priv->wmiVersion == HYPERV_WMI_VERSION_V2) {
+if (hypervAddEmbeddedParam(params, priv, "ResourceSettings",
+memResource, Msvm_MemorySettingData_WmiInfo) < 0)
+goto cleanup;
+}
+
+if (hypervInvokeMethod(priv, params, NULL) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not set 
memory"));
+goto cleanup;
+}
+
+result = 0;
+ cleanup:
+VIR_FREE(memory_str);
+hypervFreeObject(priv, (hypervObject *) vssd);
+hypervFreeObject(priv, (hypervObject *) memsd);
+return result;
+}
+
+
+static int
+hypervDomainSetMemory(virDomainPtr domain, unsigned long memory)
+{
+return hypervDomainSetMemoryFlags(domain, memory, 0);
+}
+
+
 static virHypervisorDriver hypervHypervisorDriver = {
 .name = "Hyper-V",
 .connectOpen = hypervConnectOpen, /* 0.9.5 */
@@ -1515,6 +1607,8 @@ static virHypervisorDriver hypervHypervisorDriver = {
 .domainHasManagedSaveImage = hypervDomainHasManagedSaveImage, /* 0.9.5 */
 .domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */
 .domainSendKey = hypervDomainSendKey, /* TODO: version */
+.domainSetMemory = hypervDomainSetMemory, /* TODO: version */
+.domainSetMemoryFlags = hypervDomainSetMemoryFlags, /* TODO: version */
 .connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */
 };
 
diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index 2165838..f50a58c 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -1619,3 +1619,54 @@ hypervMsvmComputerSystemFromDomain(virDomainPtr domain,
 
 return 0;
 }
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Msvm_VirtualS

[libvirt] [PATCH v4 1/5] hyperv: Functions to work with invocation parameters.

2017-05-19 Thread Sri Ramanujam
This commit introduces functionality for creating and working with
invoke parameters. This commit does not include any code for serializing
and actually performing the method invocations; it merely defines the
functions and API for using invocation parameters in driver code.

HYPERV_DEFAULT_PARAM_COUNT was chosen because almost no method
invocations have more than 4 parameters.

Functions added:
* hypervInitInvokeParamsList
* hypervFreeInvokeParams
* hypervAddSimpleParam
* hypervAddEprParam
* hypervCreateEmbeddedParam
* hypervSetEmbeddedProperty
* hypervAddEmbeddedParam
---
 src/hyperv/hyperv_wmi.c | 252 
 src/hyperv/hyperv_wmi.h |  78 ++-
 2 files changed, 329 insertions(+), 1 deletion(-)

diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index a3c7dc0..217a3b2 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -2,6 +2,7 @@
  * hyperv_wmi.c: general WMI over WSMAN related functions and structures for
  *   managing Microsoft Hyper-V hosts
  *
+ * Copyright (C) 2017 Datto Inc
  * Copyright (C) 2014 Red Hat, Inc.
  * Copyright (C) 2011 Matthias Bolte 
  * Copyright (C) 2009 Michael Sievers 
@@ -142,6 +143,257 @@ hypervVerifyResponse(WsManClient *client, WsXmlDocH 
response,
 }
 
 
+/*
+ * Methods to work with method invocation parameters
+ */
+
+/*
+ * hypervCreateInvokeParamsList:
+ * @priv: hypervPrivate object associated with the connection.
+ * @method: The name of the method you are calling
+ * @selector: The selector for the object you are invoking the method on
+ * @obj: The WmiInfo of the object class you are invoking the method on.
+ *
+ * Create a new InvokeParamsList object for the method call.
+ *
+ * Returns a pointer to the newly instantiated object on success, which should
+ * be freed by hypervInvokeMethod. Otherwise returns NULL.
+ */
+hypervInvokeParamsListPtr
+hypervCreateInvokeParamsList(hypervPrivate *priv, const char *method,
+const char *selector, hypervWmiClassInfoListPtr obj)
+{
+hypervInvokeParamsListPtr params = NULL;
+hypervWmiClassInfoPtr info = NULL;
+
+if (hypervGetWmiClassInfo(priv, obj, &info) < 0)
+goto cleanup;
+
+if (VIR_ALLOC(params) < 0)
+goto cleanup;
+
+if (VIR_ALLOC_N(params->params,
+HYPERV_DEFAULT_PARAM_COUNT) < 0) {
+VIR_FREE(params);
+goto cleanup;
+}
+
+params->method = method;
+params->ns = info->rootUri;
+params->resourceUri = info->resourceUri;
+params->selector = selector;
+params->nbParams = 0;
+params->nbAvailParams = HYPERV_DEFAULT_PARAM_COUNT;
+
+ cleanup:
+return params;
+}
+
+/*
+ * hypervFreeInvokeParams:
+ * @params: Params object to be freed
+ *
+ */
+void
+hypervFreeInvokeParams(hypervInvokeParamsListPtr params)
+{
+hypervParamPtr p = NULL;
+size_t i = 0;
+
+if (params == NULL)
+return;
+
+for (i = 0; i < params->nbParams; i++) {
+p = &(params->params[i]);
+
+switch (p->type) {
+case HYPERV_SIMPLE_PARAM:
+break;
+case HYPERV_EPR_PARAM:
+virBufferFreeAndReset(p->epr.query);
+break;
+case HYPERV_EMBEDDED_PARAM:
+virHashFree(p->embedded.table);
+break;
+default:
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Invalid parameter type passed to free"));
+}
+}
+
+VIR_DISPOSE_N(params->params, params->nbAvailParams);
+VIR_FREE(params);
+}
+
+static inline int
+hypervCheckParams(hypervInvokeParamsListPtr params)
+{
+if (params->nbParams + 1 > params->nbAvailParams) {
+if (VIR_EXPAND_N(params->params, params->nbAvailParams, 5) < 0)
+return -1;
+}
+
+return 0;
+}
+
+/*
+ * hypervAddSimpleParam:
+ * @params: Params object to add to
+ * @name: Name of the parameter
+ * @value: Value of the parameter
+ *
+ * Add a param of type HYPERV_SIMPLE_PARAM, which is essentially a serialized
+ * key/value pair.
+ *
+ * Returns -1 on failure, 0 on success.
+ */
+int
+hypervAddSimpleParam(hypervInvokeParamsListPtr params, const char *name,
+const char *value)
+{
+int result = -1;
+hypervParamPtr p = NULL;
+
+if (hypervCheckParams(params) < 0)
+goto cleanup;
+
+p = ¶ms->params[params->nbParams];
+p->type = HYPERV_SIMPLE_PARAM;
+
+p->simple.name = name;
+p->simple.value = value;
+
+params->nbParams++;
+
+result = 0;
+
+ cleanup:
+return result;
+}
+
+/*
+ * hypervAddEprParam:
+ * @params: Params object to add to
+ * @name: Parameter name
+ * @priv: hypervPrivate object associated with the connection
+ * @query: WQL filter
+ * @eprInfo: WmiInfo of the object being filtered
+ *
+ * Adds an EPR param to the params list. Returns -1 on failure, 0 on success.
+ */
+int
+hypervAddEprParam(hypervInvokeParamsListPtr params, const char *name,
+hypervPrivate 

[libvirt] [PATCH v4 3/5] hyperv: add hypervInvokeMethod

2017-05-19 Thread Sri Ramanujam
This commit adds support for invoking methods on remote objects
via hypervInvokeMethod.
---
 src/hyperv/hyperv_wmi.c | 584 
 src/hyperv/hyperv_wmi.h |   3 +
 src/hyperv/openwsman.h  |   4 +
 3 files changed, 591 insertions(+)

diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index 217a3b2..b847d17 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -24,6 +24,7 @@
  */
 
 #include 
+#include 
 
 #include "internal.h"
 #include "virerror.h"
@@ -34,11 +35,16 @@
 #include "hyperv_private.h"
 #include "hyperv_wmi.h"
 #include "virstring.h"
+#include "openwsman.h"
+#include "virlog.h"
 
 #define WS_SERIALIZER_FREE_MEM_WORKS 0
 
 #define VIR_FROM_THIS VIR_FROM_HYPERV
 
+#define HYPERV_JOB_TIMEOUT_MS 5000
+
+VIR_LOG_INIT("hyperv.hyperv_wmi");
 
 static int
 hypervGetWmiClassInfo(hypervPrivate *priv, hypervWmiClassInfoListPtr list,
@@ -394,6 +400,584 @@ hypervAddEmbeddedParam(hypervInvokeParamsListPtr params, 
hypervPrivate *priv,
 }
 
 
+/*
+ * Serializing parameters to XML and invoking methods
+ */
+
+static int
+hypervGetCimTypeInfo(hypervCimTypePtr typemap, const char *name,
+hypervCimTypePtr *property)
+{
+size_t i = 0;
+while (typemap[i].name[0] != '\0') {
+if (STREQ(typemap[i].name, name)) {
+*property = &typemap[i];
+return 0;
+}
+i++;
+}
+
+return -1;
+}
+
+
+static int
+hypervCreateInvokeXmlDoc(hypervInvokeParamsListPtr params, WsXmlDocH *docRoot)
+{
+int result = -1;
+char *method = NULL;
+WsXmlNodeH xmlNodeMethod = NULL;
+
+if (virAsprintf(&method, "%s_INPUT", params->method) < 0)
+goto cleanup;
+
+*docRoot = ws_xml_create_doc(NULL, method);
+if (*docRoot == NULL) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not instantiate XML document"));
+goto cleanup;
+}
+
+xmlNodeMethod = xml_parser_get_root(*docRoot);
+if (xmlNodeMethod == NULL) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not get root node of XML document"));
+goto cleanup;
+}
+
+/* add resource URI as namespace */
+ws_xml_set_ns(xmlNodeMethod, params->resourceUri, "p");
+
+result = 0;
+goto cleanup;
+
+ cleanup:
+if (result < 0 && *docRoot != NULL) {
+ws_xml_destroy_doc(*docRoot);
+*docRoot = NULL;
+}
+VIR_FREE(method);
+return result;
+}
+
+static int
+hypervSerializeSimpleParam(hypervParamPtr p, const char *resourceUri,
+WsXmlNodeH *methodNode)
+{
+WsXmlNodeH xmlNodeParam = NULL;
+
+xmlNodeParam = ws_xml_add_child(*methodNode, resourceUri,
+p->simple.name, p->simple.value);
+if (xmlNodeParam == NULL) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not create simple param"));
+return -1;
+}
+
+return 0;
+}
+
+static int
+hypervSerializeEprParam(hypervParamPtr p, hypervPrivate *priv,
+const char *resourceUri, WsXmlDocH doc, WsXmlNodeH *methodNode)
+{
+int result = -1;
+WsXmlNodeH xmlNodeParam = NULL,
+   xmlNodeTemp = NULL,
+   xmlNodeAddr = NULL,
+   xmlNodeRef = NULL;
+xmlNodePtr xmlNodeAddrPtr = NULL,
+   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;
+
+/* init and set up options */
+options = wsmc_options_init();
+if (!options) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not init 
options"));
+goto cleanup;
+}
+wsmc_set_action_option(options, FLAG_ENUMERATION_ENUM_EPR);
+
+/* Get query and create filter based on it */
+query_string = virBufferContentAndReset(p->epr.query);
+filter = filter_create_simple(WSM_WQL_FILTER_DIALECT, query_string);
+if (!filter) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create WQL 
filter"));
+goto cleanup;
+}
+
+/* enumerate based on the filter from this query */
+xmlDocResponse = wsmc_action_enumerate(priv->client, p->epr.info->rootUri,
+options, filter);
+if (hypervVerifyResponse(priv->client, xmlDocResponse, "enumeration") < 0)
+goto cleanup;
+
+/* Get context */
+enumContext = wsmc_get_enum_context(xmlDocResponse);
+ws_xml_destroy_doc(xmlDocResponse);
+
+/* Pull using filter and enum context */
+xmlDocResponse = wsmc_action_pull(priv->client, resourceUri, options,
+filter, enumContext);
+
+if (hypervVerifyResponse(priv->client, xmlDocResponse, "pull") < 0)
+goto cleanup;
+
+/* drill down and extract EPR node children */
+if (!(xmlNodeTemp = ws_xml_get_soap_body(xmlDocResponse))) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s"

[libvirt] [PATCH v4 2/5] hyperv: Generate object property type information.

2017-05-19 Thread Sri Ramanujam
Update the generator to generate basic property type information for
each CIM object representation. Right now, it generates arrays of
hypervCimType structs:

struct _hypervCimType {
const char *name;
const char *type;
bool isArray;
};
---
 src/hyperv/hyperv_wmi_classes.h| 19 +++
 src/hyperv/hyperv_wmi_generator.py | 15 ++-
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/src/hyperv/hyperv_wmi_classes.h b/src/hyperv/hyperv_wmi_classes.h
index f7d596f..ce4643e 100644
--- a/src/hyperv/hyperv_wmi_classes.h
+++ b/src/hyperv/hyperv_wmi_classes.h
@@ -1,6 +1,7 @@
 /*
  * hyperv_wmi_classes.h: WMI classes for managing Microsoft Hyper-V hosts
  *
+ * Copyright (C) 2017 Datto Inc
  * Copyright (C) 2011 Matthias Bolte 
  * Copyright (C) 2009 Michael Sievers 
  *
@@ -23,6 +24,7 @@
 #ifndef __HYPERV_WMI_CLASSES_H__
 # define __HYPERV_WMI_CLASSES_H__
 
+# include "internal.h"
 # include "openwsman.h"
 
 # include "hyperv_wmi_classes.generated.typedef"
@@ -96,6 +98,21 @@ enum _Msvm_ConcreteJob_JobState {
 };
 
 
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * WMI
+ */
+
+typedef struct _hypervCimType hypervCimType;
+typedef hypervCimType *hypervCimTypePtr;
+struct _hypervCimType {
+/* Parameter name */
+const char *name;
+/* Parameter type */
+const char *type;
+/* whether parameter is an array type */
+bool isArray;
+};
+
 typedef struct _hypervWmiClassInfo hypervWmiClassInfo;
 typedef hypervWmiClassInfo *hypervWmiClassInfoPtr;
 struct _hypervWmiClassInfo {
@@ -109,6 +126,8 @@ struct _hypervWmiClassInfo {
 const char *resourceUri;
 /* The wsman serializer info - one of the *_TypeInfo structs */
 XmlSerializerInfo *serializerInfo;
+/* Property type information */
+hypervCimTypePtr propertyInfo;
 };
 
 
diff --git a/src/hyperv/hyperv_wmi_generator.py 
b/src/hyperv/hyperv_wmi_generator.py
index 9aee0b9..9c0acce 100755
--- a/src/hyperv/hyperv_wmi_generator.py
+++ b/src/hyperv/hyperv_wmi_generator.py
@@ -122,6 +122,14 @@ class WmiClass:
 
 source += "SER_END_ITEMS(%s_Data);\n\n" % cls.name
 
+# also generate typemap data while we're here
+source += "hypervCimType %s_Typemap[] = {\n" % cls.name
+
+for property in cls.properties:
+source += property.generate_typemap()
+source += '{ "", "", 0 },\n' # null terminated
+source += '};\n\n'
+
 
 source += self._define_WmiInfo_struct()
 source += "\n\n"
@@ -222,7 +230,8 @@ class WmiClass:
 source += ".version = NULL,\n"
 source += ".rootUri = %s,\n" % cls.uri_info.rootUri
 source += ".resourceUri = %s_RESOURCE_URI,\n" % 
cls.name.upper()
-source += ".serializerInfo = %s_Data_TypeInfo\n" % 
cls.name
+source += ".serializerInfo = %s_Data_TypeInfo,\n" % 
cls.name
+source += ".propertyInfo = %s_Typemap\n" % cls.name
 source += "},\n"
 
 source += "}\n"
@@ -374,6 +383,10 @@ class Property:
% (Property.typemap[self.type], class_name.upper(), 
self.name)
 
 
+def generate_typemap(self):
+return '{ "%s", "%s", %s },\n' % (self.name, self.type.lower(), 
str(self.is_array).lower())
+
+
 
 def open_and_print(filename):
 if filename.startswith("./"):
-- 
2.9.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v4 0/5] Hyperv-method invocation

2017-05-19 Thread Sri Ramanujam
Changes from v3:

* Feedback from code review
* Added 5 minute timeout to hypervInvokeMethod

Sri Ramanujam (5):
  hyperv: Functions to work with invocation parameters.
  hyperv: Generate object property type information.
  hyperv: add hypervInvokeMethod
  hyperv: support virDomainSendKey
  hyperv: Add support for virDomainSetMemory

 src/hyperv/hyperv_driver.c| 201 
 src/hyperv/hyperv_wmi.c   | 894 ++
 src/hyperv/hyperv_wmi.h   |  93 +++-
 src/hyperv/hyperv_wmi_classes.h   |  19 +
 src/hyperv/hyperv_wmi_generator.input | 116 +
 src/hyperv/hyperv_wmi_generator.py|  15 +-
 src/hyperv/openwsman.h|   4 +
 7 files changed, 1340 insertions(+), 2 deletions(-)

-- 
2.9.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v3 1/5] hyperv: Functions to work with invocation parameters.

2017-05-04 Thread Sri Ramanujam
On Mon, May 1, 2017 at 6:25 PM, Matthias Bolte
 wrote:
>
> 2017-04-24 20:19 GMT+02:00 Sri Ramanujam :
> > This commit introduces functionality for creating and working with
> > invoke parameters. This commit does not include any code for serializing
> > and actually performing the method invocations; it merely defines the
> > functions and API for using invocation parameters in driver code.
> >
> > HYPERV_DEFAULT_PARAM_COUNT was chosen because almost no method
> > invocations have more than 4 parameters.
>
> > diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
> > index a3c7dc0..1960c4c 100644
> > --- a/src/hyperv/hyperv_wmi.c
> > +++ b/src/hyperv/hyperv_wmi.c
>
> > @@ -142,6 +143,269 @@ hypervVerifyResponse(WsManClient *client, WsXmlDocH 
> > response,
> >  }
> >
> >
> > +/*
> > + * Methods to work with method invocation parameters
> > + */
> > +
> > +/*
> > + * hypervInitInvokeParamsList:
> > + * @priv: hypervPrivate object associated with the connection.
> > + * @method: The name of the method you are calling
> > + * @selector: The selector for the object you are invoking the method on
> > + * @obj: The WmiInfo of the object class you are invoking the method on.
> > + *
> > + * Create a new InvokeParamsList object for the method call.
> > + *
> > + * Returns a pointer to the newly instantiated object on success, which 
> > should
> > + * be freed by hypervInvokeMethod. Otherwise returns NULL.
> > + */
> > +hypervInvokeParamsListPtr
> > +hypervInitInvokeParamsList(hypervPrivate *priv, const char *method,
> > +const char *selector, hypervWmiClassInfoListPtr obj)
>
> I'd rename this to hypervCreateInvokeParamsList to follow the common
> create/free naming pattern.
>
> > +{
> > +hypervInvokeParamsListPtr params = NULL;
> > +hypervWmiClassInfoPtr info = NULL;
> > +
> > +if (hypervGetWmiClassInfo(priv, obj, &info) < 0)
> > +goto cleanup;
> > +
> > +if (VIR_ALLOC(params) < 0)
> > +goto cleanup;
> > +
> > +if (VIR_ALLOC_N(params->params,
> > +HYPERV_DEFAULT_PARAM_COUNT) < 0) {
> > +VIR_FREE(params);
> > +goto cleanup;
> > +}
> > +
> > +params->method = method;
> > +params->ns = info->rootUri;
> > +params->resourceUri = info->resourceUri;
> > +params->selector = selector;
> > +params->nbParams = 0;
> > +params->nbAvailParams = HYPERV_DEFAULT_PARAM_COUNT;
> > +
> > + cleanup:
> > +return params;
> > +}
> > +
> > +/*
> > + * hypervFreeInvokeParams:
> > + * @params: Params object to be freed
> > + *
> > + */
> > +void
> > +hypervFreeInvokeParams(hypervInvokeParamsListPtr params)
> > +{
> > +hypervParamPtr p = NULL;
> > +int i = 0;
>
> Use size_t instead of int for i.
>
> > +
> > +if (params == NULL)
> > +return;
> > +
> > +for (i = 0; i < params->nbParams; i++) {
> > +p = &(params->params[i]);
> > +
> > +switch(p->type) {
> > +case HYPERV_SIMPLE_PARAM:
> > +VIR_FREE(p->simple.name);
> > +VIR_FREE(p->simple.value);
> > +break;
> > +case HYPERV_EPR_PARAM:
> > +virBufferFreeAndReset(p->epr.query);
> > +break;
> > +case HYPERV_EMBEDDED_PARAM:
> > +virHashFree(p->embedded.table);
> > +break;
> > +}
> > +}
> > +
> > +VIR_DISPOSE_N(params->params, params->nbAvailParams);
> > +VIR_FREE(params);
> > +}
>
> > +/*
> > + * hypervAddSimpleParam:
> > + * @params: Params object to add to
> > + * @name: Name of the parameter
> > + * @value: Value of the parameter
> > + *
> > + * Add a param of type HYPERV_SIMPLE_PARAM, which is essentially a 
> > serialized
> > + * key/value pair.
> > + *
> > + * Returns -1 on failure, 0 on success.
> > + */
> > +int
> > +hypervAddSimpleParam(hypervInvokeParamsListPtr params, const char *name,
> > +const char *value)
> > +{
> > +int result = -1;
> > +hypervParamPtr p = NULL;
> > +
> > +if (hypervCheckParams(params) < 0)
> > +goto cleanup;
> > +
> > +p = ¶ms->params[params->nbParams];
> > +p->type = H

[libvirt] [PATCH v3 3/5] hyperv: add hypervInvokeMethod

2017-04-24 Thread Sri Ramanujam
This commit adds support for invoking methods on remote objects
via hypervInvokeMethod.
---
 src/hyperv/hyperv_wmi.c | 569 
 src/hyperv/hyperv_wmi.h |   3 +
 src/hyperv/openwsman.h  |   4 +
 3 files changed, 576 insertions(+)

diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index 1960c4c..deea907 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -24,6 +24,7 @@
  */
 
 #include 
+#include 
 
 #include "internal.h"
 #include "virerror.h"
@@ -34,11 +35,14 @@
 #include "hyperv_private.h"
 #include "hyperv_wmi.h"
 #include "virstring.h"
+#include "openwsman.h"
+#include "virlog.h"
 
 #define WS_SERIALIZER_FREE_MEM_WORKS 0
 
 #define VIR_FROM_THIS VIR_FROM_HYPERV
 
+VIR_LOG_INIT("hyperv.hyperv_wmi");
 
 static int
 hypervGetWmiClassInfo(hypervPrivate *priv, hypervWmiClassInfoListPtr list,
@@ -406,6 +410,571 @@ hypervAddEmbeddedParam(hypervInvokeParamsListPtr params, 
hypervPrivate *priv,
 }
 
 
+/*
+ * Serializing parameters to XML and invoking methods
+ */
+
+static int
+hypervGetCimTypeInfo(hypervCimTypePtr typemap, const char *name,
+hypervCimTypePtr *property)
+{
+size_t i = 0;
+while (typemap[i].name[0] != '\0') {
+if (STREQ(typemap[i].name, name)) {
+*property = &typemap[i];
+return 0;
+}
+i++;
+}
+
+return -1;
+}
+
+
+static int
+hypervCreateInvokeXmlDoc(hypervInvokeParamsListPtr params, WsXmlDocH *docRoot)
+{
+int result = -1;
+char *method = NULL;
+WsXmlNodeH xmlNodeMethod = NULL;
+
+if (virAsprintf(&method, "%s_INPUT", params->method) < 0)
+goto error;
+
+*docRoot = ws_xml_create_doc(NULL, method);
+if (*docRoot == NULL) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not instantiate XML document"));
+goto error;
+}
+
+xmlNodeMethod = xml_parser_get_root(*docRoot);
+if (xmlNodeMethod == NULL) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not get root node of XML document"));
+goto error;
+}
+
+/* add resource URI as namespace */
+ws_xml_set_ns(xmlNodeMethod, params->resourceUri, "p");
+
+result = 0;
+goto cleanup;
+
+ error:
+if (*docRoot != NULL) {
+ws_xml_destroy_doc(*docRoot);
+*docRoot = NULL;
+}
+ cleanup:
+VIR_FREE(method);
+return result;
+}
+
+static int
+hypervSerializeSimpleParam(hypervParamPtr p, const char *resourceUri,
+WsXmlNodeH *methodNode)
+{
+int result = -1;
+WsXmlNodeH xmlNodeParam = NULL;
+
+xmlNodeParam = ws_xml_add_child(*methodNode, resourceUri,
+p->simple.name, p->simple.value);
+if (xmlNodeParam == NULL) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not create simple param"));
+goto cleanup;
+}
+
+result = 0;
+
+ cleanup:
+return result;
+}
+
+static int
+hypervSerializeEprParam(hypervParamPtr p, hypervPrivate *priv,
+const char *resourceUri, WsXmlDocH doc, WsXmlNodeH *methodNode)
+{
+int result = -1;
+WsXmlNodeH xmlNodeParam = NULL,
+   xmlNodeTemp = NULL,
+   xmlNodeAddr = NULL,
+   xmlNodeRef = NULL;
+xmlNodePtr xmlNodeAddrPtr = NULL,
+   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;
+
+/* init and set up options */
+options = wsmc_options_init();
+if (!options) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not init 
options"));
+goto cleanup;
+}
+wsmc_set_action_option(options, FLAG_ENUMERATION_ENUM_EPR);
+
+/* Get query and create filter based on it */
+query_string = virBufferContentAndReset(p->epr.query);
+filter = filter_create_simple(WSM_WQL_FILTER_DIALECT, query_string);
+if (!filter) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create WQL 
filter"));
+goto cleanup;
+}
+
+/* enumerate based on the filter from this query */
+xmlDocResponse = wsmc_action_enumerate(priv->client, p->epr.info->rootUri,
+options, filter);
+if (hypervVerifyResponse(priv->client, xmlDocResponse, "enumeration") < 0)
+goto cleanup;
+
+/* Get context */
+enumContext = wsmc_get_enum_context(xmlDocResponse);
+ws_xml_destroy_doc(xmlDocResponse);
+
+/* Pull using filter and enum context */
+xmlDocResponse = wsmc_action_pull(priv->client, resourceUri, options,
+filter, enumContext);
+
+if (hypervVerifyResponse(priv->client, xmlDocResponse, "pull") < 0)
+goto cleanup;
+
+/* drill down and extract EPR node children */
+if (!(xmlNodeTemp = ws_xml_get_soap_body(xmlDocResponse))) {
+virReportError(VIR_ERR_INTERNAL_

[libvirt] [PATCH v3 5/5] hyperv: Add support for virDomainSetMemory

2017-04-24 Thread Sri Ramanujam
Introduces support for virDomainSetMemory. This also serves an an
example for how to use the new method invocation API with a more
complicated method, this time including an EPR and embedded param.
---
 src/hyperv/hyperv_driver.c| 96 +++
 src/hyperv/hyperv_wmi.c   | 51 +++
 src/hyperv/hyperv_wmi.h   | 11 
 src/hyperv/hyperv_wmi_generator.input | 30 +++
 4 files changed, 188 insertions(+)

diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index 9562d5a..104e13f 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -1459,6 +1459,100 @@ hypervDomainSendKey(virDomainPtr domain, unsigned int 
codeset,
 }
 
 
+static int
+hypervDomainSetMemoryFlags(virDomainPtr domain, unsigned long memory,
+unsigned int flags)
+{
+int result = -1;
+char uuid_string[VIR_UUID_STRING_BUFLEN];
+hypervPrivate *priv = domain->conn->privateData;
+char *memory_str = NULL;
+hypervInvokeParamsListPtr params = NULL;
+unsigned long memory_mb = memory / 1024;
+Msvm_VirtualSystemSettingData *vssd = NULL;
+Msvm_MemorySettingData *memsd = NULL;
+virBuffer eprQuery = VIR_BUFFER_INITIALIZER;
+virHashTablePtr memResource = NULL;
+
+virCheckFlags(0, -1);
+
+/* memory has to be a multiple of 2; round up if necessary */
+if (memory_mb % 2) memory_mb++;
+
+if (virAsprintf(&memory_str, "%lu", memory_mb) < 0)
+goto cleanup;
+
+virUUIDFormat(domain->uuid, uuid_string);
+
+if (hypervGetMsvmVirtualSystemSettingDataFromUUID(priv, uuid_string, 
&vssd) < 0)
+goto cleanup;
+
+if (hypervGetMsvmMemorySettingDataFromVSSD(priv, 
vssd->data.common->InstanceID,
+&memsd) < 0)
+goto cleanup;
+
+if (priv->wmiVersion == HYPERV_WMI_VERSION_V1) {
+params = hypervInitInvokeParamsList(priv, 
"ModifyVirtualSystemResources",
+MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_SELECTOR,
+Msvm_VirtualSystemManagementService_WmiInfo);
+
+virBufferAddLit(&eprQuery, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+virBufferAsprintf(&eprQuery, "where Name = \"%s\"", uuid_string);
+
+if (hypervAddEprParam(params, "ComputerSystem", priv, &eprQuery,
+Msvm_ComputerSystem_WmiInfo) < 0)
+goto cleanup;
+
+} else if (priv->wmiVersion == HYPERV_WMI_VERSION_V2) {
+params = hypervInitInvokeParamsList(priv, "ModifyResourceSettings",
+MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_SELECTOR,
+Msvm_VirtualSystemManagementService_WmiInfo);
+}
+
+memResource = hypervCreateEmbeddedParam(priv, 
Msvm_MemorySettingData_WmiInfo);
+if (memResource == NULL)
+goto cleanup;
+
+if (hypervSetEmbeddedProperty(memResource, "VirtualQuantity", memory_str) 
< 0)
+goto cleanup;
+
+if (hypervSetEmbeddedProperty(memResource, "InstanceID",
+memsd->data.common->InstanceID) < 0)
+goto cleanup;
+
+
+if (priv->wmiVersion == HYPERV_WMI_VERSION_V1) {
+if (hypervAddEmbeddedParam(params, priv, "ResourceSettingData",
+memResource, Msvm_MemorySettingData_WmiInfo) < 0)
+goto cleanup;
+
+} else if (priv->wmiVersion == HYPERV_WMI_VERSION_V2) {
+if (hypervAddEmbeddedParam(params, priv, "ResourceSettings",
+memResource, Msvm_MemorySettingData_WmiInfo) < 0)
+goto cleanup;
+}
+
+if (hypervInvokeMethod(priv, params, NULL) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not set 
memory"));
+goto cleanup;
+}
+
+result = 0;
+ cleanup:
+if (memory_str) VIR_FREE(memory_str);
+hypervFreeObject(priv, (hypervObject *) vssd);
+hypervFreeObject(priv, (hypervObject *) memsd);
+return result;
+}
+
+
+static int
+hypervDomainSetMemory(virDomainPtr domain, unsigned long memory)
+{
+return hypervDomainSetMemoryFlags(domain, memory, 0);
+}
+
+
 static virHypervisorDriver hypervHypervisorDriver = {
 .name = "Hyper-V",
 .connectOpen = hypervConnectOpen, /* 0.9.5 */
@@ -1493,6 +1587,8 @@ static virHypervisorDriver hypervHypervisorDriver = {
 .domainHasManagedSaveImage = hypervDomainHasManagedSaveImage, /* 0.9.5 */
 .domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */
 .domainSendKey = hypervDomainSendKey, /* TODO: version */
+.domainSetMemory = hypervDomainSetMemory, /* TODO: version */
+.domainSetMemoryFlags = hypervDomainSetMemoryFlags, /* TODO: version */
 .connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */
 };
 
diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index df248e0..756326d 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -1616,3 +1616,54 @@ hypervMsvmComputerSystemFromDomain(virDomainPtr domain,
 
 return 0;
 }
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

[libvirt] [PATCH v3 4/5] hyperv: support virDomainSendKey

2017-04-24 Thread Sri Ramanujam
This commit adds support for virDomainSendKey. It also serves as an
example of how to use the new method invocation APIs with a single
"simple" type parameter.
---
 src/hyperv/hyperv_driver.c| 85 ++
 src/hyperv/hyperv_wmi.c   |  7 +++
 src/hyperv/hyperv_wmi.h   |  3 +-
 src/hyperv/hyperv_wmi_generator.input | 86 +++
 4 files changed, 180 insertions(+), 1 deletion(-)

diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index 0ca5971..9562d5a 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -35,6 +35,7 @@
 #include "hyperv_wmi.h"
 #include "openwsman.h"
 #include "virstring.h"
+#include "virkeycode.h"
 
 #define VIR_FROM_THIS VIR_FROM_HYPERV
 
@@ -1373,6 +1374,89 @@ hypervConnectListAllDomains(virConnectPtr conn,
 #undef MATCH
 
 
+static int
+hypervDomainSendKey(virDomainPtr domain, unsigned int codeset,
+unsigned int holdtime ATTRIBUTE_UNUSED, unsigned int *keycodes,
+int nkeycodes, unsigned int flags)
+{
+int result = -1;
+size_t i = 0;
+int keycode = 0;
+int *translatedKeycodes = NULL;
+hypervPrivate *priv = domain->conn->privateData;
+char uuid_string[VIR_UUID_STRING_BUFLEN];
+char *selector = NULL;
+Msvm_ComputerSystem *computerSystem = NULL;
+Msvm_Keyboard *keyboard = NULL;
+virBuffer query = VIR_BUFFER_INITIALIZER;
+hypervInvokeParamsListPtr params = NULL;
+
+virCheckFlags(0, -1);
+
+virUUIDFormat(domain->uuid, uuid_string);
+
+if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
+goto cleanup;
+
+virBufferAsprintf(&query,
+"associators of "
+"{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+"Name=\"%s\"} "
+"where ResultClass = Msvm_Keyboard",
+uuid_string);
+
+
+if (hypervGetMsvmKeyboardList(priv, &query, &keyboard) < 0)
+goto cleanup;
+
+/* translate keycodes to xt and generate keyup scancodes. */
+translatedKeycodes = (int *) keycodes;
+for (i = 0; i < nkeycodes; i++) {
+if (codeset != VIR_KEYCODE_SET_WIN32) {
+keycode = virKeycodeValueTranslate(codeset, VIR_KEYCODE_SET_WIN32,
+translatedKeycodes[i]);
+
+if (keycode < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not translate keycode"));
+goto cleanup;
+}
+translatedKeycodes[i] = keycode;
+}
+}
+
+if (virAsprintf(&selector,
+"CreationClassName=Msvm_Keyboard&DeviceID=%s&"
+"SystemCreationClassName=Msvm_ComputerSystem&"
+"SystemName=%s", keyboard->data.common->DeviceID, uuid_string) 
< 0)
+goto cleanup;
+
+/* type the keys */
+for (i = 0; i < nkeycodes; i++) {
+char keycodeStr[sizeof(int) * 3 + 2];
+snprintf(keycodeStr, sizeof(keycodeStr), "%d", translatedKeycodes[i]);
+
+/* params obj takes ownership of selector */
+params = hypervInitInvokeParamsList(priv, "TypeKey", selector,
+Msvm_Keyboard_WmiInfo);
+if (hypervAddSimpleParam(params, "keyCode", keycodeStr) < 0)
+goto cleanup;
+
+if (hypervInvokeMethod(priv, params, NULL) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not press key %d"),
+   translatedKeycodes[i]);
+goto cleanup;
+}
+}
+
+result = 0;
+
+ cleanup:
+hypervFreeObject(priv, (hypervObject *) keyboard);
+hypervFreeObject(priv, (hypervObject *) computerSystem);
+virBufferFreeAndReset(&query);
+return result;
+}
 
 
 static virHypervisorDriver hypervHypervisorDriver = {
@@ -1408,6 +1492,7 @@ static virHypervisorDriver hypervHypervisorDriver = {
 .domainManagedSave = hypervDomainManagedSave, /* 0.9.5 */
 .domainHasManagedSaveImage = hypervDomainHasManagedSaveImage, /* 0.9.5 */
 .domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */
+.domainSendKey = hypervDomainSendKey, /* TODO: version */
 .connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */
 };
 
diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index deea907..df248e0 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -1323,6 +1323,13 @@ hypervGetMsvmMemorySettingDataList(hypervPrivate *priv, 
virBufferPtr query,
  (hypervObject **) list);
 }
 
+int hypervGetMsvmKeyboardList(hypervPrivate *priv, virBufferPtr query,
+  Msvm_Keyboard **list)
+{
+return hypervGetWmiClassList(priv, Msvm_Keyboard_WmiInfo, query,
+ (hypervObject **) list);
+}
+
 
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
diff --git a/src/hyperv/hyperv_wmi.h b/src/hyperv/hyperv_wmi.h
index 4196f51..740bdc

[libvirt] [PATCH v3 0/5] Hyper-V method invocation

2017-04-24 Thread Sri Ramanujam
Changes from v2:

* Correctly manage and free invocation parameters
* Fixed a couple of other memory leaks found while fixing the above issue
* Minor code changes from review

I also forgot to mention previously that we have test servers available for
reviewers as we introduce new functionality to the driver. Let me know if you
want access to them :)

Sri Ramanujam (5):
  hyperv: Functions to work with invocation parameters.
  hyperv: Generate object property type information.
  hyperv: add hypervInvokeMethod
  hyperv: support virDomainSendKey
  hyperv: Add support for virDomainSetMemory

 src/hyperv/hyperv_driver.c| 181 +++
 src/hyperv/hyperv_wmi.c   | 891 ++
 src/hyperv/hyperv_wmi.h   |  93 +++-
 src/hyperv/hyperv_wmi_classes.h   |  19 +
 src/hyperv/hyperv_wmi_generator.input | 116 +
 src/hyperv/hyperv_wmi_generator.py|  15 +-
 src/hyperv/openwsman.h|   4 +
 7 files changed, 1317 insertions(+), 2 deletions(-)

-- 
2.9.3

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 2/5] hyperv: Generate object property type information.

2017-04-24 Thread Sri Ramanujam
Update the generator to generate basic property type information for
each CIM object representation. Right now, it generates arrays of
hypervCimType structs:

struct _hypervCimType {
const char *name;
const char *type;
bool isArray;
};
---
 src/hyperv/hyperv_wmi_classes.h| 19 +++
 src/hyperv/hyperv_wmi_generator.py | 15 ++-
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/src/hyperv/hyperv_wmi_classes.h b/src/hyperv/hyperv_wmi_classes.h
index f7d596f..ce4643e 100644
--- a/src/hyperv/hyperv_wmi_classes.h
+++ b/src/hyperv/hyperv_wmi_classes.h
@@ -1,6 +1,7 @@
 /*
  * hyperv_wmi_classes.h: WMI classes for managing Microsoft Hyper-V hosts
  *
+ * Copyright (C) 2017 Datto Inc
  * Copyright (C) 2011 Matthias Bolte 
  * Copyright (C) 2009 Michael Sievers 
  *
@@ -23,6 +24,7 @@
 #ifndef __HYPERV_WMI_CLASSES_H__
 # define __HYPERV_WMI_CLASSES_H__
 
+# include "internal.h"
 # include "openwsman.h"
 
 # include "hyperv_wmi_classes.generated.typedef"
@@ -96,6 +98,21 @@ enum _Msvm_ConcreteJob_JobState {
 };
 
 
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * WMI
+ */
+
+typedef struct _hypervCimType hypervCimType;
+typedef hypervCimType *hypervCimTypePtr;
+struct _hypervCimType {
+/* Parameter name */
+const char *name;
+/* Parameter type */
+const char *type;
+/* whether parameter is an array type */
+bool isArray;
+};
+
 typedef struct _hypervWmiClassInfo hypervWmiClassInfo;
 typedef hypervWmiClassInfo *hypervWmiClassInfoPtr;
 struct _hypervWmiClassInfo {
@@ -109,6 +126,8 @@ struct _hypervWmiClassInfo {
 const char *resourceUri;
 /* The wsman serializer info - one of the *_TypeInfo structs */
 XmlSerializerInfo *serializerInfo;
+/* Property type information */
+hypervCimTypePtr propertyInfo;
 };
 
 
diff --git a/src/hyperv/hyperv_wmi_generator.py 
b/src/hyperv/hyperv_wmi_generator.py
index 9aee0b9..9c0acce 100755
--- a/src/hyperv/hyperv_wmi_generator.py
+++ b/src/hyperv/hyperv_wmi_generator.py
@@ -122,6 +122,14 @@ class WmiClass:
 
 source += "SER_END_ITEMS(%s_Data);\n\n" % cls.name
 
+# also generate typemap data while we're here
+source += "hypervCimType %s_Typemap[] = {\n" % cls.name
+
+for property in cls.properties:
+source += property.generate_typemap()
+source += '{ "", "", 0 },\n' # null terminated
+source += '};\n\n'
+
 
 source += self._define_WmiInfo_struct()
 source += "\n\n"
@@ -222,7 +230,8 @@ class WmiClass:
 source += ".version = NULL,\n"
 source += ".rootUri = %s,\n" % cls.uri_info.rootUri
 source += ".resourceUri = %s_RESOURCE_URI,\n" % 
cls.name.upper()
-source += ".serializerInfo = %s_Data_TypeInfo\n" % 
cls.name
+source += ".serializerInfo = %s_Data_TypeInfo,\n" % 
cls.name
+source += ".propertyInfo = %s_Typemap\n" % cls.name
 source += "},\n"
 
 source += "}\n"
@@ -374,6 +383,10 @@ class Property:
% (Property.typemap[self.type], class_name.upper(), 
self.name)
 
 
+def generate_typemap(self):
+return '{ "%s", "%s", %s },\n' % (self.name, self.type.lower(), 
str(self.is_array).lower())
+
+
 
 def open_and_print(filename):
 if filename.startswith("./"):
-- 
2.9.3

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 1/5] hyperv: Functions to work with invocation parameters.

2017-04-24 Thread Sri Ramanujam
This commit introduces functionality for creating and working with
invoke parameters. This commit does not include any code for serializing
and actually performing the method invocations; it merely defines the
functions and API for using invocation parameters in driver code.

HYPERV_DEFAULT_PARAM_COUNT was chosen because almost no method
invocations have more than 4 parameters.

Functions added:
* hypervInitInvokeParamsList
* hypervFreeInvokeParams
* hypervAddSimpleParam
* hypervAddEprParam
* hypervCreateEmbeddedParam
* hypervSetEmbeddedProperty
* hypervAddEmbeddedParam
---
 src/hyperv/hyperv_wmi.c | 264 
 src/hyperv/hyperv_wmi.h |  78 +-
 2 files changed, 341 insertions(+), 1 deletion(-)

diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index a3c7dc0..1960c4c 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -2,6 +2,7 @@
  * hyperv_wmi.c: general WMI over WSMAN related functions and structures for
  *   managing Microsoft Hyper-V hosts
  *
+ * Copyright (C) 2017 Datto Inc
  * Copyright (C) 2014 Red Hat, Inc.
  * Copyright (C) 2011 Matthias Bolte 
  * Copyright (C) 2009 Michael Sievers 
@@ -142,6 +143,269 @@ hypervVerifyResponse(WsManClient *client, WsXmlDocH 
response,
 }
 
 
+/*
+ * Methods to work with method invocation parameters
+ */
+
+/*
+ * hypervInitInvokeParamsList:
+ * @priv: hypervPrivate object associated with the connection.
+ * @method: The name of the method you are calling
+ * @selector: The selector for the object you are invoking the method on
+ * @obj: The WmiInfo of the object class you are invoking the method on.
+ *
+ * Create a new InvokeParamsList object for the method call.
+ *
+ * Returns a pointer to the newly instantiated object on success, which should
+ * be freed by hypervInvokeMethod. Otherwise returns NULL.
+ */
+hypervInvokeParamsListPtr
+hypervInitInvokeParamsList(hypervPrivate *priv, const char *method,
+const char *selector, hypervWmiClassInfoListPtr obj)
+{
+hypervInvokeParamsListPtr params = NULL;
+hypervWmiClassInfoPtr info = NULL;
+
+if (hypervGetWmiClassInfo(priv, obj, &info) < 0)
+goto cleanup;
+
+if (VIR_ALLOC(params) < 0)
+goto cleanup;
+
+if (VIR_ALLOC_N(params->params,
+HYPERV_DEFAULT_PARAM_COUNT) < 0) {
+VIR_FREE(params);
+goto cleanup;
+}
+
+params->method = method;
+params->ns = info->rootUri;
+params->resourceUri = info->resourceUri;
+params->selector = selector;
+params->nbParams = 0;
+params->nbAvailParams = HYPERV_DEFAULT_PARAM_COUNT;
+
+ cleanup:
+return params;
+}
+
+/*
+ * hypervFreeInvokeParams:
+ * @params: Params object to be freed
+ *
+ */
+void
+hypervFreeInvokeParams(hypervInvokeParamsListPtr params)
+{
+hypervParamPtr p = NULL;
+int i = 0;
+
+if (params == NULL)
+return;
+
+for (i = 0; i < params->nbParams; i++) {
+p = &(params->params[i]);
+
+switch(p->type) {
+case HYPERV_SIMPLE_PARAM:
+VIR_FREE(p->simple.name);
+VIR_FREE(p->simple.value);
+break;
+case HYPERV_EPR_PARAM:
+virBufferFreeAndReset(p->epr.query);
+break;
+case HYPERV_EMBEDDED_PARAM:
+virHashFree(p->embedded.table);
+break;
+}
+}
+
+VIR_DISPOSE_N(params->params, params->nbAvailParams);
+VIR_FREE(params);
+}
+
+static inline int
+hypervCheckParams(hypervInvokeParamsListPtr params)
+{
+if (params->nbParams + 1 > params->nbAvailParams) {
+if (VIR_EXPAND_N(params->params, params->nbAvailParams, 5) < 0)
+return -1;
+}
+
+return 0;
+}
+
+/*
+ * hypervAddSimpleParam:
+ * @params: Params object to add to
+ * @name: Name of the parameter
+ * @value: Value of the parameter
+ *
+ * Add a param of type HYPERV_SIMPLE_PARAM, which is essentially a serialized
+ * key/value pair.
+ *
+ * Returns -1 on failure, 0 on success.
+ */
+int
+hypervAddSimpleParam(hypervInvokeParamsListPtr params, const char *name,
+const char *value)
+{
+int result = -1;
+hypervParamPtr p = NULL;
+
+if (hypervCheckParams(params) < 0)
+goto cleanup;
+
+p = ¶ms->params[params->nbParams];
+p->type = HYPERV_SIMPLE_PARAM;
+
+if (VIR_STRDUP(p->simple.name, name) < 0)
+goto cleanup;
+
+if (VIR_STRDUP(p->simple.value, value) < 0) {
+VIR_FREE(p->simple.name);
+goto cleanup;
+}
+params->nbParams++;
+
+result = 0;
+
+ cleanup:
+return result;
+}
+
+/*
+ * hypervAddEprParam:
+ * @params: Params object to add to
+ * @name: Parameter name
+ * @priv: hypervPrivate object associated with the connection
+ * @query: WQL filter
+ * @eprInfo: WmiInfo of the object being filtered
+ *
+ * Adds an EPR param to the params list. Returns -1 on failure, 0 on success.
+ */
+int
+hypervAddEprParam(hypervInvokeParamsListP

[libvirt] [PATCH v2 5/5] hyperv: Add support for virDomainSetMemory

2017-04-19 Thread Sri Ramanujam
Introduces support for virDomainSetMemory. This also serves an an
example for how to use the new method invocation API with a more
complicated method, this time including an EPR and embedded param.
---
 src/hyperv/hyperv_driver.c| 97 +++
 src/hyperv/hyperv_wmi.c   | 60 ++
 src/hyperv/hyperv_wmi.h   | 11 
 src/hyperv/hyperv_wmi_generator.input | 30 +++
 4 files changed, 198 insertions(+)

diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index 9562d5a..e01f63b 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -1459,6 +1459,101 @@ hypervDomainSendKey(virDomainPtr domain, unsigned int 
codeset,
 }
 
 
+static int
+hypervDomainSetMemoryFlags(virDomainPtr domain, unsigned long memory,
+unsigned int flags)
+{
+int result = -1;
+char uuid_string[VIR_UUID_STRING_BUFLEN];
+hypervPrivate *priv = domain->conn->privateData;
+char *memory_str = NULL;
+hypervInvokeParamsListPtr params = NULL;
+unsigned long memory_mb = memory / 1024;
+Msvm_VirtualSystemSettingData *vssd = NULL;
+Msvm_MemorySettingData *memsd = NULL;
+virBuffer eprQuery = VIR_BUFFER_INITIALIZER;
+virHashTablePtr memResource = NULL;
+
+virCheckFlags(0, -1);
+
+/* memory has to be a multiple of 2; round up if necessary */
+if (memory_mb % 2) memory_mb++;
+
+if (virAsprintf(&memory_str, "%lu", memory_mb) < 0)
+goto cleanup;
+
+virUUIDFormat(domain->uuid, uuid_string);
+
+if (hypervGetMsvmVirtualSystemSettingDataFromUUID(priv, uuid_string, 
&vssd) < 0)
+goto cleanup;
+
+if (hypervGetMsvmMemorySettingDataFromVSSD(priv, 
vssd->data.common->InstanceID,
+&memsd) < 0)
+goto cleanup;
+
+if (priv->wmiVersion == HYPERV_WMI_VERSION_V1) {
+params = hypervInitInvokeParamsList(priv, 
"ModifyVirtualSystemResources",
+MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_SELECTOR,
+Msvm_VirtualSystemManagementService_WmiInfo);
+
+virBufferAddLit(&eprQuery, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+virBufferAsprintf(&eprQuery, "where Name = \"%s\"", uuid_string);
+
+if (hypervAddEprParam(params, "ComputerSystem", priv, &eprQuery,
+Msvm_ComputerSystem_WmiInfo) < 0)
+goto cleanup;
+
+} else if (priv->wmiVersion == HYPERV_WMI_VERSION_V2) {
+params = hypervInitInvokeParamsList(priv, "ModifyResourceSettings",
+MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_SELECTOR,
+Msvm_VirtualSystemManagementService_WmiInfo);
+}
+
+memResource = hypervCreateEmbeddedParam(priv, 
Msvm_MemorySettingData_WmiInfo);
+if (memResource == NULL)
+goto cleanup;
+
+if (hypervSetEmbeddedProperty(memResource, "VirtualQuantity", memory_str) 
< 0)
+goto cleanup;
+
+if (hypervSetEmbeddedProperty(memResource, "InstanceID",
+memsd->data.common->InstanceID) < 0)
+goto cleanup;
+
+
+if (priv->wmiVersion == HYPERV_WMI_VERSION_V1) {
+if (hypervAddEmbeddedParam(params, priv, "ResourceSettingData",
+memResource, Msvm_MemorySettingData_WmiInfo) < 0)
+goto cleanup;
+
+} else if (priv->wmiVersion == HYPERV_WMI_VERSION_V2) {
+if (hypervAddEmbeddedParam(params, priv, "ResourceSettings",
+memResource, Msvm_MemorySettingData_WmiInfo) < 0)
+goto cleanup;
+}
+
+if (hypervInvokeMethod(priv, params, NULL) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not set 
memory"));
+goto cleanup;
+}
+
+result = 0;
+ cleanup:
+VIR_FREE(memory_str);
+hypervFreeObject(priv, (hypervObject *) vssd);
+hypervFreeObject(priv, (hypervObject *) memsd);
+virBufferFreeAndReset(&eprQuery);
+return result;
+}
+
+
+static int
+hypervDomainSetMemory(virDomainPtr domain, unsigned long memory)
+{
+return hypervDomainSetMemoryFlags(domain, memory, 0);
+}
+
+
 static virHypervisorDriver hypervHypervisorDriver = {
 .name = "Hyper-V",
 .connectOpen = hypervConnectOpen, /* 0.9.5 */
@@ -1493,6 +1588,8 @@ static virHypervisorDriver hypervHypervisorDriver = {
 .domainHasManagedSaveImage = hypervDomainHasManagedSaveImage, /* 0.9.5 */
 .domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */
 .domainSendKey = hypervDomainSendKey, /* TODO: version */
+.domainSetMemory = hypervDomainSetMemory, /* TODO: version */
+.domainSetMemoryFlags = hypervDomainSetMemoryFlags, /* TODO: version */
 .connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */
 };
 
diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index 8025371..0c46566 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -1595,3 +1595,63 @@ hypervMsvmComputerSystemFromDomain(virDomainPtr domain,
 
 return 0;
 }
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * 

[libvirt] [PATCH v2 2/5] hyperv: Generate object property type information.

2017-04-19 Thread Sri Ramanujam
Update the generator to generate basic property type information for
each CIM object representation. Right now, it generates arrays of
hypervCimType structs:

struct _hypervCimType {
const char *name;
const char *type;
bool isArray;
};
---
 src/hyperv/hyperv_wmi_classes.h| 19 +++
 src/hyperv/hyperv_wmi_generator.py | 15 ++-
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/src/hyperv/hyperv_wmi_classes.h b/src/hyperv/hyperv_wmi_classes.h
index f7d596f..ce4643e 100644
--- a/src/hyperv/hyperv_wmi_classes.h
+++ b/src/hyperv/hyperv_wmi_classes.h
@@ -1,6 +1,7 @@
 /*
  * hyperv_wmi_classes.h: WMI classes for managing Microsoft Hyper-V hosts
  *
+ * Copyright (C) 2017 Datto Inc
  * Copyright (C) 2011 Matthias Bolte 
  * Copyright (C) 2009 Michael Sievers 
  *
@@ -23,6 +24,7 @@
 #ifndef __HYPERV_WMI_CLASSES_H__
 # define __HYPERV_WMI_CLASSES_H__
 
+# include "internal.h"
 # include "openwsman.h"
 
 # include "hyperv_wmi_classes.generated.typedef"
@@ -96,6 +98,21 @@ enum _Msvm_ConcreteJob_JobState {
 };
 
 
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * WMI
+ */
+
+typedef struct _hypervCimType hypervCimType;
+typedef hypervCimType *hypervCimTypePtr;
+struct _hypervCimType {
+/* Parameter name */
+const char *name;
+/* Parameter type */
+const char *type;
+/* whether parameter is an array type */
+bool isArray;
+};
+
 typedef struct _hypervWmiClassInfo hypervWmiClassInfo;
 typedef hypervWmiClassInfo *hypervWmiClassInfoPtr;
 struct _hypervWmiClassInfo {
@@ -109,6 +126,8 @@ struct _hypervWmiClassInfo {
 const char *resourceUri;
 /* The wsman serializer info - one of the *_TypeInfo structs */
 XmlSerializerInfo *serializerInfo;
+/* Property type information */
+hypervCimTypePtr propertyInfo;
 };
 
 
diff --git a/src/hyperv/hyperv_wmi_generator.py 
b/src/hyperv/hyperv_wmi_generator.py
index 9aee0b9..9c0acce 100755
--- a/src/hyperv/hyperv_wmi_generator.py
+++ b/src/hyperv/hyperv_wmi_generator.py
@@ -122,6 +122,14 @@ class WmiClass:
 
 source += "SER_END_ITEMS(%s_Data);\n\n" % cls.name
 
+# also generate typemap data while we're here
+source += "hypervCimType %s_Typemap[] = {\n" % cls.name
+
+for property in cls.properties:
+source += property.generate_typemap()
+source += '{ "", "", 0 },\n' # null terminated
+source += '};\n\n'
+
 
 source += self._define_WmiInfo_struct()
 source += "\n\n"
@@ -222,7 +230,8 @@ class WmiClass:
 source += ".version = NULL,\n"
 source += ".rootUri = %s,\n" % cls.uri_info.rootUri
 source += ".resourceUri = %s_RESOURCE_URI,\n" % 
cls.name.upper()
-source += ".serializerInfo = %s_Data_TypeInfo\n" % 
cls.name
+source += ".serializerInfo = %s_Data_TypeInfo,\n" % 
cls.name
+source += ".propertyInfo = %s_Typemap\n" % cls.name
 source += "},\n"
 
 source += "}\n"
@@ -374,6 +383,10 @@ class Property:
% (Property.typemap[self.type], class_name.upper(), 
self.name)
 
 
+def generate_typemap(self):
+return '{ "%s", "%s", %s },\n' % (self.name, self.type.lower(), 
str(self.is_array).lower())
+
+
 
 def open_and_print(filename):
 if filename.startswith("./"):
-- 
2.9.3

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v2 0/5] Hyper-V method invocation

2017-04-19 Thread Sri Ramanujam
Changes from v1:
* Removed unneeded util function

Sri Ramanujam (5):
  hyperv: Functions to work with invocation parameters.
  hyperv: Generate object property type information.
  hyperv: add hypervInvokeMethod
  hyperv: support virDomainSendKey
  hyperv: Add support for virDomainSetMemory

 src/hyperv/hyperv_driver.c| 182 +++
 src/hyperv/hyperv_wmi.c   | 879 ++
 src/hyperv/hyperv_wmi.h   |  93 +++-
 src/hyperv/hyperv_wmi_classes.h   |  19 +
 src/hyperv/hyperv_wmi_generator.input | 116 +
 src/hyperv/hyperv_wmi_generator.py|  15 +-
 src/hyperv/openwsman.h|   4 +
 7 files changed, 1306 insertions(+), 2 deletions(-)

-- 
2.9.3

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v2 4/5] hyperv: support virDomainSendKey

2017-04-19 Thread Sri Ramanujam
This commit adds support for virDomainSendKey. It also serves as an
example of how to use the new method invocation APIs with a single
"simple" type parameter.
---
 src/hyperv/hyperv_driver.c| 85 ++
 src/hyperv/hyperv_wmi.c   |  7 +++
 src/hyperv/hyperv_wmi.h   |  3 +-
 src/hyperv/hyperv_wmi_generator.input | 86 +++
 4 files changed, 180 insertions(+), 1 deletion(-)

diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index 0ca5971..9562d5a 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -35,6 +35,7 @@
 #include "hyperv_wmi.h"
 #include "openwsman.h"
 #include "virstring.h"
+#include "virkeycode.h"
 
 #define VIR_FROM_THIS VIR_FROM_HYPERV
 
@@ -1373,6 +1374,89 @@ hypervConnectListAllDomains(virConnectPtr conn,
 #undef MATCH
 
 
+static int
+hypervDomainSendKey(virDomainPtr domain, unsigned int codeset,
+unsigned int holdtime ATTRIBUTE_UNUSED, unsigned int *keycodes,
+int nkeycodes, unsigned int flags)
+{
+int result = -1;
+size_t i = 0;
+int keycode = 0;
+int *translatedKeycodes = NULL;
+hypervPrivate *priv = domain->conn->privateData;
+char uuid_string[VIR_UUID_STRING_BUFLEN];
+char *selector = NULL;
+Msvm_ComputerSystem *computerSystem = NULL;
+Msvm_Keyboard *keyboard = NULL;
+virBuffer query = VIR_BUFFER_INITIALIZER;
+hypervInvokeParamsListPtr params = NULL;
+
+virCheckFlags(0, -1);
+
+virUUIDFormat(domain->uuid, uuid_string);
+
+if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
+goto cleanup;
+
+virBufferAsprintf(&query,
+"associators of "
+"{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+"Name=\"%s\"} "
+"where ResultClass = Msvm_Keyboard",
+uuid_string);
+
+
+if (hypervGetMsvmKeyboardList(priv, &query, &keyboard) < 0)
+goto cleanup;
+
+/* translate keycodes to xt and generate keyup scancodes. */
+translatedKeycodes = (int *) keycodes;
+for (i = 0; i < nkeycodes; i++) {
+if (codeset != VIR_KEYCODE_SET_WIN32) {
+keycode = virKeycodeValueTranslate(codeset, VIR_KEYCODE_SET_WIN32,
+translatedKeycodes[i]);
+
+if (keycode < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not translate keycode"));
+goto cleanup;
+}
+translatedKeycodes[i] = keycode;
+}
+}
+
+if (virAsprintf(&selector,
+"CreationClassName=Msvm_Keyboard&DeviceID=%s&"
+"SystemCreationClassName=Msvm_ComputerSystem&"
+"SystemName=%s", keyboard->data.common->DeviceID, uuid_string) 
< 0)
+goto cleanup;
+
+/* type the keys */
+for (i = 0; i < nkeycodes; i++) {
+char keycodeStr[sizeof(int) * 3 + 2];
+snprintf(keycodeStr, sizeof(keycodeStr), "%d", translatedKeycodes[i]);
+
+/* params obj takes ownership of selector */
+params = hypervInitInvokeParamsList(priv, "TypeKey", selector,
+Msvm_Keyboard_WmiInfo);
+if (hypervAddSimpleParam(params, "keyCode", keycodeStr) < 0)
+goto cleanup;
+
+if (hypervInvokeMethod(priv, params, NULL) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not press key %d"),
+   translatedKeycodes[i]);
+goto cleanup;
+}
+}
+
+result = 0;
+
+ cleanup:
+hypervFreeObject(priv, (hypervObject *) keyboard);
+hypervFreeObject(priv, (hypervObject *) computerSystem);
+virBufferFreeAndReset(&query);
+return result;
+}
 
 
 static virHypervisorDriver hypervHypervisorDriver = {
@@ -1408,6 +1492,7 @@ static virHypervisorDriver hypervHypervisorDriver = {
 .domainManagedSave = hypervDomainManagedSave, /* 0.9.5 */
 .domainHasManagedSaveImage = hypervDomainHasManagedSaveImage, /* 0.9.5 */
 .domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */
+.domainSendKey = hypervDomainSendKey, /* TODO: version */
 .connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */
 };
 
diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index cbbe028..8025371 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -1302,6 +1302,13 @@ hypervGetMsvmMemorySettingDataList(hypervPrivate *priv, 
virBufferPtr query,
  (hypervObject **) list);
 }
 
+int hypervGetMsvmKeyboardList(hypervPrivate *priv, virBufferPtr query,
+  Msvm_Keyboard **list)
+{
+return hypervGetWmiClassList(priv, Msvm_Keyboard_WmiInfo, query,
+ (hypervObject **) list);
+}
+
 
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
diff --git a/src/hyperv/hyperv_wmi.h b/src/hyperv/hyperv_wmi.h
index ac86ae0..5ff80f

[libvirt] [PATCH v2 1/5] hyperv: Functions to work with invocation parameters.

2017-04-19 Thread Sri Ramanujam
This commit introduces functionality for creating and working with
invoke parameters. This commit does not include any code for serializing
and actually performing the method invocations; it merely defines the
functions and API for using invocation parameters in driver code.

HYPERV_DEFAULT_PARAM_COUNT was chosen because almost no method
invocations have more than 4 parameters.

Functions added:
* hypervInitInvokeParamsList
* hypervFreeInvokeParams
* hypervAddSimpleParam
* hypervAddEprParam
* hypervCreateEmbeddedParam
* hypervSetEmbeddedProperty
* hypervAddEmbeddedParam
---
 src/hyperv/hyperv_wmi.c | 246 
 src/hyperv/hyperv_wmi.h |  78 ++-
 2 files changed, 323 insertions(+), 1 deletion(-)

diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index a3c7dc0..c9a7666 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -2,6 +2,7 @@
  * hyperv_wmi.c: general WMI over WSMAN related functions and structures for
  *   managing Microsoft Hyper-V hosts
  *
+ * Copyright (C) 2017 Datto Inc
  * Copyright (C) 2014 Red Hat, Inc.
  * Copyright (C) 2011 Matthias Bolte 
  * Copyright (C) 2009 Michael Sievers 
@@ -142,6 +143,251 @@ hypervVerifyResponse(WsManClient *client, WsXmlDocH 
response,
 }
 
 
+/*
+ * Methods to work with method invocation parameters
+ */
+
+/*
+ * hypervInitInvokeParamsList:
+ * @priv: hypervPrivate object associated with the connection.
+ * @method: The name of the method you are calling
+ * @selector: The selector for the object you are invoking the method on
+ * @obj: The WmiInfo of the object class you are invoking the method on.
+ *
+ * Create a new InvokeParamsList object for the method call.
+ *
+ * Returns a pointer to the newly instantiated object on success, which should
+ * be freed by hypervInvokeMethod. Otherwise returns NULL.
+ */
+hypervInvokeParamsListPtr
+hypervInitInvokeParamsList(hypervPrivate *priv, const char *method,
+const char *selector, hypervWmiClassInfoListPtr obj)
+{
+hypervInvokeParamsListPtr params = NULL;
+hypervWmiClassInfoPtr info = NULL;
+
+if (hypervGetWmiClassInfo(priv, obj, &info) < 0)
+goto cleanup;
+
+if (VIR_ALLOC(params) < 0)
+goto cleanup;
+
+if (VIR_ALLOC_N(params->params,
+HYPERV_DEFAULT_PARAM_COUNT) < 0) {
+VIR_FREE(params);
+goto cleanup;
+}
+
+params->method = method;
+params->ns = info->rootUri;
+params->resourceUri = info->resourceUri;
+params->selector = selector;
+params->nbParams = 0;
+params->nbAvailParams = HYPERV_DEFAULT_PARAM_COUNT;
+
+ cleanup:
+return params;
+}
+
+/*
+ * hypervFreeInvokeParams:
+ * @params: Params object to be freed
+ *
+ */
+void
+hypervFreeInvokeParams(hypervInvokeParamsListPtr params)
+{
+if (params == NULL)
+return;
+
+VIR_DISPOSE_N(params->params, params->nbAvailParams);
+VIR_FREE(params);
+
+return;
+}
+
+static inline int
+hypervCheckParams(hypervInvokeParamsListPtr params)
+{
+int result = -1;
+
+if (params->nbParams + 1 > params->nbAvailParams) {
+if (VIR_EXPAND_N(params->params, params->nbAvailParams, 5) < 0)
+goto cleanup;
+}
+
+result = 0;
+ cleanup:
+return result;
+}
+
+/*
+ * hypervAddSimpleParam:
+ * @params: Params object to add to
+ * @name: Name of the parameter
+ * @value: Value of the parameter
+ *
+ * Add a param of type HYPERV_SIMPLE_PARAM, which is essentially a serialized
+ * key/value pair.
+ *
+ * Returns -1 on failure, 0 on success.
+ */
+int
+hypervAddSimpleParam(hypervInvokeParamsListPtr params, const char *name,
+const char *value)
+{
+int result = -1;
+hypervParamPtr p = NULL;
+
+if (hypervCheckParams(params) < 0)
+goto cleanup;
+
+p = ¶ms->params[params->nbParams];
+p->type = HYPERV_SIMPLE_PARAM;
+p->simple.name = name;
+p->simple.value = value;
+params->nbParams++;
+
+result = 0;
+ cleanup:
+return result;
+}
+
+/*
+ * hypervAddEprParam:
+ * @params: Params objec to add to
+ * @name: Parameter name
+ * @priv: hypervPrivate object associated with the connection
+ * @query: WQL filter
+ * @eprInfo: WmiInfo of the object being filtered
+ *
+ * Adds an EPR param to the params list. Returns -1 on failure, 0 on success.
+ */
+int
+hypervAddEprParam(hypervInvokeParamsListPtr params, const char *name,
+hypervPrivate *priv, virBufferPtr query,
+hypervWmiClassInfoListPtr eprInfo)
+{
+int result = -1;
+hypervParamPtr p = NULL;
+hypervWmiClassInfoPtr classInfo = NULL;
+
+if (hypervGetWmiClassInfo(priv, eprInfo, &classInfo) < 0)
+goto cleanup;
+
+if (hypervCheckParams(params) < 0)
+goto cleanup;
+
+p = ¶ms->params[params->nbParams];
+p->type = HYPERV_EPR_PARAM;
+p->epr.name = name;
+p->epr.query = query;
+p->epr.info = classInfo;
+params->nbParams++;
+
+result = 0;
+ cleanup:
+return result;
+}
+
+/

[libvirt] [PATCH v2 3/5] hyperv: add hypervInvokeMethod

2017-04-19 Thread Sri Ramanujam
This commit adds support for invoking methods on remote objects
via hypervInvokeMethod.
---
 src/hyperv/hyperv_wmi.c | 566 
 src/hyperv/hyperv_wmi.h |   3 +
 src/hyperv/openwsman.h  |   4 +
 3 files changed, 573 insertions(+)

diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index c9a7666..cbbe028 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -24,6 +24,7 @@
  */
 
 #include 
+#include 
 
 #include "internal.h"
 #include "virerror.h"
@@ -34,11 +35,14 @@
 #include "hyperv_private.h"
 #include "hyperv_wmi.h"
 #include "virstring.h"
+#include "openwsman.h"
+#include "virlog.h"
 
 #define WS_SERIALIZER_FREE_MEM_WORKS 0
 
 #define VIR_FROM_THIS VIR_FROM_HYPERV
 
+VIR_LOG_INIT("hyperv.hyperv_wmi");
 
 static int
 hypervGetWmiClassInfo(hypervPrivate *priv, hypervWmiClassInfoListPtr list,
@@ -388,6 +392,568 @@ hypervAddEmbeddedParam(hypervInvokeParamsListPtr params, 
hypervPrivate *priv,
 }
 
 
+/*
+ * Serializing parameters to XML and invoking methods
+ */
+
+static int
+hypervGetCimTypeInfo(hypervCimTypePtr typemap, const char *name,
+hypervCimTypePtr *property)
+{
+size_t i = 0;
+while (typemap[i].name[0] != '\0') {
+if (STREQ(typemap[i].name, name)) {
+*property = &typemap[i];
+return 0;
+}
+i++;
+}
+
+return -1;
+}
+
+
+static int
+hypervCreateInvokeXmlDoc(hypervInvokeParamsListPtr params, WsXmlDocH *docRoot)
+{
+int result = -1;
+char *method = NULL;
+WsXmlNodeH xmlNodeMethod = NULL;
+
+if (virAsprintf(&method, "%s_INPUT", params->method) < 0)
+goto err;
+
+*docRoot = ws_xml_create_doc(NULL, method);
+if (*docRoot == NULL) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not instantiate XML document"));
+goto err;
+}
+
+xmlNodeMethod = xml_parser_get_root(*docRoot);
+if (xmlNodeMethod == NULL) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not get root node of XML document"));
+goto err;
+}
+
+/* add resource URI as namespace */
+ws_xml_set_ns(xmlNodeMethod, params->resourceUri, "p");
+
+result = 0;
+goto cleanup;
+
+ err:
+if (*docRoot != NULL) {
+ws_xml_destroy_doc(*docRoot);
+*docRoot = NULL;
+}
+ cleanup:
+VIR_FREE(method);
+return result;
+}
+
+static int
+hypervSerializeSimpleParam(hypervParamPtr p, const char *resourceUri,
+WsXmlNodeH *methodNode)
+{
+int result = -1;
+WsXmlNodeH xmlNodeParam = NULL;
+
+xmlNodeParam = ws_xml_add_child(*methodNode, resourceUri,
+p->simple.name, p->simple.value);
+if (xmlNodeParam == NULL) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not create simple param"));
+goto cleanup;
+}
+
+result = 0;
+
+ cleanup:
+return result;
+}
+
+static int
+hypervSerializeEprParam(hypervParamPtr p, hypervPrivate *priv,
+const char *resourceUri, WsXmlDocH doc, WsXmlNodeH *methodNode)
+{
+int result = -1;
+WsXmlNodeH xmlNodeParam = NULL,
+   xmlNodeTemp = NULL,
+   xmlNodeAddr = NULL,
+   xmlNodeRef = NULL;
+xmlNodePtr xmlNodeAddrPtr = NULL,
+   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;
+
+/* init and set up options */
+options = wsmc_options_init();
+if (!options) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not init 
options"));
+goto cleanup;
+}
+wsmc_set_action_option(options, FLAG_ENUMERATION_ENUM_EPR);
+
+/* Get query and create filter based on it */
+query_string = virBufferContentAndReset(p->epr.query);
+filter = filter_create_simple(WSM_WQL_FILTER_DIALECT, query_string);
+if (!filter) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create WQL 
filter"));
+goto cleanup;
+}
+
+/* enumerate based on the filter from this query */
+xmlDocResponse = wsmc_action_enumerate(priv->client, p->epr.info->rootUri,
+options, filter);
+if (hypervVerifyResponse(priv->client, xmlDocResponse, "enumeration") < 0)
+goto cleanup;
+
+/* Get context */
+enumContext = wsmc_get_enum_context(xmlDocResponse);
+ws_xml_destroy_doc(xmlDocResponse);
+
+/* Pull using filter and enum context */
+xmlDocResponse = wsmc_action_pull(priv->client, resourceUri, options,
+filter, enumContext);
+
+if (hypervVerifyResponse(priv->client, xmlDocResponse, "pull") < 0)
+goto cleanup;
+
+/* drill down and extract EPR node children */
+if (!(xmlNodeTemp = ws_xml_get_soap_body(xmlDocResponse))) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "

Re: [libvirt] [PATCH 5/6] util: add virNumToStr

2017-04-18 Thread Sri Ramanujam
Ah, you're absolutely right, I completely forgot this function existed.

On Tue, Apr 18, 2017 at 5:18 PM Matthias Bolte <
matthias.bo...@googlemail.com> wrote:

> 2017-04-18 0:36 GMT+02:00 Sri Ramanujam :
> > Add virNumToStr(), which safely converts numbers into their string
> > representation.
> >
> > Functions added:
> > * virNumToStr_l
> > * virNumToStr_ul
> > ---
> >  src/util/virstring.c | 34 ++
> >  src/util/virstring.h |  8 
> >  2 files changed, 42 insertions(+)
> >
> > diff --git a/src/util/virstring.c b/src/util/virstring.c
> > index 69abc26..f0d9e19 100644
> > --- a/src/util/virstring.c
> > +++ b/src/util/virstring.c
> > @@ -536,6 +536,40 @@ virStrToDouble(char const *s,
> >  return 0;
> >  }
> >
> > +/**
> > + * Converts signed number to string representation. The caller is
> responsible
> > + * for freeing the result.
> > + */
> > +int
> > +virNumToStr_l(long num, char **dst)
> > +{
> > +int sz;
> > +
> > +sz = snprintf(NULL, 0, "%ld", num);
> > +if (sz > 0 && VIR_ALLOC_N(*dst, sz + 1) < 0)
> > +return -1;
> > +
> > +snprintf(*dst, sz + 1, "%ld", num);
> > +return 0;
> > +}
> > +
> > +/**
> > + * Converts unsigned number to string representation. The caller is
> responsible
> > + * for freeing the result.
> > + */
> > +int
> > +virNumToStr_ul(unsigned long num, char **dst)
> > +{
> > +int sz;
> > +
> > +sz = snprintf(NULL, 0, "%lu", num);
> > +if (sz > 0 && VIR_ALLOC_N(*dst, sz + 1) < 0)
> > +return -1;
> > +
> > +    snprintf(*dst, sz + 1, "%lu", num);
> > +return 0;
> > +}
> > +
>
> What's the gain of
>
> if (virNumToStr_ul(memory_mb, &memory_str) < 0)
>goto cleanup;
>
> over
>
> if (virAsprintf(&memory_str, "%lu", memory_mb) < 0)
>goto cleanup;
>
> ?
>
> I think those two new functions are not necessary at all.
>
> --
> Matthias Bolte
> http://photron.blogspot.com
>
-- 
*Sri Ramanujam*
Software Engineer
Datto, Inc.
www.datto.com

<http://datto.com/datto-signature/>

Join the conversation! [image: Facebook]
<http://www.facebook.com/dattoinc> [image:
Twitter] <https://twitter.com/dattobackup> [image: LinkedIn]
<http://www.linkedin.com/company/1477873?trk=tyah> [image: pinterest]
<http://pinterest.com/dattobackup/> [image: Blog RSS]
<http://blog.dattobackup.com/blog> [image: YouTube]
<http://www.youtube.com/user/DattoInc/featured> [image: Google Plus Page]
<https://plus.google.com/u/0/108292366419623632143/posts>
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 5/6] util: add virNumToStr

2017-04-17 Thread Sri Ramanujam
Add virNumToStr(), which safely converts numbers into their string
representation.

Functions added:
* virNumToStr_l
* virNumToStr_ul
---
 src/util/virstring.c | 34 ++
 src/util/virstring.h |  8 
 2 files changed, 42 insertions(+)

diff --git a/src/util/virstring.c b/src/util/virstring.c
index 69abc26..f0d9e19 100644
--- a/src/util/virstring.c
+++ b/src/util/virstring.c
@@ -536,6 +536,40 @@ virStrToDouble(char const *s,
 return 0;
 }
 
+/**
+ * Converts signed number to string representation. The caller is responsible
+ * for freeing the result.
+ */
+int
+virNumToStr_l(long num, char **dst)
+{
+int sz;
+
+sz = snprintf(NULL, 0, "%ld", num);
+if (sz > 0 && VIR_ALLOC_N(*dst, sz + 1) < 0)
+return -1;
+
+snprintf(*dst, sz + 1, "%ld", num);
+return 0;
+}
+
+/**
+ * Converts unsigned number to string representation. The caller is responsible
+ * for freeing the result.
+ */
+int
+virNumToStr_ul(unsigned long num, char **dst)
+{
+int sz;
+
+sz = snprintf(NULL, 0, "%lu", num);
+if (sz > 0 && VIR_ALLOC_N(*dst, sz + 1) < 0)
+return -1;
+
+snprintf(*dst, sz + 1, "%lu", num);
+return 0;
+}
+
 int
 virVasprintfInternal(bool report,
  int domcode,
diff --git a/src/util/virstring.h b/src/util/virstring.h
index 603650a..9918e07 100644
--- a/src/util/virstring.h
+++ b/src/util/virstring.h
@@ -109,6 +109,13 @@ int virStrToDouble(char const *s,
double *result)
 ATTRIBUTE_RETURN_CHECK;
 
+int virNumToStr_l(long num,
+  char **dst)
+ATTRIBUTE_RETURN_CHECK;
+int virnumToStr_ul(unsigned long num,
+char **dst)
+ATTRIBUTE_RETURN_CHECK;
+
 void virSkipSpaces(const char **str) ATTRIBUTE_NONNULL(1);
 void virSkipSpacesAndBackslash(const char **str) ATTRIBUTE_NONNULL(1);
 void virTrimSpaces(char *str, char **endp) ATTRIBUTE_NONNULL(1);
@@ -288,6 +295,7 @@ bool virStringBufferIsPrintable(const uint8_t *buf, size_t 
buflen);
 
 char *virStringEncodeBase64(const uint8_t *buf, size_t buflen);
 
+
 static inline void
 virStringTrimOptionalNewline(char *str)
 {
-- 
2.9.3

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 2/6] hyperv: Generate object property type information.

2017-04-17 Thread Sri Ramanujam
Update the generator to generate basic property type information for
each CIM object representation. Right now, it generates arrays of
hypervCimType structs:

struct _hypervCimType {
const char *name;
const char *type;
bool isArray;
};
---
 src/hyperv/hyperv_wmi_classes.h| 19 +++
 src/hyperv/hyperv_wmi_generator.py | 15 ++-
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/src/hyperv/hyperv_wmi_classes.h b/src/hyperv/hyperv_wmi_classes.h
index f7d596f..ce4643e 100644
--- a/src/hyperv/hyperv_wmi_classes.h
+++ b/src/hyperv/hyperv_wmi_classes.h
@@ -1,6 +1,7 @@
 /*
  * hyperv_wmi_classes.h: WMI classes for managing Microsoft Hyper-V hosts
  *
+ * Copyright (C) 2017 Datto Inc
  * Copyright (C) 2011 Matthias Bolte 
  * Copyright (C) 2009 Michael Sievers 
  *
@@ -23,6 +24,7 @@
 #ifndef __HYPERV_WMI_CLASSES_H__
 # define __HYPERV_WMI_CLASSES_H__
 
+# include "internal.h"
 # include "openwsman.h"
 
 # include "hyperv_wmi_classes.generated.typedef"
@@ -96,6 +98,21 @@ enum _Msvm_ConcreteJob_JobState {
 };
 
 
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * WMI
+ */
+
+typedef struct _hypervCimType hypervCimType;
+typedef hypervCimType *hypervCimTypePtr;
+struct _hypervCimType {
+/* Parameter name */
+const char *name;
+/* Parameter type */
+const char *type;
+/* whether parameter is an array type */
+bool isArray;
+};
+
 typedef struct _hypervWmiClassInfo hypervWmiClassInfo;
 typedef hypervWmiClassInfo *hypervWmiClassInfoPtr;
 struct _hypervWmiClassInfo {
@@ -109,6 +126,8 @@ struct _hypervWmiClassInfo {
 const char *resourceUri;
 /* The wsman serializer info - one of the *_TypeInfo structs */
 XmlSerializerInfo *serializerInfo;
+/* Property type information */
+hypervCimTypePtr propertyInfo;
 };
 
 
diff --git a/src/hyperv/hyperv_wmi_generator.py 
b/src/hyperv/hyperv_wmi_generator.py
index c15d97a..a51c151 100755
--- a/src/hyperv/hyperv_wmi_generator.py
+++ b/src/hyperv/hyperv_wmi_generator.py
@@ -122,6 +122,14 @@ class WmiClass:
 
 source += "SER_END_ITEMS(%s_Data);\n\n" % cls.name
 
+# also generate typemap data while we're here
+source += "hypervCimType %s_Typemap[] = {\n" % cls.name
+
+for property in cls.properties:
+source += property.generate_typemap()
+source += '{ "", "", 0 },\n' # null terminated
+source += '};\n\n'
+
 
 source += self._define_WmiInfo_struct()
 source += "\n\n"
@@ -222,7 +230,8 @@ class WmiClass:
 source += ".version = NULL,\n"
 source += ".rootUri = %s,\n" % cls.uri_info.rootUri
 source += ".resourceUri = %s_RESOURCE_URI,\n" % 
cls.name.upper()
-source += ".serializerInfo = %s_Data_TypeInfo\n" % 
cls.name
+source += ".serializerInfo = %s_Data_TypeInfo,\n" % 
cls.name
+source += ".propertyInfo = %s_Typemap\n" % cls.name
 source += "},\n"
 
 source += "}\n"
@@ -374,6 +383,10 @@ class Property:
% (Property.typemap[self.type], class_name.upper(), 
self.name)
 
 
+def generate_typemap(self):
+return '{ "%s", "%s", %s },\n' % (self.name, self.type.lower(), 
str(self.is_array).lower())
+
+
 
 def open_and_print(filename):
 if filename.startswith("./"):
-- 
2.9.3

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 6/6] hyperv: Add support for virDomainSetMemory

2017-04-17 Thread Sri Ramanujam
Introduces support for virDomainSetMemory. This also serves an an
example for how to use the new method invocation API with a more
complicated method, this time including an EPR and embedded param.
---
 src/hyperv/hyperv_driver.c| 97 +++
 src/hyperv/hyperv_wmi.c   | 60 ++
 src/hyperv/hyperv_wmi.h   | 11 
 src/hyperv/hyperv_wmi_generator.input | 30 +++
 4 files changed, 198 insertions(+)

diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index 1c8c436..254612b 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -1436,6 +1436,101 @@ hypervDomainSendKey(virDomainPtr domain, unsigned int 
codeset,
 }
 
 
+static int
+hypervDomainSetMemoryFlags(virDomainPtr domain, unsigned long memory,
+unsigned int flags)
+{
+int result = -1;
+char uuid_string[VIR_UUID_STRING_BUFLEN];
+hypervPrivate *priv = domain->conn->privateData;
+char *memory_str = NULL;
+hypervInvokeParamsListPtr params = NULL;
+unsigned long memory_mb = memory / 1024;
+Msvm_VirtualSystemSettingData *vssd = NULL;
+Msvm_MemorySettingData *memsd = NULL;
+virBuffer eprQuery = VIR_BUFFER_INITIALIZER;
+virHashTablePtr memResource = NULL;
+
+virCheckFlags(0, -1);
+
+/* memory has to be a multiple of 2; round up if necessary */
+if (memory_mb % 2) memory_mb++;
+
+if (virNumToStr_ul(memory_mb, &memory_str) < 0)
+goto cleanup;
+
+virUUIDFormat(domain->uuid, uuid_string);
+
+if (hypervGetMsvmVirtualSystemSettingDataFromUUID(priv, uuid_string, 
&vssd) < 0)
+goto cleanup;
+
+if (hypervGetMsvmMemorySettingDataFromVSSD(priv, 
vssd->data.common->InstanceID,
+&memsd) < 0)
+goto cleanup;
+
+if (priv->wmiVersion == HYPERV_WMI_VERSION_V1) {
+params = hypervInitInvokeParamsList(priv, 
"ModifyVirtualSystemResources",
+MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_SELECTOR,
+Msvm_VirtualSystemManagementService_WmiInfo);
+
+virBufferAddLit(&eprQuery, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+virBufferAsprintf(&eprQuery, "where Name = \"%s\"", uuid_string);
+
+if (hypervAddEprParam(params, "ComputerSystem", priv, &eprQuery,
+Msvm_ComputerSystem_WmiInfo) < 0)
+goto cleanup;
+
+} else if (priv->wmiVersion == HYPERV_WMI_VERSION_V2) {
+params = hypervInitInvokeParamsList(priv, "ModifyResourceSettings",
+MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_SELECTOR,
+Msvm_VirtualSystemManagementService_WmiInfo);
+}
+
+memResource = hypervCreateEmbeddedParam(priv, 
Msvm_MemorySettingData_WmiInfo);
+if (memResource == NULL)
+goto cleanup;
+
+if (hypervSetEmbeddedProperty(memResource, "VirtualQuantity", memory_str) 
< 0)
+goto cleanup;
+
+if (hypervSetEmbeddedProperty(memResource, "InstanceID",
+memsd->data.common->InstanceID) < 0)
+goto cleanup;
+
+
+if (priv->wmiVersion == HYPERV_WMI_VERSION_V1) {
+if (hypervAddEmbeddedParam(params, priv, "ResourceSettingData",
+memResource, Msvm_MemorySettingData_WmiInfo) < 0)
+goto cleanup;
+
+} else if (priv->wmiVersion == HYPERV_WMI_VERSION_V2) {
+if (hypervAddEmbeddedParam(params, priv, "ResourceSettings",
+memResource, Msvm_MemorySettingData_WmiInfo) < 0)
+goto cleanup;
+}
+
+if (hypervInvokeMethod(priv, params, NULL) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not set 
memory"));
+goto cleanup;
+}
+
+result = 0;
+ cleanup:
+VIR_FREE(memory_str);
+hypervFreeObject(priv, (hypervObject *) vssd);
+hypervFreeObject(priv, (hypervObject *) memsd);
+virBufferFreeAndReset(&eprQuery);
+return result;
+}
+
+
+static int
+hypervDomainSetMemory(virDomainPtr domain, unsigned long memory)
+{
+return hypervDomainSetMemoryFlags(domain, memory, 0);
+}
+
+
 static virHypervisorDriver hypervHypervisorDriver = {
 .name = "Hyper-V",
 .connectOpen = hypervConnectOpen, /* 0.9.5 */
@@ -1470,6 +1565,8 @@ static virHypervisorDriver hypervHypervisorDriver = {
 .domainHasManagedSaveImage = hypervDomainHasManagedSaveImage, /* 0.9.5 */
 .domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */
 .domainSendKey = hypervDomainSendKey, /* TODO: version */
+.domainSetMemory = hypervDomainSetMemory, /* TODO: version */
+.domainSetMemoryFlags = hypervDomainSetMemoryFlags, /* TODO: version */
 .connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */
 };
 
diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index 8025371..0c46566 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -1595,3 +1595,63 @@ hypervMsvmComputerSystemFromDomain(virDomainPtr domain,
 
 return 0;
 }
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * 

[libvirt] [PATCH 4/6] hyperv: support virDomainSendKey

2017-04-17 Thread Sri Ramanujam
This commit adds support for virDomainSendKey. It also serves as an
example of how to use the new method invocation APIs with a single
"simple" type parameter.
---
 src/hyperv/hyperv_driver.c| 85 ++
 src/hyperv/hyperv_wmi.c   |  7 +++
 src/hyperv/hyperv_wmi.h   |  3 +-
 src/hyperv/hyperv_wmi_generator.input | 86 +++
 4 files changed, 180 insertions(+), 1 deletion(-)

diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index 090ea24..1c8c436 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -35,6 +35,7 @@
 #include "hyperv_wmi.h"
 #include "openwsman.h"
 #include "virstring.h"
+#include "virkeycode.h"
 
 #define VIR_FROM_THIS VIR_FROM_HYPERV
 
@@ -1350,6 +1351,89 @@ hypervConnectListAllDomains(virConnectPtr conn,
 #undef MATCH
 
 
+static int
+hypervDomainSendKey(virDomainPtr domain, unsigned int codeset,
+unsigned int holdtime ATTRIBUTE_UNUSED, unsigned int *keycodes,
+int nkeycodes, unsigned int flags)
+{
+int result = -1;
+size_t i = 0;
+int keycode = 0;
+int *translatedKeycodes = NULL;
+hypervPrivate *priv = domain->conn->privateData;
+char uuid_string[VIR_UUID_STRING_BUFLEN];
+char *selector = NULL;
+Msvm_ComputerSystem *computerSystem = NULL;
+Msvm_Keyboard *keyboard = NULL;
+virBuffer query = VIR_BUFFER_INITIALIZER;
+hypervInvokeParamsListPtr params = NULL;
+
+virCheckFlags(0, -1);
+
+virUUIDFormat(domain->uuid, uuid_string);
+
+if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
+goto cleanup;
+
+virBufferAsprintf(&query,
+"associators of "
+"{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+"Name=\"%s\"} "
+"where ResultClass = Msvm_Keyboard",
+uuid_string);
+
+
+if (hypervGetMsvmKeyboardList(priv, &query, &keyboard) < 0)
+goto cleanup;
+
+/* translate keycodes to xt and generate keyup scancodes. */
+translatedKeycodes = (int *) keycodes;
+for (i = 0; i < nkeycodes; i++) {
+if (codeset != VIR_KEYCODE_SET_WIN32) {
+keycode = virKeycodeValueTranslate(codeset, VIR_KEYCODE_SET_WIN32,
+translatedKeycodes[i]);
+
+if (keycode < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not translate keycode"));
+goto cleanup;
+}
+translatedKeycodes[i] = keycode;
+}
+}
+
+if (virAsprintf(&selector,
+"CreationClassName=Msvm_Keyboard&DeviceID=%s&"
+"SystemCreationClassName=Msvm_ComputerSystem&"
+"SystemName=%s", keyboard->data.common->DeviceID, uuid_string) 
< 0)
+goto cleanup;
+
+/* type the keys */
+for (i = 0; i < nkeycodes; i++) {
+char keycodeStr[sizeof(int) * 3 + 2];
+snprintf(keycodeStr, sizeof(keycodeStr), "%d", translatedKeycodes[i]);
+
+/* params obj takes ownership of selector */
+params = hypervInitInvokeParamsList(priv, "TypeKey", selector,
+Msvm_Keyboard_WmiInfo);
+if (hypervAddSimpleParam(params, "keyCode", keycodeStr) < 0)
+goto cleanup;
+
+if (hypervInvokeMethod(priv, params, NULL) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not press key %d"),
+   translatedKeycodes[i]);
+goto cleanup;
+}
+}
+
+result = 0;
+
+ cleanup:
+hypervFreeObject(priv, (hypervObject *) keyboard);
+hypervFreeObject(priv, (hypervObject *) computerSystem);
+virBufferFreeAndReset(&query);
+return result;
+}
 
 
 static virHypervisorDriver hypervHypervisorDriver = {
@@ -1385,6 +1469,7 @@ static virHypervisorDriver hypervHypervisorDriver = {
 .domainManagedSave = hypervDomainManagedSave, /* 0.9.5 */
 .domainHasManagedSaveImage = hypervDomainHasManagedSaveImage, /* 0.9.5 */
 .domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */
+.domainSendKey = hypervDomainSendKey, /* TODO: version */
 .connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */
 };
 
diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index cbbe028..8025371 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -1302,6 +1302,13 @@ hypervGetMsvmMemorySettingDataList(hypervPrivate *priv, 
virBufferPtr query,
  (hypervObject **) list);
 }
 
+int hypervGetMsvmKeyboardList(hypervPrivate *priv, virBufferPtr query,
+  Msvm_Keyboard **list)
+{
+return hypervGetWmiClassList(priv, Msvm_Keyboard_WmiInfo, query,
+ (hypervObject **) list);
+}
+
 
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
diff --git a/src/hyperv/hyperv_wmi.h b/src/hyperv/hyperv_wmi.h
index ac86ae0..5ff80f

[libvirt] [PATCH 0/6] Hyper-V method invocation support

2017-04-17 Thread Sri Ramanujam
This patchset introduces functionality to support invoking Hyper-V methods over 
WMI.
It also includes implementations for virDomainSendKey and virDomainSetMemory as
examples of how to use the new functionality.

With this patchset, all the pieces should be in place to implement all parts
of the driver. I've got about 30 functions pending, to be submitted after this
patchset is ACKed.

Additionally, this patchset includes a new function under util that converts
numbers into their string representation. There is a variant for both signed
and unsigned numbers. Since everything must be represented as a string at the 
XML
layer, this function comes in handy throughout the Hyper-V driver and I thought
it would have some utility as a convenience method for the whole project.

Sri Ramanujam (6):
  hyperv: Functions to work with invocation parameters.
  hyperv: Generate object property type information.
  hyperv: add hypervInvokeMethod
  hyperv: support virDomainSendKey
  util: add virNumToStr
  hyperv: Add support for virDomainSetMemory

 src/hyperv/hyperv_driver.c| 182 +++
 src/hyperv/hyperv_wmi.c   | 879 ++
 src/hyperv/hyperv_wmi.h   |  93 +++-
 src/hyperv/hyperv_wmi_classes.h   |  19 +
 src/hyperv/hyperv_wmi_generator.input | 116 +
 src/hyperv/hyperv_wmi_generator.py|  15 +-
 src/hyperv/openwsman.h|   4 +
 src/util/virstring.c  |  34 ++
 src/util/virstring.h  |   8 +
 9 files changed, 1348 insertions(+), 2 deletions(-)

-- 
2.9.3

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 1/6] hyperv: Functions to work with invocation parameters.

2017-04-17 Thread Sri Ramanujam
This commit introduces functionality for creating and working with
invoke parameters. This commit does not include any code for serializing
and actually performing the method invocations; it merely defines the
functions and API for using invocation parameters in driver code.

HYPERV_DEFAULT_PARAM_COUNT was chosen because almost no method
invocations have more than 4 parameters.

Functions added:
* hypervInitInvokeParamsList
* hypervFreeInvokeParams
* hypervAddSimpleParam
* hypervAddEprParam
* hypervCreateEmbeddedParam
* hypervSetEmbeddedProperty
* hypervAddEmbeddedParam
---
 src/hyperv/hyperv_wmi.c | 246 
 src/hyperv/hyperv_wmi.h |  78 ++-
 2 files changed, 323 insertions(+), 1 deletion(-)

diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index a3c7dc0..c9a7666 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -2,6 +2,7 @@
  * hyperv_wmi.c: general WMI over WSMAN related functions and structures for
  *   managing Microsoft Hyper-V hosts
  *
+ * Copyright (C) 2017 Datto Inc
  * Copyright (C) 2014 Red Hat, Inc.
  * Copyright (C) 2011 Matthias Bolte 
  * Copyright (C) 2009 Michael Sievers 
@@ -142,6 +143,251 @@ hypervVerifyResponse(WsManClient *client, WsXmlDocH 
response,
 }
 
 
+/*
+ * Methods to work with method invocation parameters
+ */
+
+/*
+ * hypervInitInvokeParamsList:
+ * @priv: hypervPrivate object associated with the connection.
+ * @method: The name of the method you are calling
+ * @selector: The selector for the object you are invoking the method on
+ * @obj: The WmiInfo of the object class you are invoking the method on.
+ *
+ * Create a new InvokeParamsList object for the method call.
+ *
+ * Returns a pointer to the newly instantiated object on success, which should
+ * be freed by hypervInvokeMethod. Otherwise returns NULL.
+ */
+hypervInvokeParamsListPtr
+hypervInitInvokeParamsList(hypervPrivate *priv, const char *method,
+const char *selector, hypervWmiClassInfoListPtr obj)
+{
+hypervInvokeParamsListPtr params = NULL;
+hypervWmiClassInfoPtr info = NULL;
+
+if (hypervGetWmiClassInfo(priv, obj, &info) < 0)
+goto cleanup;
+
+if (VIR_ALLOC(params) < 0)
+goto cleanup;
+
+if (VIR_ALLOC_N(params->params,
+HYPERV_DEFAULT_PARAM_COUNT) < 0) {
+VIR_FREE(params);
+goto cleanup;
+}
+
+params->method = method;
+params->ns = info->rootUri;
+params->resourceUri = info->resourceUri;
+params->selector = selector;
+params->nbParams = 0;
+params->nbAvailParams = HYPERV_DEFAULT_PARAM_COUNT;
+
+ cleanup:
+return params;
+}
+
+/*
+ * hypervFreeInvokeParams:
+ * @params: Params object to be freed
+ *
+ */
+void
+hypervFreeInvokeParams(hypervInvokeParamsListPtr params)
+{
+if (params == NULL)
+return;
+
+VIR_DISPOSE_N(params->params, params->nbAvailParams);
+VIR_FREE(params);
+
+return;
+}
+
+static inline int
+hypervCheckParams(hypervInvokeParamsListPtr params)
+{
+int result = -1;
+
+if (params->nbParams + 1 > params->nbAvailParams) {
+if (VIR_EXPAND_N(params->params, params->nbAvailParams, 5) < 0)
+goto cleanup;
+}
+
+result = 0;
+ cleanup:
+return result;
+}
+
+/*
+ * hypervAddSimpleParam:
+ * @params: Params object to add to
+ * @name: Name of the parameter
+ * @value: Value of the parameter
+ *
+ * Add a param of type HYPERV_SIMPLE_PARAM, which is essentially a serialized
+ * key/value pair.
+ *
+ * Returns -1 on failure, 0 on success.
+ */
+int
+hypervAddSimpleParam(hypervInvokeParamsListPtr params, const char *name,
+const char *value)
+{
+int result = -1;
+hypervParamPtr p = NULL;
+
+if (hypervCheckParams(params) < 0)
+goto cleanup;
+
+p = ¶ms->params[params->nbParams];
+p->type = HYPERV_SIMPLE_PARAM;
+p->simple.name = name;
+p->simple.value = value;
+params->nbParams++;
+
+result = 0;
+ cleanup:
+return result;
+}
+
+/*
+ * hypervAddEprParam:
+ * @params: Params objec to add to
+ * @name: Parameter name
+ * @priv: hypervPrivate object associated with the connection
+ * @query: WQL filter
+ * @eprInfo: WmiInfo of the object being filtered
+ *
+ * Adds an EPR param to the params list. Returns -1 on failure, 0 on success.
+ */
+int
+hypervAddEprParam(hypervInvokeParamsListPtr params, const char *name,
+hypervPrivate *priv, virBufferPtr query,
+hypervWmiClassInfoListPtr eprInfo)
+{
+int result = -1;
+hypervParamPtr p = NULL;
+hypervWmiClassInfoPtr classInfo = NULL;
+
+if (hypervGetWmiClassInfo(priv, eprInfo, &classInfo) < 0)
+goto cleanup;
+
+if (hypervCheckParams(params) < 0)
+goto cleanup;
+
+p = ¶ms->params[params->nbParams];
+p->type = HYPERV_EPR_PARAM;
+p->epr.name = name;
+p->epr.query = query;
+p->epr.info = classInfo;
+params->nbParams++;
+
+result = 0;
+ cleanup:
+return result;
+}
+
+/

[libvirt] [PATCH 3/6] hyperv: add hypervInvokeMethod

2017-04-17 Thread Sri Ramanujam
This commit adds support for invoking methods on remote objects
via hypervInvokeMethod.
---
 src/hyperv/hyperv_wmi.c | 566 
 src/hyperv/hyperv_wmi.h |   3 +
 src/hyperv/openwsman.h  |   4 +
 3 files changed, 573 insertions(+)

diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index c9a7666..cbbe028 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -24,6 +24,7 @@
  */
 
 #include 
+#include 
 
 #include "internal.h"
 #include "virerror.h"
@@ -34,11 +35,14 @@
 #include "hyperv_private.h"
 #include "hyperv_wmi.h"
 #include "virstring.h"
+#include "openwsman.h"
+#include "virlog.h"
 
 #define WS_SERIALIZER_FREE_MEM_WORKS 0
 
 #define VIR_FROM_THIS VIR_FROM_HYPERV
 
+VIR_LOG_INIT("hyperv.hyperv_wmi");
 
 static int
 hypervGetWmiClassInfo(hypervPrivate *priv, hypervWmiClassInfoListPtr list,
@@ -388,6 +392,568 @@ hypervAddEmbeddedParam(hypervInvokeParamsListPtr params, 
hypervPrivate *priv,
 }
 
 
+/*
+ * Serializing parameters to XML and invoking methods
+ */
+
+static int
+hypervGetCimTypeInfo(hypervCimTypePtr typemap, const char *name,
+hypervCimTypePtr *property)
+{
+size_t i = 0;
+while (typemap[i].name[0] != '\0') {
+if (STREQ(typemap[i].name, name)) {
+*property = &typemap[i];
+return 0;
+}
+i++;
+}
+
+return -1;
+}
+
+
+static int
+hypervCreateInvokeXmlDoc(hypervInvokeParamsListPtr params, WsXmlDocH *docRoot)
+{
+int result = -1;
+char *method = NULL;
+WsXmlNodeH xmlNodeMethod = NULL;
+
+if (virAsprintf(&method, "%s_INPUT", params->method) < 0)
+goto err;
+
+*docRoot = ws_xml_create_doc(NULL, method);
+if (*docRoot == NULL) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not instantiate XML document"));
+goto err;
+}
+
+xmlNodeMethod = xml_parser_get_root(*docRoot);
+if (xmlNodeMethod == NULL) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not get root node of XML document"));
+goto err;
+}
+
+/* add resource URI as namespace */
+ws_xml_set_ns(xmlNodeMethod, params->resourceUri, "p");
+
+result = 0;
+goto cleanup;
+
+ err:
+if (*docRoot != NULL) {
+ws_xml_destroy_doc(*docRoot);
+*docRoot = NULL;
+}
+ cleanup:
+VIR_FREE(method);
+return result;
+}
+
+static int
+hypervSerializeSimpleParam(hypervParamPtr p, const char *resourceUri,
+WsXmlNodeH *methodNode)
+{
+int result = -1;
+WsXmlNodeH xmlNodeParam = NULL;
+
+xmlNodeParam = ws_xml_add_child(*methodNode, resourceUri,
+p->simple.name, p->simple.value);
+if (xmlNodeParam == NULL) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+_("Could not create simple param"));
+goto cleanup;
+}
+
+result = 0;
+
+ cleanup:
+return result;
+}
+
+static int
+hypervSerializeEprParam(hypervParamPtr p, hypervPrivate *priv,
+const char *resourceUri, WsXmlDocH doc, WsXmlNodeH *methodNode)
+{
+int result = -1;
+WsXmlNodeH xmlNodeParam = NULL,
+   xmlNodeTemp = NULL,
+   xmlNodeAddr = NULL,
+   xmlNodeRef = NULL;
+xmlNodePtr xmlNodeAddrPtr = NULL,
+   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;
+
+/* init and set up options */
+options = wsmc_options_init();
+if (!options) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not init 
options"));
+goto cleanup;
+}
+wsmc_set_action_option(options, FLAG_ENUMERATION_ENUM_EPR);
+
+/* Get query and create filter based on it */
+query_string = virBufferContentAndReset(p->epr.query);
+filter = filter_create_simple(WSM_WQL_FILTER_DIALECT, query_string);
+if (!filter) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create WQL 
filter"));
+goto cleanup;
+}
+
+/* enumerate based on the filter from this query */
+xmlDocResponse = wsmc_action_enumerate(priv->client, p->epr.info->rootUri,
+options, filter);
+if (hypervVerifyResponse(priv->client, xmlDocResponse, "enumeration") < 0)
+goto cleanup;
+
+/* Get context */
+enumContext = wsmc_get_enum_context(xmlDocResponse);
+ws_xml_destroy_doc(xmlDocResponse);
+
+/* Pull using filter and enum context */
+xmlDocResponse = wsmc_action_pull(priv->client, resourceUri, options,
+filter, enumContext);
+
+if (hypervVerifyResponse(priv->client, xmlDocResponse, "pull") < 0)
+goto cleanup;
+
+/* drill down and extract EPR node children */
+if (!(xmlNodeTemp = ws_xml_get_soap_body(xmlDocResponse))) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "