2011-07-13 14:47:01 +00:00
|
|
|
/*
|
|
|
|
* hyperv_driver.c: core driver functions for managing Microsoft Hyper-V hosts
|
|
|
|
*
|
2013-01-10 21:39:43 +00:00
|
|
|
* Copyright (C) 2011-2013 Matthias Bolte <matthias.bolte@googlemail.com>
|
2011-07-13 14:47:01 +00:00
|
|
|
* Copyright (C) 2009 Michael Sievers <msievers83@googlemail.com>
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 10:06:23 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2011-07-13 14:47:01 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include "internal.h"
|
|
|
|
#include "datatypes.h"
|
2015-07-17 09:11:23 +00:00
|
|
|
#include "virdomainobjlist.h"
|
2012-03-19 16:21:12 +00:00
|
|
|
#include "virauth.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2012-12-13 18:01:25 +00:00
|
|
|
#include "viruuid.h"
|
2011-07-13 14:47:01 +00:00
|
|
|
#include "hyperv_driver.h"
|
|
|
|
#include "hyperv_private.h"
|
2011-07-13 15:16:47 +00:00
|
|
|
#include "hyperv_util.h"
|
|
|
|
#include "hyperv_wmi.h"
|
|
|
|
#include "openwsman.h"
|
2013-04-03 10:36:23 +00:00
|
|
|
#include "virstring.h"
|
2017-06-27 19:13:26 +00:00
|
|
|
#include "virkeycode.h"
|
|
|
|
#include "intprops.h"
|
2011-07-13 14:47:01 +00:00
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_HYPERV
|
|
|
|
|
2014-02-28 12:16:17 +00:00
|
|
|
VIR_LOG_INIT("hyperv.hyperv_driver");
|
2011-07-13 14:47:01 +00:00
|
|
|
|
2011-07-13 15:16:47 +00:00
|
|
|
static void
|
|
|
|
hypervFreePrivate(hypervPrivate **priv)
|
|
|
|
{
|
2014-11-13 14:23:51 +00:00
|
|
|
if (priv == NULL || *priv == NULL)
|
2011-07-13 15:16:47 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
if ((*priv)->client != NULL) {
|
|
|
|
/* FIXME: This leaks memory due to bugs in openwsman <= 2.2.6 */
|
|
|
|
wsmc_release((*priv)->client);
|
|
|
|
}
|
|
|
|
|
|
|
|
hypervFreeParsedUri(&(*priv)->parsedUri);
|
|
|
|
VIR_FREE(*priv);
|
|
|
|
}
|
|
|
|
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
static int
|
|
|
|
hypervInitConnection(virConnectPtr conn, hypervPrivate *priv,
|
|
|
|
char *username, char *password)
|
|
|
|
{
|
|
|
|
virBuffer query = VIR_BUFFER_INITIALIZER;
|
|
|
|
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
|
|
|
|
hypervObject *computerSystem = NULL;
|
|
|
|
int ret = -1;
|
2011-07-13 15:16:47 +00:00
|
|
|
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
/* Initialize the openwsman connection */
|
|
|
|
priv->client = wsmc_create(conn->uri->server, conn->uri->port, "/wsman",
|
|
|
|
priv->parsedUri->transport, username, password);
|
|
|
|
|
|
|
|
if (priv->client == NULL) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Could not create openwsman client"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wsmc_transport_init(priv->client, NULL) != 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Could not initialize openwsman transport"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: Currently only basic authentication is supported */
|
|
|
|
wsman_transport_set_auth_method(priv->client, "basic");
|
|
|
|
|
|
|
|
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
|
|
|
|
wqlQuery.query = &query;
|
|
|
|
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
|
|
|
|
virBufferAddLit(&query, "WHERE ");
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_PHYSICAL);
|
|
|
|
|
|
|
|
/* try query using V2 namespace (for Hyper-V 2012+) */
|
|
|
|
priv->wmiVersion = HYPERV_WMI_VERSION_V2;
|
|
|
|
|
|
|
|
if (hypervEnumAndPull(priv, &wqlQuery, &computerSystem) < 0) {
|
|
|
|
/* rebuild query because hypervEnumAndPull consumes it */
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
|
|
|
|
virBufferAddLit(&query, "WHERE ");
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_PHYSICAL);
|
|
|
|
|
|
|
|
/* fall back to V1 namespace (for Hyper-V 2008) */
|
|
|
|
priv->wmiVersion = HYPERV_WMI_VERSION_V1;
|
|
|
|
|
2017-10-06 06:47:33 +00:00
|
|
|
if (hypervEnumAndPull(priv, &wqlQuery, &computerSystem) < 0)
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
hypervFreeObject(priv, computerSystem);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2011-07-13 15:16:47 +00:00
|
|
|
|
2011-07-13 14:47:01 +00:00
|
|
|
static virDrvOpenStatus
|
2016-06-03 17:01:27 +00:00
|
|
|
hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth,
|
2019-10-14 12:45:33 +00:00
|
|
|
virConfPtr conf G_GNUC_UNUSED,
|
2016-06-03 17:01:27 +00:00
|
|
|
unsigned int flags)
|
2011-07-13 14:47:01 +00:00
|
|
|
{
|
2011-07-13 15:16:47 +00:00
|
|
|
virDrvOpenStatus result = VIR_DRV_OPEN_ERROR;
|
|
|
|
hypervPrivate *priv = NULL;
|
|
|
|
char *username = NULL;
|
|
|
|
char *password = NULL;
|
|
|
|
|
2011-07-13 14:47:01 +00:00
|
|
|
virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
|
|
|
|
|
2011-07-13 15:16:47 +00:00
|
|
|
/* Allocate per-connection private data */
|
2013-07-04 10:09:29 +00:00
|
|
|
if (VIR_ALLOC(priv) < 0)
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2014-11-13 14:23:51 +00:00
|
|
|
if (hypervParseUri(&priv->parsedUri, conn->uri) < 0)
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* Set the port dependent on the transport protocol if no port is
|
|
|
|
* specified. This allows us to rely on the port parameter being
|
|
|
|
* correctly set when building URIs later on, without the need to
|
|
|
|
* distinguish between the situations port == 0 and port != 0 */
|
|
|
|
if (conn->uri->port == 0) {
|
|
|
|
if (STRCASEEQ(priv->parsedUri->transport, "https")) {
|
|
|
|
conn->uri->port = 5986;
|
|
|
|
} else {
|
|
|
|
conn->uri->port = 5985;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Request credentials */
|
|
|
|
if (conn->uri->user != NULL) {
|
2019-10-20 11:49:46 +00:00
|
|
|
username = g_strdup(conn->uri->user);
|
2011-07-13 15:16:47 +00:00
|
|
|
} else {
|
2018-08-14 16:31:52 +00:00
|
|
|
if (!(username = virAuthGetUsername(conn, auth, "hyperv",
|
|
|
|
"administrator",
|
|
|
|
conn->uri->server)))
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2018-08-14 16:31:52 +00:00
|
|
|
if (!(password = virAuthGetPassword(conn, auth, "hyperv", username,
|
|
|
|
conn->uri->server)))
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
if (hypervInitConnection(conn, priv, username, password) < 0)
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
conn->privateData = priv;
|
2013-01-10 21:39:43 +00:00
|
|
|
priv = NULL;
|
2011-07-13 15:16:47 +00:00
|
|
|
result = VIR_DRV_OPEN_SUCCESS;
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2013-01-10 21:39:43 +00:00
|
|
|
hypervFreePrivate(&priv);
|
2011-07-13 15:16:47 +00:00
|
|
|
VIR_FREE(username);
|
|
|
|
VIR_FREE(password);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
hypervConnectClose(virConnectPtr conn)
|
2011-07-13 15:16:47 +00:00
|
|
|
{
|
|
|
|
hypervPrivate *priv = conn->privateData;
|
|
|
|
|
|
|
|
hypervFreePrivate(&priv);
|
|
|
|
|
|
|
|
conn->privateData = NULL;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const char *
|
2019-10-14 12:45:33 +00:00
|
|
|
hypervConnectGetType(virConnectPtr conn G_GNUC_UNUSED)
|
2011-07-13 15:16:47 +00:00
|
|
|
{
|
|
|
|
return "Hyper-V";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static char *
|
2013-04-23 12:50:18 +00:00
|
|
|
hypervConnectGetHostname(virConnectPtr conn)
|
2011-07-13 15:16:47 +00:00
|
|
|
{
|
|
|
|
char *hostname = NULL;
|
|
|
|
hypervPrivate *priv = conn->privateData;
|
|
|
|
virBuffer query = VIR_BUFFER_INITIALIZER;
|
|
|
|
Win32_ComputerSystem *computerSystem = NULL;
|
|
|
|
|
|
|
|
virBufferAddLit(&query, WIN32_COMPUTERSYSTEM_WQL_SELECT);
|
|
|
|
|
2014-11-13 14:23:51 +00:00
|
|
|
if (hypervGetWin32ComputerSystemList(priv, &query, &computerSystem) < 0)
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (computerSystem == NULL) {
|
2012-07-18 14:29:12 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Could not lookup %s"),
|
|
|
|
"Win32_ComputerSystem");
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2019-10-18 11:27:03 +00:00
|
|
|
hostname = g_strdup(computerSystem->data.common->DNSHostName);
|
2011-07-13 15:16:47 +00:00
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2011-07-13 15:16:47 +00:00
|
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
|
|
|
|
|
|
return hostname;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
hypervNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
|
|
|
|
{
|
|
|
|
int result = -1;
|
|
|
|
hypervPrivate *priv = conn->privateData;
|
|
|
|
virBuffer query = VIR_BUFFER_INITIALIZER;
|
|
|
|
Win32_ComputerSystem *computerSystem = NULL;
|
|
|
|
Win32_Processor *processorList = NULL;
|
|
|
|
Win32_Processor *processor = NULL;
|
|
|
|
char *tmp;
|
|
|
|
|
2012-03-29 09:52:04 +00:00
|
|
|
memset(info, 0, sizeof(*info));
|
2011-07-13 15:16:47 +00:00
|
|
|
|
|
|
|
virBufferAddLit(&query, WIN32_COMPUTERSYSTEM_WQL_SELECT);
|
|
|
|
|
|
|
|
/* Get Win32_ComputerSystem */
|
2014-11-13 14:23:51 +00:00
|
|
|
if (hypervGetWin32ComputerSystemList(priv, &query, &computerSystem) < 0)
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (computerSystem == NULL) {
|
2012-07-18 14:29:12 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Could not lookup %s"),
|
|
|
|
"Win32_ComputerSystem");
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get Win32_Processor list */
|
2017-10-06 06:47:34 +00:00
|
|
|
virBufferEscapeSQL(&query,
|
|
|
|
"associators of "
|
|
|
|
"{Win32_ComputerSystem.Name=\"%s\"} "
|
|
|
|
"where AssocClass = Win32_ComputerSystemProcessor "
|
|
|
|
"ResultClass = Win32_Processor",
|
|
|
|
computerSystem->data.common->Name);
|
2011-07-13 15:16:47 +00:00
|
|
|
|
2014-11-13 14:23:51 +00:00
|
|
|
if (hypervGetWin32ProcessorList(priv, &query, &processorList) < 0)
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (processorList == NULL) {
|
2012-07-18 14:29:12 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Could not lookup %s"),
|
|
|
|
"Win32_Processor");
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Strip the string to fit more relevant information in 32 chars */
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
tmp = processorList->data.common->Name;
|
2011-07-13 15:16:47 +00:00
|
|
|
|
|
|
|
while (*tmp != '\0') {
|
|
|
|
if (STRPREFIX(tmp, " ")) {
|
|
|
|
memmove(tmp, tmp + 1, strlen(tmp + 1) + 1);
|
|
|
|
continue;
|
|
|
|
} else if (STRPREFIX(tmp, "(R)") || STRPREFIX(tmp, "(C)")) {
|
|
|
|
memmove(tmp, tmp + 3, strlen(tmp + 3) + 1);
|
|
|
|
continue;
|
|
|
|
} else if (STRPREFIX(tmp, "(TM)")) {
|
|
|
|
memmove(tmp, tmp + 4, strlen(tmp + 4) + 1);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
++tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fill struct */
|
2018-07-20 07:50:37 +00:00
|
|
|
if (virStrcpyStatic(info->model, processorList->data.common->Name) < 0) {
|
2012-07-18 14:29:12 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("CPU model %s too long for destination"),
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
processorList->data.common->Name);
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
info->memory = computerSystem->data.common->TotalPhysicalMemory / 1024; /* byte to kilobyte */
|
|
|
|
info->mhz = processorList->data.common->MaxClockSpeed;
|
2011-07-13 15:16:47 +00:00
|
|
|
info->nodes = 1;
|
|
|
|
info->sockets = 0;
|
|
|
|
|
|
|
|
for (processor = processorList; processor != NULL;
|
|
|
|
processor = processor->next) {
|
|
|
|
++info->sockets;
|
|
|
|
}
|
|
|
|
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
info->cores = processorList->data.common->NumberOfCores;
|
|
|
|
info->threads = info->cores / processorList->data.common->NumberOfLogicalProcessors;
|
2011-07-13 15:16:47 +00:00
|
|
|
info->cpus = info->sockets * info->cores;
|
|
|
|
|
|
|
|
result = 0;
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2011-07-13 15:16:47 +00:00
|
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
|
|
hypervFreeObject(priv, (hypervObject *)processorList);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
hypervConnectListDomains(virConnectPtr conn, int *ids, int maxids)
|
2011-07-13 15:16:47 +00:00
|
|
|
{
|
|
|
|
bool success = false;
|
|
|
|
hypervPrivate *priv = conn->privateData;
|
|
|
|
virBuffer query = VIR_BUFFER_INITIALIZER;
|
|
|
|
Msvm_ComputerSystem *computerSystemList = NULL;
|
|
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
|
|
int count = 0;
|
|
|
|
|
2014-11-13 14:23:51 +00:00
|
|
|
if (maxids == 0)
|
2011-07-13 15:16:47 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
|
|
|
|
virBufferAddLit(&query, "where ");
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_VIRTUAL);
|
|
|
|
virBufferAddLit(&query, "and ");
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_ACTIVE);
|
|
|
|
|
|
|
|
if (hypervGetMsvmComputerSystemList(priv, &query,
|
|
|
|
&computerSystemList) < 0) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (computerSystem = computerSystemList; computerSystem != NULL;
|
|
|
|
computerSystem = computerSystem->next) {
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
ids[count++] = computerSystem->data.common->ProcessID;
|
2011-07-13 15:16:47 +00:00
|
|
|
|
2014-11-13 14:23:51 +00:00
|
|
|
if (count >= maxids)
|
2011-07-13 15:16:47 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
success = true;
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2011-07-13 15:16:47 +00:00
|
|
|
hypervFreeObject(priv, (hypervObject *)computerSystemList);
|
|
|
|
|
|
|
|
return success ? count : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
hypervConnectNumOfDomains(virConnectPtr conn)
|
2011-07-13 15:16:47 +00:00
|
|
|
{
|
|
|
|
bool success = false;
|
|
|
|
hypervPrivate *priv = conn->privateData;
|
|
|
|
virBuffer query = VIR_BUFFER_INITIALIZER;
|
|
|
|
Msvm_ComputerSystem *computerSystemList = NULL;
|
|
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
|
|
|
|
virBufferAddLit(&query, "where ");
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_VIRTUAL);
|
|
|
|
virBufferAddLit(&query, "and ");
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_ACTIVE);
|
|
|
|
|
|
|
|
if (hypervGetMsvmComputerSystemList(priv, &query,
|
|
|
|
&computerSystemList) < 0) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (computerSystem = computerSystemList; computerSystem != NULL;
|
|
|
|
computerSystem = computerSystem->next) {
|
|
|
|
++count;
|
|
|
|
}
|
|
|
|
|
|
|
|
success = true;
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2011-07-13 15:16:47 +00:00
|
|
|
hypervFreeObject(priv, (hypervObject *)computerSystemList);
|
|
|
|
|
|
|
|
return success ? count : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static virDomainPtr
|
|
|
|
hypervDomainLookupByID(virConnectPtr conn, int id)
|
|
|
|
{
|
|
|
|
virDomainPtr domain = NULL;
|
|
|
|
hypervPrivate *priv = conn->privateData;
|
|
|
|
virBuffer query = VIR_BUFFER_INITIALIZER;
|
|
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
|
|
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
|
|
|
|
virBufferAddLit(&query, "where ");
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_VIRTUAL);
|
|
|
|
virBufferAsprintf(&query, "and ProcessID = %d", id);
|
|
|
|
|
2014-11-13 14:23:51 +00:00
|
|
|
if (hypervGetMsvmComputerSystemList(priv, &query, &computerSystem) < 0)
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (computerSystem == NULL) {
|
2012-07-18 14:29:12 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, _("No domain with ID %d"), id);
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
hypervMsvmComputerSystemToDomain(conn, computerSystem, &domain);
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2011-07-13 15:16:47 +00:00
|
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
|
|
|
|
|
|
return domain;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static virDomainPtr
|
|
|
|
hypervDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
|
|
|
|
{
|
|
|
|
virDomainPtr domain = NULL;
|
|
|
|
hypervPrivate *priv = conn->privateData;
|
|
|
|
char uuid_string[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virBuffer query = VIR_BUFFER_INITIALIZER;
|
|
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
|
|
|
|
|
|
virUUIDFormat(uuid, uuid_string);
|
|
|
|
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
|
|
|
|
virBufferAddLit(&query, "where ");
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_VIRTUAL);
|
2017-10-06 06:47:34 +00:00
|
|
|
virBufferEscapeSQL(&query, "and Name = \"%s\"", uuid_string);
|
2011-07-13 15:16:47 +00:00
|
|
|
|
2014-11-13 14:23:51 +00:00
|
|
|
if (hypervGetMsvmComputerSystemList(priv, &query, &computerSystem) < 0)
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (computerSystem == NULL) {
|
2012-07-18 14:29:12 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with UUID %s"), uuid_string);
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
hypervMsvmComputerSystemToDomain(conn, computerSystem, &domain);
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2011-07-13 15:16:47 +00:00
|
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
|
|
|
|
|
|
return domain;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static virDomainPtr
|
|
|
|
hypervDomainLookupByName(virConnectPtr conn, const char *name)
|
|
|
|
{
|
|
|
|
virDomainPtr domain = NULL;
|
|
|
|
hypervPrivate *priv = conn->privateData;
|
|
|
|
virBuffer query = VIR_BUFFER_INITIALIZER;
|
|
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
|
|
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
|
|
|
|
virBufferAddLit(&query, "where ");
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_VIRTUAL);
|
2017-10-06 06:47:34 +00:00
|
|
|
virBufferEscapeSQL(&query, "and ElementName = \"%s\"", name);
|
2011-07-13 15:16:47 +00:00
|
|
|
|
2014-11-13 14:23:51 +00:00
|
|
|
if (hypervGetMsvmComputerSystemList(priv, &query, &computerSystem) < 0)
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (computerSystem == NULL) {
|
2012-07-18 14:29:12 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with name %s"), name);
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
hypervMsvmComputerSystemToDomain(conn, computerSystem, &domain);
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2011-07-13 15:16:47 +00:00
|
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
|
|
|
|
|
|
return domain;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
hypervDomainSuspend(virDomainPtr domain)
|
|
|
|
{
|
|
|
|
int result = -1;
|
|
|
|
hypervPrivate *priv = domain->conn->privateData;
|
|
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
|
|
|
2014-11-13 14:23:51 +00:00
|
|
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
if (computerSystem->data.common->EnabledState !=
|
2011-07-13 15:16:47 +00:00
|
|
|
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_ENABLED) {
|
2012-07-18 14:29:12 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("Domain is not active"));
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = hypervInvokeMsvmComputerSystemRequestStateChange
|
|
|
|
(domain, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_PAUSED);
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2011-07-13 15:16:47 +00:00
|
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
hypervDomainResume(virDomainPtr domain)
|
|
|
|
{
|
|
|
|
int result = -1;
|
|
|
|
hypervPrivate *priv = domain->conn->privateData;
|
|
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
|
|
|
2014-11-13 14:23:51 +00:00
|
|
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
if (computerSystem->data.common->EnabledState !=
|
2011-07-13 15:16:47 +00:00
|
|
|
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_PAUSED) {
|
2012-07-18 14:29:12 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("Domain is not paused"));
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = hypervInvokeMsvmComputerSystemRequestStateChange
|
|
|
|
(domain, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_ENABLED);
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2011-07-13 15:16:47 +00:00
|
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
hypervDomainDestroyFlags(virDomainPtr domain, unsigned int flags)
|
|
|
|
{
|
|
|
|
int result = -1;
|
|
|
|
hypervPrivate *priv = domain->conn->privateData;
|
|
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
|
|
bool in_transition = false;
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2014-11-13 14:23:51 +00:00
|
|
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!hypervIsMsvmComputerSystemActive(computerSystem, &in_transition) ||
|
|
|
|
in_transition) {
|
2012-07-18 14:29:12 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("Domain is not active or is in state transition"));
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = hypervInvokeMsvmComputerSystemRequestStateChange
|
|
|
|
(domain, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_DISABLED);
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2011-07-13 15:16:47 +00:00
|
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
hypervDomainDestroy(virDomainPtr domain)
|
|
|
|
{
|
|
|
|
return hypervDomainDestroyFlags(domain, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static char *
|
2019-10-14 12:45:33 +00:00
|
|
|
hypervDomainGetOSType(virDomainPtr domain G_GNUC_UNUSED)
|
2011-07-13 15:16:47 +00:00
|
|
|
{
|
2013-05-03 12:42:20 +00:00
|
|
|
char *osType;
|
2011-07-13 15:16:47 +00:00
|
|
|
|
2019-10-18 11:27:03 +00:00
|
|
|
osType = g_strdup("hvm");
|
2011-07-13 15:16:47 +00:00
|
|
|
return osType;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
hypervDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
|
|
|
|
{
|
|
|
|
int result = -1;
|
|
|
|
hypervPrivate *priv = domain->conn->privateData;
|
|
|
|
char uuid_string[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virBuffer query = VIR_BUFFER_INITIALIZER;
|
|
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
|
|
Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
|
|
|
|
Msvm_ProcessorSettingData *processorSettingData = NULL;
|
|
|
|
Msvm_MemorySettingData *memorySettingData = NULL;
|
|
|
|
|
2012-03-29 09:52:04 +00:00
|
|
|
memset(info, 0, sizeof(*info));
|
2011-07-13 15:16:47 +00:00
|
|
|
|
|
|
|
virUUIDFormat(domain->uuid, uuid_string);
|
|
|
|
|
|
|
|
/* Get Msvm_ComputerSystem */
|
2014-11-13 14:23:51 +00:00
|
|
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* Get Msvm_VirtualSystemSettingData */
|
2017-10-06 06:47:34 +00:00
|
|
|
virBufferEscapeSQL(&query,
|
|
|
|
"associators of "
|
|
|
|
"{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
|
|
|
|
"Name=\"%s\"} "
|
|
|
|
"where AssocClass = Msvm_SettingsDefineState "
|
|
|
|
"ResultClass = Msvm_VirtualSystemSettingData",
|
|
|
|
uuid_string);
|
2011-07-13 15:16:47 +00:00
|
|
|
|
|
|
|
if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query,
|
|
|
|
&virtualSystemSettingData) < 0) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virtualSystemSettingData == NULL) {
|
2012-07-18 14:29:12 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Could not lookup %s for domain %s"),
|
|
|
|
"Msvm_VirtualSystemSettingData",
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
computerSystem->data.common->ElementName);
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get Msvm_ProcessorSettingData */
|
2017-10-06 06:47:34 +00:00
|
|
|
virBufferEscapeSQL(&query,
|
|
|
|
"associators of "
|
|
|
|
"{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
|
|
|
|
"where AssocClass = Msvm_VirtualSystemSettingDataComponent "
|
|
|
|
"ResultClass = Msvm_ProcessorSettingData",
|
|
|
|
virtualSystemSettingData->data.common->InstanceID);
|
2011-07-13 15:16:47 +00:00
|
|
|
|
|
|
|
if (hypervGetMsvmProcessorSettingDataList(priv, &query,
|
|
|
|
&processorSettingData) < 0) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (processorSettingData == NULL) {
|
2012-07-18 14:29:12 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Could not lookup %s for domain %s"),
|
|
|
|
"Msvm_ProcessorSettingData",
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
computerSystem->data.common->ElementName);
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get Msvm_MemorySettingData */
|
2017-10-06 06:47:34 +00:00
|
|
|
virBufferEscapeSQL(&query,
|
|
|
|
"associators of "
|
|
|
|
"{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
|
|
|
|
"where AssocClass = Msvm_VirtualSystemSettingDataComponent "
|
|
|
|
"ResultClass = Msvm_MemorySettingData",
|
|
|
|
virtualSystemSettingData->data.common->InstanceID);
|
2011-07-13 15:16:47 +00:00
|
|
|
|
|
|
|
if (hypervGetMsvmMemorySettingDataList(priv, &query,
|
|
|
|
&memorySettingData) < 0) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (memorySettingData == NULL) {
|
2012-07-18 14:29:12 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Could not lookup %s for domain %s"),
|
|
|
|
"Msvm_MemorySettingData",
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
computerSystem->data.common->ElementName);
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fill struct */
|
|
|
|
info->state = hypervMsvmComputerSystemEnabledStateToDomainState(computerSystem);
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
info->maxMem = memorySettingData->data.common->Limit * 1024; /* megabyte to kilobyte */
|
|
|
|
info->memory = memorySettingData->data.common->VirtualQuantity * 1024; /* megabyte to kilobyte */
|
|
|
|
info->nrVirtCpu = processorSettingData->data.common->VirtualQuantity;
|
2011-07-13 15:16:47 +00:00
|
|
|
info->cpuTime = 0;
|
|
|
|
|
|
|
|
result = 0;
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2011-07-13 15:16:47 +00:00
|
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
|
|
hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
|
|
|
|
hypervFreeObject(priv, (hypervObject *)processorSettingData);
|
|
|
|
hypervFreeObject(priv, (hypervObject *)memorySettingData);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
hypervDomainGetState(virDomainPtr domain, int *state, int *reason,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
int result = -1;
|
|
|
|
hypervPrivate *priv = domain->conn->privateData;
|
|
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2014-11-13 14:23:51 +00:00
|
|
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
*state = hypervMsvmComputerSystemEnabledStateToDomainState(computerSystem);
|
|
|
|
|
2014-11-13 14:23:51 +00:00
|
|
|
if (reason != NULL)
|
2011-07-13 15:16:47 +00:00
|
|
|
*reason = 0;
|
|
|
|
|
|
|
|
result = 0;
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2011-07-13 15:16:47 +00:00
|
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
|
|
|
|
{
|
|
|
|
char *xml = NULL;
|
|
|
|
hypervPrivate *priv = domain->conn->privateData;
|
|
|
|
virDomainDefPtr def = NULL;
|
|
|
|
char uuid_string[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virBuffer query = VIR_BUFFER_INITIALIZER;
|
|
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
|
|
Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
|
|
|
|
Msvm_ProcessorSettingData *processorSettingData = NULL;
|
|
|
|
Msvm_MemorySettingData *memorySettingData = NULL;
|
|
|
|
|
2019-02-14 20:25:01 +00:00
|
|
|
virCheckFlags(VIR_DOMAIN_XML_COMMON_FLAGS, NULL);
|
2011-07-13 15:16:47 +00:00
|
|
|
|
2015-10-19 17:06:55 +00:00
|
|
|
if (!(def = virDomainDefNew()))
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
virUUIDFormat(domain->uuid, uuid_string);
|
|
|
|
|
|
|
|
/* Get Msvm_ComputerSystem */
|
2014-11-13 14:23:51 +00:00
|
|
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* Get Msvm_VirtualSystemSettingData */
|
2017-10-06 06:47:34 +00:00
|
|
|
virBufferEscapeSQL(&query,
|
|
|
|
"associators of "
|
|
|
|
"{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
|
|
|
|
"Name=\"%s\"} "
|
|
|
|
"where AssocClass = Msvm_SettingsDefineState "
|
|
|
|
"ResultClass = Msvm_VirtualSystemSettingData",
|
|
|
|
uuid_string);
|
2011-07-13 15:16:47 +00:00
|
|
|
|
|
|
|
if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query,
|
|
|
|
&virtualSystemSettingData) < 0) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virtualSystemSettingData == NULL) {
|
2012-07-18 14:29:12 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Could not lookup %s for domain %s"),
|
|
|
|
"Msvm_VirtualSystemSettingData",
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
computerSystem->data.common->ElementName);
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get Msvm_ProcessorSettingData */
|
2017-10-06 06:47:34 +00:00
|
|
|
virBufferEscapeSQL(&query,
|
|
|
|
"associators of "
|
|
|
|
"{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
|
|
|
|
"where AssocClass = Msvm_VirtualSystemSettingDataComponent "
|
|
|
|
"ResultClass = Msvm_ProcessorSettingData",
|
|
|
|
virtualSystemSettingData->data.common->InstanceID);
|
2011-07-13 15:16:47 +00:00
|
|
|
|
|
|
|
if (hypervGetMsvmProcessorSettingDataList(priv, &query,
|
|
|
|
&processorSettingData) < 0) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (processorSettingData == NULL) {
|
2012-07-18 14:29:12 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Could not lookup %s for domain %s"),
|
|
|
|
"Msvm_ProcessorSettingData",
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
computerSystem->data.common->ElementName);
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get Msvm_MemorySettingData */
|
2017-10-06 06:47:34 +00:00
|
|
|
virBufferEscapeSQL(&query,
|
|
|
|
"associators of "
|
|
|
|
"{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
|
|
|
|
"where AssocClass = Msvm_VirtualSystemSettingDataComponent "
|
|
|
|
"ResultClass = Msvm_MemorySettingData",
|
|
|
|
virtualSystemSettingData->data.common->InstanceID);
|
2011-07-13 15:16:47 +00:00
|
|
|
|
|
|
|
if (hypervGetMsvmMemorySettingDataList(priv, &query,
|
|
|
|
&memorySettingData) < 0) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (memorySettingData == NULL) {
|
2012-07-18 14:29:12 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Could not lookup %s for domain %s"),
|
|
|
|
"Msvm_MemorySettingData",
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
computerSystem->data.common->ElementName);
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fill struct */
|
|
|
|
def->virtType = VIR_DOMAIN_VIRT_HYPERV;
|
|
|
|
|
|
|
|
if (hypervIsMsvmComputerSystemActive(computerSystem, NULL)) {
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
def->id = computerSystem->data.common->ProcessID;
|
2011-07-13 15:16:47 +00:00
|
|
|
} else {
|
|
|
|
def->id = -1;
|
|
|
|
}
|
|
|
|
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
if (virUUIDParse(computerSystem->data.common->Name, def->uuid) < 0) {
|
2012-07-18 14:29:12 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Could not parse UUID from string '%s'"),
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
computerSystem->data.common->Name);
|
2011-07-13 15:16:47 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-10-20 11:49:46 +00:00
|
|
|
def->name = g_strdup(computerSystem->data.common->ElementName);
|
2011-07-13 15:16:47 +00:00
|
|
|
|
2017-04-18 14:56:20 +00:00
|
|
|
if (priv->wmiVersion == HYPERV_WMI_VERSION_V1) {
|
2019-10-20 11:49:46 +00:00
|
|
|
def->description = g_strdup(virtualSystemSettingData->data.v1->Notes);
|
2017-04-18 14:56:20 +00:00
|
|
|
} else if (priv->wmiVersion == HYPERV_WMI_VERSION_V2 &&
|
|
|
|
virtualSystemSettingData->data.v2->Notes.data != NULL) {
|
|
|
|
char **notes = (char **)virtualSystemSettingData->data.v2->Notes.data;
|
|
|
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
|
|
size_t i = 0;
|
|
|
|
|
|
|
|
/* in practice Notes has 1 element */
|
|
|
|
for (i = 0; i < virtualSystemSettingData->data.v2->Notes.count; i++) {
|
|
|
|
/* but if there's more than 1, separate by double new line */
|
|
|
|
if (virBufferUse(&buf) > 0)
|
|
|
|
virBufferAddLit(&buf, "\n\n");
|
|
|
|
|
|
|
|
virBufferAdd(&buf, *notes, -1);
|
|
|
|
notes++;
|
|
|
|
}
|
|
|
|
|
|
|
|
def->description = virBufferContentAndReset(&buf);
|
|
|
|
}
|
2011-07-13 15:16:47 +00:00
|
|
|
|
2017-10-06 06:47:35 +00:00
|
|
|
/* mebibytes to kibibytes */
|
|
|
|
def->mem.max_memory = memorySettingData->data.common->Limit * 1024;
|
|
|
|
def->mem.cur_balloon = memorySettingData->data.common->VirtualQuantity * 1024;
|
|
|
|
virDomainDefSetMemoryTotal(def, memorySettingData->data.common->VirtualQuantity * 1024);
|
2011-07-13 15:16:47 +00:00
|
|
|
|
2015-10-16 14:10:27 +00:00
|
|
|
if (virDomainDefSetVcpusMax(def,
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
processorSettingData->data.common->VirtualQuantity,
|
2016-06-29 12:55:24 +00:00
|
|
|
NULL) < 0)
|
2015-10-16 14:10:27 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-10-22 08:52:05 +00:00
|
|
|
if (virDomainDefSetVcpus(def,
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
processorSettingData->data.common->VirtualQuantity) < 0)
|
2015-10-22 08:52:05 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-04-17 00:11:06 +00:00
|
|
|
def->os.type = VIR_DOMAIN_OSTYPE_HVM;
|
2011-07-13 15:16:47 +00:00
|
|
|
|
|
|
|
/* FIXME: devices section is totally missing */
|
|
|
|
|
2016-02-03 21:40:35 +00:00
|
|
|
xml = virDomainDefFormat(def, NULL,
|
2014-11-18 16:44:00 +00:00
|
|
|
virDomainDefFormatConvertXMLFlags(flags));
|
2011-07-13 15:16:47 +00:00
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2011-07-13 15:16:47 +00:00
|
|
|
virDomainDefFree(def);
|
|
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
|
|
hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
|
|
|
|
hypervFreeObject(priv, (hypervObject *)processorSettingData);
|
|
|
|
hypervFreeObject(priv, (hypervObject *)memorySettingData);
|
|
|
|
|
|
|
|
return xml;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
hypervConnectListDefinedDomains(virConnectPtr conn, char **const names, int maxnames)
|
2011-07-13 15:16:47 +00:00
|
|
|
{
|
|
|
|
bool success = false;
|
|
|
|
hypervPrivate *priv = conn->privateData;
|
|
|
|
virBuffer query = VIR_BUFFER_INITIALIZER;
|
|
|
|
Msvm_ComputerSystem *computerSystemList = NULL;
|
|
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
|
|
int count = 0;
|
Convert 'int i' to 'size_t i' in src/hyperv/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2011-07-13 15:16:47 +00:00
|
|
|
|
2014-11-13 14:23:51 +00:00
|
|
|
if (maxnames == 0)
|
2011-07-13 15:16:47 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
|
|
|
|
virBufferAddLit(&query, "where ");
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_VIRTUAL);
|
|
|
|
virBufferAddLit(&query, "and ");
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_INACTIVE);
|
|
|
|
|
|
|
|
if (hypervGetMsvmComputerSystemList(priv, &query,
|
|
|
|
&computerSystemList) < 0) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (computerSystem = computerSystemList; computerSystem != NULL;
|
|
|
|
computerSystem = computerSystem->next) {
|
2019-10-20 11:49:46 +00:00
|
|
|
names[count] = g_strdup(computerSystem->data.common->ElementName);
|
2011-07-13 15:16:47 +00:00
|
|
|
|
|
|
|
++count;
|
|
|
|
|
2014-11-13 14:23:51 +00:00
|
|
|
if (count >= maxnames)
|
2011-07-13 15:16:47 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
success = true;
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2011-07-13 15:16:47 +00:00
|
|
|
if (!success) {
|
2014-11-13 14:23:51 +00:00
|
|
|
for (i = 0; i < count; ++i)
|
2011-07-13 15:16:47 +00:00
|
|
|
VIR_FREE(names[i]);
|
|
|
|
|
|
|
|
count = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
hypervFreeObject(priv, (hypervObject *)computerSystemList);
|
|
|
|
|
|
|
|
return count;
|
2011-07-13 14:47:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
hypervConnectNumOfDefinedDomains(virConnectPtr conn)
|
2011-07-13 15:16:47 +00:00
|
|
|
{
|
|
|
|
bool success = false;
|
|
|
|
hypervPrivate *priv = conn->privateData;
|
|
|
|
virBuffer query = VIR_BUFFER_INITIALIZER;
|
|
|
|
Msvm_ComputerSystem *computerSystemList = NULL;
|
|
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
|
|
|
|
virBufferAddLit(&query, "where ");
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_VIRTUAL);
|
|
|
|
virBufferAddLit(&query, "and ");
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_INACTIVE);
|
|
|
|
|
|
|
|
if (hypervGetMsvmComputerSystemList(priv, &query,
|
|
|
|
&computerSystemList) < 0) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (computerSystem = computerSystemList; computerSystem != NULL;
|
|
|
|
computerSystem = computerSystem->next) {
|
|
|
|
++count;
|
|
|
|
}
|
|
|
|
|
|
|
|
success = true;
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2011-07-13 15:16:47 +00:00
|
|
|
hypervFreeObject(priv, (hypervObject *)computerSystemList);
|
|
|
|
|
|
|
|
return success ? count : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
hypervDomainCreateWithFlags(virDomainPtr domain, unsigned int flags)
|
|
|
|
{
|
|
|
|
int result = -1;
|
|
|
|
hypervPrivate *priv = domain->conn->privateData;
|
|
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2014-11-13 14:23:51 +00:00
|
|
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (hypervIsMsvmComputerSystemActive(computerSystem, NULL)) {
|
2012-07-18 14:29:12 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("Domain is already active or is in state transition"));
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = hypervInvokeMsvmComputerSystemRequestStateChange
|
|
|
|
(domain, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_ENABLED);
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2011-07-13 15:16:47 +00:00
|
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
hypervDomainCreate(virDomainPtr domain)
|
|
|
|
{
|
|
|
|
return hypervDomainCreateWithFlags(domain, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
hypervConnectIsEncrypted(virConnectPtr conn)
|
2011-07-13 15:16:47 +00:00
|
|
|
{
|
|
|
|
hypervPrivate *priv = conn->privateData;
|
|
|
|
|
|
|
|
if (STRCASEEQ(priv->parsedUri->transport, "https")) {
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
hypervConnectIsSecure(virConnectPtr conn)
|
2011-07-13 15:16:47 +00:00
|
|
|
{
|
|
|
|
hypervPrivate *priv = conn->privateData;
|
|
|
|
|
|
|
|
if (STRCASEEQ(priv->parsedUri->transport, "https")) {
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-09-23 06:56:13 +00:00
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
hypervConnectIsAlive(virConnectPtr conn)
|
2011-09-23 06:56:13 +00:00
|
|
|
{
|
|
|
|
hypervPrivate *priv = conn->privateData;
|
|
|
|
|
|
|
|
/* XXX we should be able to do something better than this is simple, safe,
|
|
|
|
* and good enough for now. In worst case, the function will return true
|
|
|
|
* even though the connection is not alive.
|
|
|
|
*/
|
|
|
|
if (priv->client)
|
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-07-13 15:16:47 +00:00
|
|
|
static int
|
|
|
|
hypervDomainIsActive(virDomainPtr domain)
|
|
|
|
{
|
|
|
|
int result = -1;
|
|
|
|
hypervPrivate *priv = domain->conn->privateData;
|
|
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
|
|
|
2014-11-13 14:23:51 +00:00
|
|
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
result = hypervIsMsvmComputerSystemActive(computerSystem, NULL) ? 1 : 0;
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2011-07-13 15:16:47 +00:00
|
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2019-10-14 12:45:33 +00:00
|
|
|
hypervDomainIsPersistent(virDomainPtr domain G_GNUC_UNUSED)
|
2011-07-13 15:16:47 +00:00
|
|
|
{
|
|
|
|
/* Hyper-V has no concept of transient domains, so all of them are persistent */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2019-10-14 12:45:33 +00:00
|
|
|
hypervDomainIsUpdated(virDomainPtr domain G_GNUC_UNUSED)
|
2011-07-13 14:47:01 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-07-13 15:16:47 +00:00
|
|
|
static int
|
|
|
|
hypervDomainManagedSave(virDomainPtr domain, unsigned int flags)
|
|
|
|
{
|
|
|
|
int result = -1;
|
|
|
|
hypervPrivate *priv = domain->conn->privateData;
|
|
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
|
|
bool in_transition = false;
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2014-11-13 14:23:51 +00:00
|
|
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!hypervIsMsvmComputerSystemActive(computerSystem, &in_transition) ||
|
|
|
|
in_transition) {
|
2012-07-18 14:29:12 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("Domain is not active or is in state transition"));
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = hypervInvokeMsvmComputerSystemRequestStateChange
|
|
|
|
(domain, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_SUSPENDED);
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2011-07-13 15:16:47 +00:00
|
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
hypervDomainHasManagedSaveImage(virDomainPtr domain, unsigned int flags)
|
|
|
|
{
|
|
|
|
int result = -1;
|
|
|
|
hypervPrivate *priv = domain->conn->privateData;
|
|
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2014-11-13 14:23:51 +00:00
|
|
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
result = computerSystem->data.common->EnabledState ==
|
2011-07-13 15:16:47 +00:00
|
|
|
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SUSPENDED ? 1 : 0;
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2011-07-13 15:16:47 +00:00
|
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
hypervDomainManagedSaveRemove(virDomainPtr domain, unsigned int flags)
|
|
|
|
{
|
|
|
|
int result = -1;
|
|
|
|
hypervPrivate *priv = domain->conn->privateData;
|
|
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2014-11-13 14:23:51 +00:00
|
|
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
if (computerSystem->data.common->EnabledState !=
|
2011-07-13 15:16:47 +00:00
|
|
|
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SUSPENDED) {
|
2012-07-18 14:29:12 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("Domain has no managed save image"));
|
2011-07-13 15:16:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = hypervInvokeMsvmComputerSystemRequestStateChange
|
|
|
|
(domain, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_DISABLED);
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2011-07-13 15:16:47 +00:00
|
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-06-05 12:20:58 +00:00
|
|
|
#define MATCH(FLAG) (flags & (FLAG))
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
hypervConnectListAllDomains(virConnectPtr conn,
|
|
|
|
virDomainPtr **domains,
|
|
|
|
unsigned int flags)
|
2012-06-05 12:20:58 +00:00
|
|
|
{
|
|
|
|
hypervPrivate *priv = conn->privateData;
|
|
|
|
virBuffer query = VIR_BUFFER_INITIALIZER;
|
|
|
|
Msvm_ComputerSystem *computerSystemList = NULL;
|
|
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
|
|
size_t ndoms;
|
|
|
|
virDomainPtr domain;
|
|
|
|
virDomainPtr *doms = NULL;
|
|
|
|
int count = 0;
|
|
|
|
int ret = -1;
|
Convert 'int i' to 'size_t i' in src/hyperv/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2012-06-05 12:20:58 +00:00
|
|
|
|
|
|
|
virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
|
|
|
|
|
|
|
|
/* check for filter combinations that return no results:
|
|
|
|
* persistent: all hyperv guests are persistent
|
|
|
|
* snapshot: the driver does not support snapshot management
|
|
|
|
* autostart: the driver does not support autostarting guests
|
|
|
|
*/
|
|
|
|
if ((MATCH(VIR_CONNECT_LIST_DOMAINS_TRANSIENT) &&
|
|
|
|
!MATCH(VIR_CONNECT_LIST_DOMAINS_PERSISTENT)) ||
|
|
|
|
(MATCH(VIR_CONNECT_LIST_DOMAINS_AUTOSTART) &&
|
|
|
|
!MATCH(VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART)) ||
|
|
|
|
(MATCH(VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT) &&
|
|
|
|
!MATCH(VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT))) {
|
2013-07-04 10:09:29 +00:00
|
|
|
if (domains && VIR_ALLOC_N(*domains, 1) < 0)
|
|
|
|
goto cleanup;
|
2012-06-05 12:20:58 +00:00
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
|
|
|
|
virBufferAddLit(&query, "where ");
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_VIRTUAL);
|
|
|
|
|
|
|
|
/* construct query with filter depending on flags */
|
2012-09-09 15:39:40 +00:00
|
|
|
if (!(MATCH(VIR_CONNECT_LIST_DOMAINS_ACTIVE) &&
|
|
|
|
MATCH(VIR_CONNECT_LIST_DOMAINS_INACTIVE))) {
|
|
|
|
if (MATCH(VIR_CONNECT_LIST_DOMAINS_ACTIVE)) {
|
2012-06-05 12:20:58 +00:00
|
|
|
virBufferAddLit(&query, "and ");
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_ACTIVE);
|
|
|
|
}
|
2012-09-09 15:39:40 +00:00
|
|
|
|
|
|
|
if (MATCH(VIR_CONNECT_LIST_DOMAINS_INACTIVE)) {
|
2012-06-05 12:20:58 +00:00
|
|
|
virBufferAddLit(&query, "and ");
|
|
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_INACTIVE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hypervGetMsvmComputerSystemList(priv, &query,
|
|
|
|
&computerSystemList) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (domains) {
|
|
|
|
if (VIR_ALLOC_N(doms, 1) < 0)
|
2013-07-04 10:09:29 +00:00
|
|
|
goto cleanup;
|
2012-06-05 12:20:58 +00:00
|
|
|
ndoms = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (computerSystem = computerSystemList; computerSystem != NULL;
|
|
|
|
computerSystem = computerSystem->next) {
|
|
|
|
|
|
|
|
/* filter by domain state */
|
|
|
|
if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE)) {
|
|
|
|
int st = hypervMsvmComputerSystemEnabledStateToDomainState(computerSystem);
|
|
|
|
if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_RUNNING) &&
|
|
|
|
st == VIR_DOMAIN_RUNNING) ||
|
|
|
|
(MATCH(VIR_CONNECT_LIST_DOMAINS_PAUSED) &&
|
|
|
|
st == VIR_DOMAIN_PAUSED) ||
|
|
|
|
(MATCH(VIR_CONNECT_LIST_DOMAINS_SHUTOFF) &&
|
|
|
|
st == VIR_DOMAIN_SHUTOFF) ||
|
|
|
|
(MATCH(VIR_CONNECT_LIST_DOMAINS_OTHER) &&
|
|
|
|
(st != VIR_DOMAIN_RUNNING &&
|
|
|
|
st != VIR_DOMAIN_PAUSED &&
|
|
|
|
st != VIR_DOMAIN_SHUTOFF))))
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* managed save filter */
|
|
|
|
if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_MANAGEDSAVE)) {
|
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
2017-04-04 22:26:08 +00:00
|
|
|
bool mansave = computerSystem->data.common->EnabledState ==
|
2012-06-05 12:20:58 +00:00
|
|
|
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SUSPENDED;
|
|
|
|
|
|
|
|
if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE) && mansave) ||
|
|
|
|
(MATCH(VIR_CONNECT_LIST_DOMAINS_NO_MANAGEDSAVE) && !mansave)))
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!doms) {
|
|
|
|
count++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2012-09-09 15:39:40 +00:00
|
|
|
if (VIR_RESIZE_N(doms, ndoms, count, 2) < 0)
|
2013-07-04 10:09:29 +00:00
|
|
|
goto cleanup;
|
2012-06-05 12:20:58 +00:00
|
|
|
|
2012-09-09 15:39:40 +00:00
|
|
|
domain = NULL;
|
|
|
|
|
2012-06-05 12:20:58 +00:00
|
|
|
if (hypervMsvmComputerSystemToDomain(conn, computerSystem,
|
|
|
|
&domain) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2012-09-09 15:39:40 +00:00
|
|
|
doms[count++] = domain;
|
2012-06-05 12:20:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (doms)
|
|
|
|
*domains = doms;
|
|
|
|
doms = NULL;
|
|
|
|
ret = count;
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2012-06-05 12:20:58 +00:00
|
|
|
if (doms) {
|
2014-11-13 14:23:51 +00:00
|
|
|
for (i = 0; i < count; ++i)
|
2014-11-30 14:57:02 +00:00
|
|
|
virObjectUnref(doms[i]);
|
2012-09-09 15:39:40 +00:00
|
|
|
|
|
|
|
VIR_FREE(doms);
|
2012-06-05 12:20:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
hypervFreeObject(priv, (hypervObject *)computerSystemList);
|
2012-09-09 15:39:40 +00:00
|
|
|
|
2012-06-05 12:20:58 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#undef MATCH
|
|
|
|
|
|
|
|
|
2017-06-27 19:13:26 +00:00
|
|
|
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;
|
|
|
|
|
2017-10-06 06:47:34 +00:00
|
|
|
virBufferEscapeSQL(&query,
|
2017-06-27 19:13:26 +00:00
|
|
|
"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)
|
2019-10-02 17:01:11 +00:00
|
|
|
g_usleep(holdtime * 1000);
|
2017-06-27 19:13:26 +00:00
|
|
|
|
|
|
|
/* 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);
|
2018-04-25 12:42:33 +00:00
|
|
|
hypervFreeObject(priv, (hypervObject *)keyboard);
|
|
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
2017-06-27 19:13:26 +00:00
|
|
|
virBufferFreeAndReset(&query);
|
|
|
|
return result;
|
|
|
|
}
|
2012-06-05 12:20:58 +00:00
|
|
|
|
2011-07-13 15:16:47 +00:00
|
|
|
|
2017-06-27 19:13:27 +00:00
|
|
|
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);
|
2017-10-06 06:47:34 +00:00
|
|
|
virBufferEscapeSQL(&eprQuery, "where Name = \"%s\"", uuid_string);
|
2017-06-27 19:13:27 +00:00
|
|
|
|
|
|
|
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);
|
2018-04-25 12:42:33 +00:00
|
|
|
hypervFreeObject(priv, (hypervObject *)vssd);
|
|
|
|
hypervFreeObject(priv, (hypervObject *)memsd);
|
2017-06-27 19:13:27 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
hypervDomainSetMemory(virDomainPtr domain, unsigned long memory)
|
|
|
|
{
|
|
|
|
return hypervDomainSetMemoryFlags(domain, memory, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-20 16:16:26 +00:00
|
|
|
static virHypervisorDriver hypervHypervisorDriver = {
|
2011-07-13 14:47:01 +00:00
|
|
|
.name = "Hyper-V",
|
2013-04-23 12:50:18 +00:00
|
|
|
.connectOpen = hypervConnectOpen, /* 0.9.5 */
|
|
|
|
.connectClose = hypervConnectClose, /* 0.9.5 */
|
|
|
|
.connectGetType = hypervConnectGetType, /* 0.9.5 */
|
|
|
|
.connectGetHostname = hypervConnectGetHostname, /* 0.9.5 */
|
2011-07-13 15:16:47 +00:00
|
|
|
.nodeGetInfo = hypervNodeGetInfo, /* 0.9.5 */
|
2013-04-23 12:50:18 +00:00
|
|
|
.connectListDomains = hypervConnectListDomains, /* 0.9.5 */
|
|
|
|
.connectNumOfDomains = hypervConnectNumOfDomains, /* 0.9.5 */
|
|
|
|
.connectListAllDomains = hypervConnectListAllDomains, /* 0.10.2 */
|
2011-07-13 15:16:47 +00:00
|
|
|
.domainLookupByID = hypervDomainLookupByID, /* 0.9.5 */
|
|
|
|
.domainLookupByUUID = hypervDomainLookupByUUID, /* 0.9.5 */
|
|
|
|
.domainLookupByName = hypervDomainLookupByName, /* 0.9.5 */
|
|
|
|
.domainSuspend = hypervDomainSuspend, /* 0.9.5 */
|
|
|
|
.domainResume = hypervDomainResume, /* 0.9.5 */
|
|
|
|
.domainDestroy = hypervDomainDestroy, /* 0.9.5 */
|
|
|
|
.domainDestroyFlags = hypervDomainDestroyFlags, /* 0.9.5 */
|
|
|
|
.domainGetOSType = hypervDomainGetOSType, /* 0.9.5 */
|
|
|
|
.domainGetInfo = hypervDomainGetInfo, /* 0.9.5 */
|
|
|
|
.domainGetState = hypervDomainGetState, /* 0.9.5 */
|
|
|
|
.domainGetXMLDesc = hypervDomainGetXMLDesc, /* 0.9.5 */
|
2013-04-23 12:50:18 +00:00
|
|
|
.connectListDefinedDomains = hypervConnectListDefinedDomains, /* 0.9.5 */
|
|
|
|
.connectNumOfDefinedDomains = hypervConnectNumOfDefinedDomains, /* 0.9.5 */
|
2011-07-13 15:16:47 +00:00
|
|
|
.domainCreate = hypervDomainCreate, /* 0.9.5 */
|
|
|
|
.domainCreateWithFlags = hypervDomainCreateWithFlags, /* 0.9.5 */
|
2013-04-23 12:50:18 +00:00
|
|
|
.connectIsEncrypted = hypervConnectIsEncrypted, /* 0.9.5 */
|
|
|
|
.connectIsSecure = hypervConnectIsSecure, /* 0.9.5 */
|
2011-07-13 15:16:47 +00:00
|
|
|
.domainIsActive = hypervDomainIsActive, /* 0.9.5 */
|
|
|
|
.domainIsPersistent = hypervDomainIsPersistent, /* 0.9.5 */
|
|
|
|
.domainIsUpdated = hypervDomainIsUpdated, /* 0.9.5 */
|
|
|
|
.domainManagedSave = hypervDomainManagedSave, /* 0.9.5 */
|
|
|
|
.domainHasManagedSaveImage = hypervDomainHasManagedSaveImage, /* 0.9.5 */
|
|
|
|
.domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */
|
2017-06-27 19:13:26 +00:00
|
|
|
.domainSendKey = hypervDomainSendKey, /* 3.6.0 */
|
2017-06-27 19:13:27 +00:00
|
|
|
.domainSetMemory = hypervDomainSetMemory, /* 3.6.0 */
|
|
|
|
.domainSetMemoryFlags = hypervDomainSetMemoryFlags, /* 3.6.0 */
|
2013-04-23 12:50:18 +00:00
|
|
|
.connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */
|
2011-07-13 14:47:01 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-07-13 15:16:47 +00:00
|
|
|
static void
|
|
|
|
hypervDebugHandler(const char *message, debug_level_e level,
|
2019-10-14 12:45:33 +00:00
|
|
|
void *user_data G_GNUC_UNUSED)
|
2011-07-13 15:16:47 +00:00
|
|
|
{
|
|
|
|
switch (level) {
|
|
|
|
case DEBUG_LEVEL_ERROR:
|
|
|
|
case DEBUG_LEVEL_CRITICAL:
|
2018-02-14 09:43:59 +00:00
|
|
|
case DEBUG_LEVEL_ALWAYS:
|
|
|
|
VIR_ERROR(_("openwsman: %s"), message);
|
2011-07-13 15:16:47 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DEBUG_LEVEL_WARNING:
|
2018-02-14 09:43:59 +00:00
|
|
|
VIR_WARN("openwsman: %s", message);
|
2011-07-13 15:16:47 +00:00
|
|
|
break;
|
|
|
|
|
2018-02-14 09:43:59 +00:00
|
|
|
case DEBUG_LEVEL_MESSAGE:
|
|
|
|
VIR_INFO("openwsman: %s", message);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEBUG_LEVEL_INFO:
|
|
|
|
VIR_INFO("openwsman: %s", message);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEBUG_LEVEL_DEBUG:
|
|
|
|
VIR_DEBUG("openwsman: %s", message);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEBUG_LEVEL_NONE:
|
2011-07-13 15:16:47 +00:00
|
|
|
default:
|
|
|
|
/* Ignore the rest */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-20 16:16:26 +00:00
|
|
|
static virConnectDriver hypervConnectDriver = {
|
2018-07-10 23:31:01 +00:00
|
|
|
.remoteOnly = true,
|
2018-03-27 14:51:45 +00:00
|
|
|
.uriSchemes = (const char *[]){ "hyperv", NULL },
|
2015-01-20 16:16:26 +00:00
|
|
|
.hypervisorDriver = &hypervHypervisorDriver,
|
|
|
|
};
|
2011-07-13 15:16:47 +00:00
|
|
|
|
2011-07-13 14:47:01 +00:00
|
|
|
int
|
|
|
|
hypervRegister(void)
|
|
|
|
{
|
2011-07-13 15:16:47 +00:00
|
|
|
/* Forward openwsman errors and warnings to libvirt's logging */
|
|
|
|
debug_add_handler(hypervDebugHandler, DEBUG_LEVEL_WARNING, NULL);
|
|
|
|
|
2015-01-20 16:16:26 +00:00
|
|
|
return virRegisterConnectDriver(&hypervConnectDriver,
|
|
|
|
false);
|
2011-07-13 14:47:01 +00:00
|
|
|
}
|