mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-11-02 11:21:12 +00:00
4445e16bfa
When SASL requests auth credentials, try to look them up in the config file first. If any are found, remove them from the list that the user is prompted for Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
1341 lines
37 KiB
C
1341 lines
37 KiB
C
|
|
/*
|
|
* hyperv_driver.c: core driver functions for managing Microsoft Hyper-V hosts
|
|
*
|
|
* Copyright (C) 2011 Matthias Bolte <matthias.bolte@googlemail.com>
|
|
* 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
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include "internal.h"
|
|
#include "datatypes.h"
|
|
#include "domain_conf.h"
|
|
#include "virauth.h"
|
|
#include "util.h"
|
|
#include "memory.h"
|
|
#include "logging.h"
|
|
#include "uuid.h"
|
|
#include "hyperv_driver.h"
|
|
#include "hyperv_interface_driver.h"
|
|
#include "hyperv_network_driver.h"
|
|
#include "hyperv_storage_driver.h"
|
|
#include "hyperv_device_monitor.h"
|
|
#include "hyperv_secret_driver.h"
|
|
#include "hyperv_nwfilter_driver.h"
|
|
#include "hyperv_private.h"
|
|
#include "hyperv_util.h"
|
|
#include "hyperv_wmi.h"
|
|
#include "openwsman.h"
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_HYPERV
|
|
|
|
|
|
|
|
static void
|
|
hypervFreePrivate(hypervPrivate **priv)
|
|
{
|
|
if (priv == NULL || *priv == NULL) {
|
|
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);
|
|
}
|
|
|
|
|
|
|
|
static virDrvOpenStatus
|
|
hypervOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags)
|
|
{
|
|
virDrvOpenStatus result = VIR_DRV_OPEN_ERROR;
|
|
char *plus;
|
|
hypervPrivate *priv = NULL;
|
|
char *username = NULL;
|
|
char *password = NULL;
|
|
virBuffer query = VIR_BUFFER_INITIALIZER;
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
|
|
virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
|
|
|
|
/* Decline if the URI is NULL or the scheme is NULL */
|
|
if (conn->uri == NULL || conn->uri->scheme == NULL) {
|
|
return VIR_DRV_OPEN_DECLINED;
|
|
}
|
|
|
|
/* Decline if the scheme is not hyperv */
|
|
plus = strchr(conn->uri->scheme, '+');
|
|
|
|
if (plus == NULL) {
|
|
if (STRCASENEQ(conn->uri->scheme, "hyperv")) {
|
|
return VIR_DRV_OPEN_DECLINED;
|
|
}
|
|
} else {
|
|
if (plus - conn->uri->scheme != 6 ||
|
|
STRCASENEQLEN(conn->uri->scheme, "hyperv", 6)) {
|
|
return VIR_DRV_OPEN_DECLINED;
|
|
}
|
|
|
|
HYPERV_ERROR(VIR_ERR_INVALID_ARG,
|
|
_("Transport '%s' in URI scheme is not supported, try again "
|
|
"without the transport part"), plus + 1);
|
|
return VIR_DRV_OPEN_ERROR;
|
|
}
|
|
|
|
/* Require server part */
|
|
if (conn->uri->server == NULL) {
|
|
HYPERV_ERROR(VIR_ERR_INVALID_ARG, "%s",
|
|
_("URI is missing the server part"));
|
|
return VIR_DRV_OPEN_ERROR;
|
|
}
|
|
|
|
/* Require auth */
|
|
if (auth == NULL || auth->cb == NULL) {
|
|
HYPERV_ERROR(VIR_ERR_INVALID_ARG, "%s",
|
|
_("Missing or invalid auth pointer"));
|
|
return VIR_DRV_OPEN_ERROR;
|
|
}
|
|
|
|
/* Allocate per-connection private data */
|
|
if (VIR_ALLOC(priv) < 0) {
|
|
virReportOOMError();
|
|
goto cleanup;
|
|
}
|
|
|
|
if (hypervParseUri(&priv->parsedUri, conn->uri) < 0) {
|
|
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) {
|
|
username = strdup(conn->uri->user);
|
|
|
|
if (username == NULL) {
|
|
virReportOOMError();
|
|
goto cleanup;
|
|
}
|
|
} else {
|
|
username = virAuthGetUsername(conn, auth, "hyperv", "administrator", conn->uri->server);
|
|
|
|
if (username == NULL) {
|
|
HYPERV_ERROR(VIR_ERR_AUTH_FAILED, "%s", _("Username request failed"));
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
password = virAuthGetPassword(conn, auth, "hyperv", username, conn->uri->server);
|
|
|
|
if (password == NULL) {
|
|
HYPERV_ERROR(VIR_ERR_AUTH_FAILED, "%s", _("Password request failed"));
|
|
goto cleanup;
|
|
}
|
|
|
|
/* Initialize the openwsman connection */
|
|
priv->client = wsmc_create(conn->uri->server, conn->uri->port, "/wsman",
|
|
priv->parsedUri->transport, username, password);
|
|
|
|
if (priv->client == NULL) {
|
|
HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
_("Could not create openwsman client"));
|
|
goto cleanup;
|
|
}
|
|
|
|
if (wsmc_transport_init(priv->client, NULL) != 0) {
|
|
HYPERV_ERROR(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");
|
|
|
|
/* Check if the connection can be established and if the server has the
|
|
* Hyper-V role installed. If the call to hypervGetMsvmComputerSystemList
|
|
* succeeds than the connection has been established. If the returned list
|
|
* is empty than the server isn't a Hyper-V server. */
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
|
|
virBufferAddLit(&query, "where ");
|
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_PHYSICAL);
|
|
|
|
if (hypervGetMsvmComputerSystemList(priv, &query, &computerSystem) < 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (computerSystem == NULL) {
|
|
HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR,
|
|
_("%s is not a Hyper-V server"), conn->uri->server);
|
|
goto cleanup;
|
|
}
|
|
|
|
conn->privateData = priv;
|
|
|
|
result = VIR_DRV_OPEN_SUCCESS;
|
|
|
|
cleanup:
|
|
if (result == VIR_DRV_OPEN_ERROR) {
|
|
hypervFreePrivate(&priv);
|
|
}
|
|
|
|
VIR_FREE(username);
|
|
VIR_FREE(password);
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
hypervClose(virConnectPtr conn)
|
|
{
|
|
hypervPrivate *priv = conn->privateData;
|
|
|
|
hypervFreePrivate(&priv);
|
|
|
|
conn->privateData = NULL;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
static const char *
|
|
hypervGetType(virConnectPtr conn ATTRIBUTE_UNUSED)
|
|
{
|
|
return "Hyper-V";
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
hypervGetHostname(virConnectPtr conn)
|
|
{
|
|
char *hostname = NULL;
|
|
hypervPrivate *priv = conn->privateData;
|
|
virBuffer query = VIR_BUFFER_INITIALIZER;
|
|
Win32_ComputerSystem *computerSystem = NULL;
|
|
|
|
virBufferAddLit(&query, WIN32_COMPUTERSYSTEM_WQL_SELECT);
|
|
|
|
if (hypervGetWin32ComputerSystemList(priv, &query, &computerSystem) < 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (computerSystem == NULL) {
|
|
HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR,
|
|
_("Could not lookup %s"),
|
|
"Win32_ComputerSystem");
|
|
goto cleanup;
|
|
}
|
|
|
|
hostname = strdup(computerSystem->data->DNSHostName);
|
|
|
|
if (hostname == NULL) {
|
|
virReportOOMError();
|
|
goto cleanup;
|
|
}
|
|
|
|
cleanup:
|
|
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;
|
|
|
|
memset(info, 0, sizeof (*info));
|
|
|
|
virBufferAddLit(&query, WIN32_COMPUTERSYSTEM_WQL_SELECT);
|
|
|
|
/* Get Win32_ComputerSystem */
|
|
if (hypervGetWin32ComputerSystemList(priv, &query, &computerSystem) < 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (computerSystem == NULL) {
|
|
HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR,
|
|
_("Could not lookup %s"),
|
|
"Win32_ComputerSystem");
|
|
goto cleanup;
|
|
}
|
|
|
|
/* Get Win32_Processor list */
|
|
virBufferAsprintf(&query,
|
|
"associators of "
|
|
"{Win32_ComputerSystem.Name=\"%s\"} "
|
|
"where AssocClass = Win32_ComputerSystemProcessor "
|
|
"ResultClass = Win32_Processor",
|
|
computerSystem->data->Name);
|
|
|
|
if (hypervGetWin32ProcessorList(priv, &query, &processorList) < 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (processorList == NULL) {
|
|
HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR,
|
|
_("Could not lookup %s"),
|
|
"Win32_Processor");
|
|
goto cleanup;
|
|
}
|
|
|
|
/* Strip the string to fit more relevant information in 32 chars */
|
|
tmp = processorList->data->Name;
|
|
|
|
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 */
|
|
if (virStrncpy(info->model, processorList->data->Name,
|
|
sizeof (info->model) - 1, sizeof (info->model)) == NULL) {
|
|
HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR,
|
|
_("CPU model %s too long for destination"),
|
|
processorList->data->Name);
|
|
goto cleanup;
|
|
}
|
|
|
|
info->memory = computerSystem->data->TotalPhysicalMemory / 1024; /* byte to kilobyte */
|
|
info->mhz = processorList->data->MaxClockSpeed;
|
|
info->nodes = 1;
|
|
info->sockets = 0;
|
|
|
|
for (processor = processorList; processor != NULL;
|
|
processor = processor->next) {
|
|
++info->sockets;
|
|
}
|
|
|
|
info->cores = processorList->data->NumberOfCores;
|
|
info->threads = info->cores / processorList->data->NumberOfLogicalProcessors;
|
|
info->cpus = info->sockets * info->cores;
|
|
|
|
result = 0;
|
|
|
|
cleanup:
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
hypervFreeObject(priv, (hypervObject *)processorList);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
hypervListDomains(virConnectPtr conn, int *ids, int maxids)
|
|
{
|
|
bool success = false;
|
|
hypervPrivate *priv = conn->privateData;
|
|
virBuffer query = VIR_BUFFER_INITIALIZER;
|
|
Msvm_ComputerSystem *computerSystemList = NULL;
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
int count = 0;
|
|
|
|
if (maxids == 0) {
|
|
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) {
|
|
ids[count++] = computerSystem->data->ProcessID;
|
|
|
|
if (count >= maxids) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
success = true;
|
|
|
|
cleanup:
|
|
hypervFreeObject(priv, (hypervObject *)computerSystemList);
|
|
|
|
return success ? count : -1;
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
hypervNumberOfDomains(virConnectPtr conn)
|
|
{
|
|
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;
|
|
|
|
cleanup:
|
|
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);
|
|
|
|
if (hypervGetMsvmComputerSystemList(priv, &query, &computerSystem) < 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (computerSystem == NULL) {
|
|
HYPERV_ERROR(VIR_ERR_NO_DOMAIN, _("No domain with ID %d"), id);
|
|
goto cleanup;
|
|
}
|
|
|
|
hypervMsvmComputerSystemToDomain(conn, computerSystem, &domain);
|
|
|
|
cleanup:
|
|
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);
|
|
virBufferAsprintf(&query, "and Name = \"%s\"", uuid_string);
|
|
|
|
if (hypervGetMsvmComputerSystemList(priv, &query, &computerSystem) < 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (computerSystem == NULL) {
|
|
HYPERV_ERROR(VIR_ERR_NO_DOMAIN,
|
|
_("No domain with UUID %s"), uuid_string);
|
|
goto cleanup;
|
|
}
|
|
|
|
hypervMsvmComputerSystemToDomain(conn, computerSystem, &domain);
|
|
|
|
cleanup:
|
|
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);
|
|
virBufferAsprintf(&query, "and ElementName = \"%s\"", name);
|
|
|
|
if (hypervGetMsvmComputerSystemList(priv, &query, &computerSystem) < 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (computerSystem == NULL) {
|
|
HYPERV_ERROR(VIR_ERR_NO_DOMAIN,
|
|
_("No domain with name %s"), name);
|
|
goto cleanup;
|
|
}
|
|
|
|
hypervMsvmComputerSystemToDomain(conn, computerSystem, &domain);
|
|
|
|
cleanup:
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
|
|
return domain;
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
hypervDomainSuspend(virDomainPtr domain)
|
|
{
|
|
int result = -1;
|
|
hypervPrivate *priv = domain->conn->privateData;
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
|
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (computerSystem->data->EnabledState !=
|
|
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_ENABLED) {
|
|
HYPERV_ERROR(VIR_ERR_OPERATION_INVALID, "%s",
|
|
_("Domain is not active"));
|
|
goto cleanup;
|
|
}
|
|
|
|
result = hypervInvokeMsvmComputerSystemRequestStateChange
|
|
(domain, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_PAUSED);
|
|
|
|
cleanup:
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
hypervDomainResume(virDomainPtr domain)
|
|
{
|
|
int result = -1;
|
|
hypervPrivate *priv = domain->conn->privateData;
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
|
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (computerSystem->data->EnabledState !=
|
|
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_PAUSED) {
|
|
HYPERV_ERROR(VIR_ERR_OPERATION_INVALID, "%s",
|
|
_("Domain is not paused"));
|
|
goto cleanup;
|
|
}
|
|
|
|
result = hypervInvokeMsvmComputerSystemRequestStateChange
|
|
(domain, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_ENABLED);
|
|
|
|
cleanup:
|
|
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);
|
|
|
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (!hypervIsMsvmComputerSystemActive(computerSystem, &in_transition) ||
|
|
in_transition) {
|
|
HYPERV_ERROR(VIR_ERR_OPERATION_INVALID, "%s",
|
|
_("Domain is not active or is in state transition"));
|
|
goto cleanup;
|
|
}
|
|
|
|
result = hypervInvokeMsvmComputerSystemRequestStateChange
|
|
(domain, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_DISABLED);
|
|
|
|
cleanup:
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
hypervDomainDestroy(virDomainPtr domain)
|
|
{
|
|
return hypervDomainDestroyFlags(domain, 0);
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
hypervDomainGetOSType(virDomainPtr domain ATTRIBUTE_UNUSED)
|
|
{
|
|
char *osType = strdup("hvm");
|
|
|
|
if (osType == NULL) {
|
|
virReportOOMError();
|
|
return NULL;
|
|
}
|
|
|
|
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;
|
|
|
|
memset(info, 0, sizeof (*info));
|
|
|
|
virUUIDFormat(domain->uuid, uuid_string);
|
|
|
|
/* Get Msvm_ComputerSystem */
|
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
/* Get Msvm_VirtualSystemSettingData */
|
|
virBufferAsprintf(&query,
|
|
"associators of "
|
|
"{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
|
|
"Name=\"%s\"} "
|
|
"where AssocClass = Msvm_SettingsDefineState "
|
|
"ResultClass = Msvm_VirtualSystemSettingData",
|
|
uuid_string);
|
|
|
|
if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query,
|
|
&virtualSystemSettingData) < 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (virtualSystemSettingData == NULL) {
|
|
HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR,
|
|
_("Could not lookup %s for domain %s"),
|
|
"Msvm_VirtualSystemSettingData",
|
|
computerSystem->data->ElementName);
|
|
goto cleanup;
|
|
}
|
|
|
|
/* Get Msvm_ProcessorSettingData */
|
|
virBufferAsprintf(&query,
|
|
"associators of "
|
|
"{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
|
|
"where AssocClass = Msvm_VirtualSystemSettingDataComponent "
|
|
"ResultClass = Msvm_ProcessorSettingData",
|
|
virtualSystemSettingData->data->InstanceID);
|
|
|
|
if (hypervGetMsvmProcessorSettingDataList(priv, &query,
|
|
&processorSettingData) < 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (processorSettingData == NULL) {
|
|
HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR,
|
|
_("Could not lookup %s for domain %s"),
|
|
"Msvm_ProcessorSettingData",
|
|
computerSystem->data->ElementName);
|
|
goto cleanup;
|
|
}
|
|
|
|
/* Get Msvm_MemorySettingData */
|
|
virBufferAsprintf(&query,
|
|
"associators of "
|
|
"{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
|
|
"where AssocClass = Msvm_VirtualSystemSettingDataComponent "
|
|
"ResultClass = Msvm_MemorySettingData",
|
|
virtualSystemSettingData->data->InstanceID);
|
|
|
|
if (hypervGetMsvmMemorySettingDataList(priv, &query,
|
|
&memorySettingData) < 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
if (memorySettingData == NULL) {
|
|
HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR,
|
|
_("Could not lookup %s for domain %s"),
|
|
"Msvm_MemorySettingData",
|
|
computerSystem->data->ElementName);
|
|
goto cleanup;
|
|
}
|
|
|
|
/* Fill struct */
|
|
info->state = hypervMsvmComputerSystemEnabledStateToDomainState(computerSystem);
|
|
info->maxMem = memorySettingData->data->Limit * 1024; /* megabyte to kilobyte */
|
|
info->memory = memorySettingData->data->VirtualQuantity * 1024; /* megabyte to kilobyte */
|
|
info->nrVirtCpu = processorSettingData->data->VirtualQuantity;
|
|
info->cpuTime = 0;
|
|
|
|
result = 0;
|
|
|
|
cleanup:
|
|
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);
|
|
|
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
*state = hypervMsvmComputerSystemEnabledStateToDomainState(computerSystem);
|
|
|
|
if (reason != NULL) {
|
|
*reason = 0;
|
|
}
|
|
|
|
result = 0;
|
|
|
|
cleanup:
|
|
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;
|
|
|
|
/* Flags checked by virDomainDefFormat */
|
|
|
|
if (VIR_ALLOC(def) < 0) {
|
|
virReportOOMError();
|
|
goto cleanup;
|
|
}
|
|
|
|
virUUIDFormat(domain->uuid, uuid_string);
|
|
|
|
/* Get Msvm_ComputerSystem */
|
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
/* Get Msvm_VirtualSystemSettingData */
|
|
virBufferAsprintf(&query,
|
|
"associators of "
|
|
"{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
|
|
"Name=\"%s\"} "
|
|
"where AssocClass = Msvm_SettingsDefineState "
|
|
"ResultClass = Msvm_VirtualSystemSettingData",
|
|
uuid_string);
|
|
|
|
if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query,
|
|
&virtualSystemSettingData) < 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (virtualSystemSettingData == NULL) {
|
|
HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR,
|
|
_("Could not lookup %s for domain %s"),
|
|
"Msvm_VirtualSystemSettingData",
|
|
computerSystem->data->ElementName);
|
|
goto cleanup;
|
|
}
|
|
|
|
/* Get Msvm_ProcessorSettingData */
|
|
virBufferAsprintf(&query,
|
|
"associators of "
|
|
"{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
|
|
"where AssocClass = Msvm_VirtualSystemSettingDataComponent "
|
|
"ResultClass = Msvm_ProcessorSettingData",
|
|
virtualSystemSettingData->data->InstanceID);
|
|
|
|
if (hypervGetMsvmProcessorSettingDataList(priv, &query,
|
|
&processorSettingData) < 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (processorSettingData == NULL) {
|
|
HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR,
|
|
_("Could not lookup %s for domain %s"),
|
|
"Msvm_ProcessorSettingData",
|
|
computerSystem->data->ElementName);
|
|
goto cleanup;
|
|
}
|
|
|
|
/* Get Msvm_MemorySettingData */
|
|
virBufferAsprintf(&query,
|
|
"associators of "
|
|
"{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
|
|
"where AssocClass = Msvm_VirtualSystemSettingDataComponent "
|
|
"ResultClass = Msvm_MemorySettingData",
|
|
virtualSystemSettingData->data->InstanceID);
|
|
|
|
if (hypervGetMsvmMemorySettingDataList(priv, &query,
|
|
&memorySettingData) < 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
if (memorySettingData == NULL) {
|
|
HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR,
|
|
_("Could not lookup %s for domain %s"),
|
|
"Msvm_MemorySettingData",
|
|
computerSystem->data->ElementName);
|
|
goto cleanup;
|
|
}
|
|
|
|
/* Fill struct */
|
|
def->virtType = VIR_DOMAIN_VIRT_HYPERV;
|
|
|
|
if (hypervIsMsvmComputerSystemActive(computerSystem, NULL)) {
|
|
def->id = computerSystem->data->ProcessID;
|
|
} else {
|
|
def->id = -1;
|
|
}
|
|
|
|
if (virUUIDParse(computerSystem->data->Name, def->uuid) < 0) {
|
|
HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR,
|
|
_("Could not parse UUID from string '%s'"),
|
|
computerSystem->data->Name);
|
|
return NULL;
|
|
}
|
|
|
|
def->name = strdup(computerSystem->data->ElementName);
|
|
|
|
if (def->name == NULL) {
|
|
virReportOOMError();
|
|
goto cleanup;
|
|
}
|
|
|
|
if (virtualSystemSettingData->data->Notes != NULL) {
|
|
def->description = strdup(virtualSystemSettingData->data->Notes);
|
|
|
|
if (def->description == NULL) {
|
|
virReportOOMError();
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
def->mem.max_balloon = memorySettingData->data->Limit * 1024; /* megabyte to kilobyte */
|
|
def->mem.cur_balloon = memorySettingData->data->VirtualQuantity * 1024; /* megabyte to kilobyte */
|
|
|
|
def->vcpus = processorSettingData->data->VirtualQuantity;
|
|
def->maxvcpus = processorSettingData->data->VirtualQuantity;
|
|
|
|
def->os.type = strdup("hvm");
|
|
|
|
if (def->os.type == NULL) {
|
|
virReportOOMError();
|
|
goto cleanup;
|
|
}
|
|
|
|
/* FIXME: devices section is totally missing */
|
|
|
|
xml = virDomainDefFormat(def, flags);
|
|
|
|
cleanup:
|
|
virDomainDefFree(def);
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
|
|
hypervFreeObject(priv, (hypervObject *)processorSettingData);
|
|
hypervFreeObject(priv, (hypervObject *)memorySettingData);
|
|
|
|
return xml;
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
hypervListDefinedDomains(virConnectPtr conn, char **const names, int maxnames)
|
|
{
|
|
bool success = false;
|
|
hypervPrivate *priv = conn->privateData;
|
|
virBuffer query = VIR_BUFFER_INITIALIZER;
|
|
Msvm_ComputerSystem *computerSystemList = NULL;
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
int count = 0;
|
|
int i;
|
|
|
|
if (maxnames == 0) {
|
|
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) {
|
|
names[count] = strdup(computerSystem->data->ElementName);
|
|
|
|
if (names[count] == NULL) {
|
|
virReportOOMError();
|
|
goto cleanup;
|
|
}
|
|
|
|
++count;
|
|
|
|
if (count >= maxnames) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
success = true;
|
|
|
|
cleanup:
|
|
if (!success) {
|
|
for (i = 0; i < count; ++i) {
|
|
VIR_FREE(names[i]);
|
|
}
|
|
|
|
count = -1;
|
|
}
|
|
|
|
hypervFreeObject(priv, (hypervObject *)computerSystemList);
|
|
|
|
return count;
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
hypervNumberOfDefinedDomains(virConnectPtr conn)
|
|
{
|
|
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;
|
|
|
|
cleanup:
|
|
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);
|
|
|
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (hypervIsMsvmComputerSystemActive(computerSystem, NULL)) {
|
|
HYPERV_ERROR(VIR_ERR_OPERATION_INVALID, "%s",
|
|
_("Domain is already active or is in state transition"));
|
|
goto cleanup;
|
|
}
|
|
|
|
result = hypervInvokeMsvmComputerSystemRequestStateChange
|
|
(domain, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_ENABLED);
|
|
|
|
cleanup:
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
hypervDomainCreate(virDomainPtr domain)
|
|
{
|
|
return hypervDomainCreateWithFlags(domain, 0);
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
hypervIsEncrypted(virConnectPtr conn)
|
|
{
|
|
hypervPrivate *priv = conn->privateData;
|
|
|
|
if (STRCASEEQ(priv->parsedUri->transport, "https")) {
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
hypervIsSecure(virConnectPtr conn)
|
|
{
|
|
hypervPrivate *priv = conn->privateData;
|
|
|
|
if (STRCASEEQ(priv->parsedUri->transport, "https")) {
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
hypervIsAlive(virConnectPtr conn)
|
|
{
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
hypervDomainIsActive(virDomainPtr domain)
|
|
{
|
|
int result = -1;
|
|
hypervPrivate *priv = domain->conn->privateData;
|
|
Msvm_ComputerSystem *computerSystem = NULL;
|
|
|
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
result = hypervIsMsvmComputerSystemActive(computerSystem, NULL) ? 1 : 0;
|
|
|
|
cleanup:
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
hypervDomainIsPersistent(virDomainPtr domain ATTRIBUTE_UNUSED)
|
|
{
|
|
/* Hyper-V has no concept of transient domains, so all of them are persistent */
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
hypervDomainIsUpdated(virDomainPtr domain ATTRIBUTE_UNUSED)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (!hypervIsMsvmComputerSystemActive(computerSystem, &in_transition) ||
|
|
in_transition) {
|
|
HYPERV_ERROR(VIR_ERR_OPERATION_INVALID, "%s",
|
|
_("Domain is not active or is in state transition"));
|
|
goto cleanup;
|
|
}
|
|
|
|
result = hypervInvokeMsvmComputerSystemRequestStateChange
|
|
(domain, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_SUSPENDED);
|
|
|
|
cleanup:
|
|
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);
|
|
|
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
result = computerSystem->data->EnabledState ==
|
|
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SUSPENDED ? 1 : 0;
|
|
|
|
cleanup:
|
|
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);
|
|
|
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (computerSystem->data->EnabledState !=
|
|
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SUSPENDED) {
|
|
HYPERV_ERROR(VIR_ERR_OPERATION_INVALID, "%s",
|
|
_("Domain has no managed save image"));
|
|
goto cleanup;
|
|
}
|
|
|
|
result = hypervInvokeMsvmComputerSystemRequestStateChange
|
|
(domain, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_DISABLED);
|
|
|
|
cleanup:
|
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
static virDriver hypervDriver = {
|
|
.no = VIR_DRV_HYPERV,
|
|
.name = "Hyper-V",
|
|
.open = hypervOpen, /* 0.9.5 */
|
|
.close = hypervClose, /* 0.9.5 */
|
|
.type = hypervGetType, /* 0.9.5 */
|
|
.getHostname = hypervGetHostname, /* 0.9.5 */
|
|
.nodeGetInfo = hypervNodeGetInfo, /* 0.9.5 */
|
|
.listDomains = hypervListDomains, /* 0.9.5 */
|
|
.numOfDomains = hypervNumberOfDomains, /* 0.9.5 */
|
|
.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 */
|
|
.listDefinedDomains = hypervListDefinedDomains, /* 0.9.5 */
|
|
.numOfDefinedDomains = hypervNumberOfDefinedDomains, /* 0.9.5 */
|
|
.domainCreate = hypervDomainCreate, /* 0.9.5 */
|
|
.domainCreateWithFlags = hypervDomainCreateWithFlags, /* 0.9.5 */
|
|
.isEncrypted = hypervIsEncrypted, /* 0.9.5 */
|
|
.isSecure = hypervIsSecure, /* 0.9.5 */
|
|
.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 */
|
|
.isAlive = hypervIsAlive, /* 0.9.8 */
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
hypervDebugHandler(const char *message, debug_level_e level,
|
|
void *user_data ATTRIBUTE_UNUSED)
|
|
{
|
|
switch (level) {
|
|
case DEBUG_LEVEL_ERROR:
|
|
case DEBUG_LEVEL_CRITICAL:
|
|
VIR_ERROR(_("openwsman error: %s"), message);
|
|
break;
|
|
|
|
case DEBUG_LEVEL_WARNING:
|
|
VIR_WARN("openwsman warning: %s", message);
|
|
break;
|
|
|
|
default:
|
|
/* Ignore the rest */
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int
|
|
hypervRegister(void)
|
|
{
|
|
if (virRegisterDriver(&hypervDriver) < 0 ||
|
|
hypervInterfaceRegister() < 0 ||
|
|
hypervNetworkRegister() < 0 ||
|
|
hypervStorageRegister() < 0 ||
|
|
hypervDeviceRegister() < 0 ||
|
|
hypervSecretRegister() < 0 ||
|
|
hypervNWFilterRegister() < 0) {
|
|
return -1;
|
|
}
|
|
|
|
/* Forward openwsman errors and warnings to libvirt's logging */
|
|
debug_add_handler(hypervDebugHandler, DEBUG_LEVEL_WARNING, NULL);
|
|
|
|
return 0;
|
|
}
|