[libvirt] [PATCH] xenapi: Don't leak url and caps in case of error
by Matthias Bolte
---
src/xenapi/xenapi_driver.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c
index 9a38e3f..7d0b748 100644
--- a/src/xenapi/xenapi_driver.c
+++ b/src/xenapi/xenapi_driver.c
@@ -172,9 +172,12 @@ xenapiOpen (virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUS
VIR_FREE(password);
if (privP != NULL) {
+ virCapabilitiesFree(privP->caps);
+
if (privP->session != NULL)
xenSessionFree(privP->session);
+ VIR_FREE(privP->url);
VIR_FREE(privP);
}
--
1.6.3.3
14 years, 8 months
[libvirt] [PATCH] xenapi: Check for NULL before accessing the scheme
by Matthias Bolte
---
src/xenapi/xenapi_driver.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c
index 00b62b3..9a38e3f 100644
--- a/src/xenapi/xenapi_driver.c
+++ b/src/xenapi/xenapi_driver.c
@@ -87,7 +87,8 @@ xenapiOpen (virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUS
char *password = NULL;
struct _xenapiPrivate *privP = NULL;
- if (STRCASENEQ(conn->uri->scheme, "XenAPI")) {
+ if (conn->uri == NULL || conn->uri->scheme == NULL ||
+ STRCASENEQ(conn->uri->scheme, "XenAPI")) {
return VIR_DRV_OPEN_DECLINED;
}
--
1.6.3.3
14 years, 8 months
[libvirt] [PATCH] xenapi: Request a username if there is non in the URI
by Matthias Bolte
Use virRequestUsername and virRequestPassword.
---
src/xenapi/xenapi_driver.c | 119 +++++++++++++++++++++++++++++++-------------
1 files changed, 84 insertions(+), 35 deletions(-)
diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c
index 8d5c8bb..00b62b3 100644
--- a/src/xenapi/xenapi_driver.c
+++ b/src/xenapi/xenapi_driver.c
@@ -83,62 +83,101 @@ getCapsObject (void)
static virDrvOpenStatus
xenapiOpen (virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED)
{
- char *passwd = NULL;
- xen_session *session;
- struct _xenapiPrivate *privP;
+ char *username = NULL;
+ char *password = NULL;
+ struct _xenapiPrivate *privP = NULL;
if (STRCASENEQ(conn->uri->scheme, "XenAPI")) {
return VIR_DRV_OPEN_DECLINED;
}
+
if (conn->uri->server == NULL) {
- xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED, "Server name not in URI");
- return VIR_DRV_OPEN_ERROR;
+ xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED,
+ "Server name not in URI");
+ goto error;
+ }
+
+ if (auth == NULL) {
+ xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED,
+ "Authentication Credentials not found");
+ goto error;
}
- if (auth) {
- passwd = xenapiUtil_RequestPassword(auth, conn->uri->user, conn->uri->server);
+
+ if (conn->uri->user != NULL) {
+ username = strdup(conn->uri->user);
+
+ if (username == NULL) {
+ virReportOOMError();
+ goto error;
+ }
} else {
- xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED, "Authentication Credentials not found");
- return VIR_DRV_OPEN_ERROR;
+ username = virRequestUsername(auth, NULL, conn->uri->server);
+
+ if (username == NULL) {
+ xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED,
+ "Username request failed");
+ goto error;
+ }
}
- if (!passwd || !conn->uri->user) {
- xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED, "Username/Password not valid");
- if (passwd) VIR_FREE(passwd);
- return VIR_DRV_OPEN_ERROR;
+
+ password = virRequestPassword(auth, username, conn->uri->server);
+
+ if (password == NULL) {
+ xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED,
+ "Password request failed");
+ goto error;
}
+
if (VIR_ALLOC(privP) < 0) {
virReportOOMError();
- return VIR_DRV_OPEN_ERROR;
+ goto error;
}
+
if (virAsprintf(&privP->url, "https://%s", conn->uri->server) < 0) {
virReportOOMError();
- VIR_FREE(passwd);
- return VIR_DRV_OPEN_ERROR;
+ goto error;
}
- xenapiUtil_ParseQuery(conn, conn->uri, &privP->noVerify);
+
+ if (xenapiUtil_ParseQuery(conn, conn->uri, &privP->noVerify) < 0)
+ goto error;
+
+ if (!(privP->caps = getCapsObject())) {
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR,
+ "Capabilities not found");
+ goto error;
+ }
+
xmlInitParser();
xmlKeepBlanksDefault(0);
xen_init();
curl_global_init(CURL_GLOBAL_ALL);
- session = xen_session_login_with_password(call_func, privP, conn->uri->user, passwd, xen_api_latest_version);
+ privP->session = xen_session_login_with_password(call_func, privP, username,
+ password, xen_api_latest_version);
- if (session && session->ok) {
- privP->session = session;
- if (!(privP->caps = getCapsObject())) {
- xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Capabilities not found");
- VIR_FREE(passwd);
- return VIR_DRV_OPEN_ERROR;
- }
+ if (privP->session != NULL && privP->session->ok) {
conn->privateData = privP;
- VIR_FREE(passwd);
+
+ VIR_FREE(username);
+ VIR_FREE(password);
+
return VIR_DRV_OPEN_SUCCESS;
- } else {
- xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED, "");
- if (session) xenSessionFree(session);
+ }
+
+ xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED, "");
+
+ error:
+ VIR_FREE(username);
+ VIR_FREE(password);
+
+ if (privP != NULL) {
+ if (privP->session != NULL)
+ xenSessionFree(privP->session);
+
VIR_FREE(privP);
- VIR_FREE(passwd);
- return VIR_DRV_OPEN_ERROR;
}
+
+ return VIR_DRV_OPEN_ERROR;
}
/*
@@ -150,10 +189,20 @@ xenapiOpen (virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUS
static int
xenapiClose (virConnectPtr conn)
{
- xen_session_logout(((struct _xenapiPrivate *)(conn->privateData))->session);
- virCapabilitiesFree(((struct _xenapiPrivate *)(conn->privateData))->caps);
- VIR_FREE(((struct _xenapiPrivate *)(conn->privateData))->url);
- VIR_FREE(conn->privateData);
+ struct _xenapiPrivate *priv = conn->privateData;
+
+ virCapabilitiesFree(priv->caps);
+
+ if (priv->session != NULL) {
+ xen_session_logout(priv->session);
+ xenSessionFree(priv->session);
+ }
+
+ VIR_FREE(priv->url);
+ VIR_FREE(priv);
+
+ conn->privateData = NULL;
+
return 0;
}
--
1.6.3.3
14 years, 8 months
[libvirt] [PATCH] xenapi: Check for valid private data in xenapiSessionErrorHandle
by Matthias Bolte
---
src/xenapi/xenapi_utils.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/xenapi/xenapi_utils.c b/src/xenapi/xenapi_utils.c
index 4b9a6d8..bfd53ed 100644
--- a/src/xenapi/xenapi_utils.c
+++ b/src/xenapi/xenapi_utils.c
@@ -374,12 +374,12 @@ xenapiSessionErrorHandle(virConnectPtr conn, virErrorNumber errNum,
const char *buf, const char *filename, const char *func,
size_t lineno)
{
- xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+ struct _xenapiPrivate *priv = conn->privateData;
- if (buf == NULL) {
- char *ret = returnErrorFromSession(session);
+ if (buf == NULL && priv != NULL && priv->session != NULL) {
+ char *ret = returnErrorFromSession(priv->session);
virReportErrorHelper(conn, VIR_FROM_XENAPI, errNum, filename, func, lineno, _("%s"), ret);
- xen_session_clear_error(session);
+ xen_session_clear_error(priv->session);
VIR_FREE(ret);
} else {
virReportErrorHelper(conn, VIR_FROM_XENAPI, errNum, filename, func, lineno, _("%s"), buf);
--
1.6.3.3
14 years, 8 months
[libvirt] [PATCH] esx: Move username and password helper functions to util.c
by Matthias Bolte
---
src/esx/esx_driver.c | 8 ++--
src/esx/esx_util.c | 83 ----------------------------------------------
src/esx/esx_util.h | 7 ----
src/util/util.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/util/util.h | 5 +++
5 files changed, 98 insertions(+), 94 deletions(-)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index c47af1c..3f8b900 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -354,7 +354,7 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED)
goto failure;
}
} else {
- username = esxUtil_RequestUsername(auth, "root", conn->uri->server);
+ username = virRequestUsername(auth, "root", conn->uri->server);
if (username == NULL) {
ESX_ERROR(VIR_ERR_AUTH_FAILED, "Username request failed");
@@ -366,7 +366,7 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED)
goto failure;
}
- password = esxUtil_RequestPassword(auth, username, conn->uri->server);
+ password = virRequestPassword(auth, username, conn->uri->server);
if (password == NULL) {
ESX_ERROR(VIR_ERR_AUTH_FAILED, "Password request failed");
@@ -491,14 +491,14 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED)
goto failure;
}
- username = esxUtil_RequestUsername(auth, "administrator", vCenter);
+ username = virRequestUsername(auth, "administrator", vCenter);
if (username == NULL) {
ESX_ERROR(VIR_ERR_AUTH_FAILED, "Username request failed");
goto failure;
}
- password = esxUtil_RequestPassword(auth, username, vCenter);
+ password = virRequestPassword(auth, username, vCenter);
if (password == NULL) {
ESX_ERROR(VIR_ERR_AUTH_FAILED, "Password request failed");
diff --git a/src/esx/esx_util.c b/src/esx/esx_util.c
index dcbd86c..3cbd2b1 100644
--- a/src/esx/esx_util.c
+++ b/src/esx/esx_util.c
@@ -49,89 +49,6 @@
-char *
-esxUtil_RequestUsername(virConnectAuthPtr auth, const char *defaultUsername,
- const char *hostname)
-{
- unsigned int ncred;
- virConnectCredential cred;
- char *prompt = NULL;
-
- memset(&cred, 0, sizeof(virConnectCredential));
-
- if (virAsprintf(&prompt, "Enter username for %s [%s]", hostname,
- defaultUsername) < 0) {
- return NULL;
- }
-
- for (ncred = 0; ncred < auth->ncredtype; ncred++) {
- if (auth->credtype[ncred] != VIR_CRED_AUTHNAME) {
- continue;
- }
-
- cred.type = VIR_CRED_AUTHNAME;
- cred.prompt = prompt;
- cred.challenge = hostname;
- cred.defresult = defaultUsername;
- cred.result = NULL;
- cred.resultlen = 0;
-
- if ((*(auth->cb))(&cred, 1, auth->cbdata) < 0) {
- VIR_FREE(cred.result);
- }
-
- break;
- }
-
- VIR_FREE(prompt);
-
- return cred.result;
-}
-
-
-
-char *
-esxUtil_RequestPassword(virConnectAuthPtr auth, const char *username,
- const char *hostname)
-{
- unsigned int ncred;
- virConnectCredential cred;
- char *prompt;
-
- memset(&cred, 0, sizeof(virConnectCredential));
-
- if (virAsprintf(&prompt, "Enter %s password for %s", username,
- hostname) < 0) {
- return NULL;
- }
-
- for (ncred = 0; ncred < auth->ncredtype; ncred++) {
- if (auth->credtype[ncred] != VIR_CRED_PASSPHRASE &&
- auth->credtype[ncred] != VIR_CRED_NOECHOPROMPT) {
- continue;
- }
-
- cred.type = auth->credtype[ncred];
- cred.prompt = prompt;
- cred.challenge = hostname;
- cred.defresult = NULL;
- cred.result = NULL;
- cred.resultlen = 0;
-
- if ((*(auth->cb))(&cred, 1, auth->cbdata) < 0) {
- VIR_FREE(cred.result);
- }
-
- break;
- }
-
- VIR_FREE(prompt);
-
- return cred.result;
-}
-
-
-
int
esxUtil_ParseQuery(xmlURIPtr uri, char **transport, char **vCenter,
int *noVerify, int *autoAnswer)
diff --git a/src/esx/esx_util.h b/src/esx/esx_util.h
index b5cb419..f4f971c 100644
--- a/src/esx/esx_util.h
+++ b/src/esx/esx_util.h
@@ -28,13 +28,6 @@
# include "internal.h"
# include "conf.h"
-char *esxUtil_RequestUsername(virConnectAuthPtr auth,
- const char *defaultUsername,
- const char *hostname);
-
-char *esxUtil_RequestPassword(virConnectAuthPtr auth, const char *username,
- const char *hostname);
-
int esxUtil_ParseQuery(xmlURIPtr uri, char **transport, char **vCenter,
int *noVerify, int *autoAnswer);
diff --git a/src/util/util.c b/src/util/util.c
index 87b0714..4292f01 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -2676,3 +2676,92 @@ int virBuildPathInternal(char **path, ...)
return ret;
}
+
+
+
+char *
+virRequestUsername(virConnectAuthPtr auth, const char *defaultUsername,
+ const char *hostname)
+{
+ unsigned int ncred;
+ virConnectCredential cred;
+ char *prompt;
+
+ memset(&cred, 0, sizeof (virConnectCredential));
+
+ if (defaultUsername != NULL) {
+ if (virAsprintf(&prompt, _("Enter username for %s [%s]"), hostname,
+ defaultUsername) < 0) {
+ return NULL;
+ }
+ } else {
+ if (virAsprintf(&prompt, _("Enter username for %s"), hostname) < 0) {
+ return NULL;
+ }
+ }
+
+ for (ncred = 0; ncred < auth->ncredtype; ncred++) {
+ if (auth->credtype[ncred] != VIR_CRED_AUTHNAME) {
+ continue;
+ }
+
+ cred.type = VIR_CRED_AUTHNAME;
+ cred.prompt = prompt;
+ cred.challenge = hostname;
+ cred.defresult = defaultUsername;
+ cred.result = NULL;
+ cred.resultlen = 0;
+
+ if ((*(auth->cb))(&cred, 1, auth->cbdata) < 0) {
+ VIR_FREE(cred.result);
+ }
+
+ break;
+ }
+
+ VIR_FREE(prompt);
+
+ return cred.result;
+}
+
+
+
+char *
+virRequestPassword(virConnectAuthPtr auth, const char *username,
+ const char *hostname)
+{
+ unsigned int ncred;
+ virConnectCredential cred;
+ char *prompt;
+
+ memset(&cred, 0, sizeof (virConnectCredential));
+
+ if (virAsprintf(&prompt, _("Enter %s password for %s"), username,
+ hostname) < 0) {
+ return NULL;
+ }
+
+ for (ncred = 0; ncred < auth->ncredtype; ncred++) {
+ if (auth->credtype[ncred] != VIR_CRED_PASSPHRASE &&
+ auth->credtype[ncred] != VIR_CRED_NOECHOPROMPT) {
+ continue;
+ }
+
+ cred.type = auth->credtype[ncred];
+ cred.prompt = prompt;
+ cred.challenge = hostname;
+ cred.defresult = NULL;
+ cred.result = NULL;
+ cred.resultlen = 0;
+
+ if ((*(auth->cb))(&cred, 1, auth->cbdata) < 0) {
+ VIR_FREE(cred.result);
+ }
+
+ break;
+ }
+
+ VIR_FREE(prompt);
+
+ return cred.result;
+}
diff --git a/src/util/util.h b/src/util/util.h
index e8fc565..9796e0a 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -268,4 +268,9 @@ void virFileWaitForDevices(void);
# define virBuildPath(path, ...) virBuildPathInternal(path, __VA_ARGS__, NULL)
int virBuildPathInternal(char **path, ...) ATTRIBUTE_SENTINEL;
+char *virRequestUsername(virConnectAuthPtr auth, const char *defaultUsername,
+ const char *hostname);
+char *virRequestPassword(virConnectAuthPtr auth, const char *username,
+ const char *hostname);
+
#endif /* __VIR_UTIL_H__ */
--
1.6.3.3
14 years, 8 months
[libvirt] [PATCH] Fix syntax-check errors
by Jiri Denemark
Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
src/nodeinfo.c | 4 ++--
src/xenapi/xenapi_driver.c | 27 ++++++++++++++---------------
src/xenapi/xenapi_utils.c | 4 ++--
3 files changed, 17 insertions(+), 18 deletions(-)
Actually, one more error is reported by syntax-check, but it's already fixed
in "xenapi: Request a username if there is non in the URI" patch sent by
Matthias yesterday:
src/xenapi/xenapi_driver.c: if (passwd) VIR_FREE(passwd)
diff --git a/src/nodeinfo.c b/src/nodeinfo.c
index bf57517..4858e71 100644
--- a/src/nodeinfo.c
+++ b/src/nodeinfo.c
@@ -162,10 +162,10 @@ int linuxNodeInfoCPUPopulate(virConnectPtr conn, FILE *cpuinfo,
nodeinfo->cores = 1;
nodeinfo->nodes = 1;
-#if HAVE_NUMACTL
+# if HAVE_NUMACTL
if (numa_available() >= 0)
nodeinfo->nodes = numa_max_node() + 1;
-#endif
+# endif
/* NB: It is impossible to fill our nodes, since cpuinfo
* has no knowledge of NUMA nodes */
diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c
index 8d5c8bb..ad77068 100644
--- a/src/xenapi/xenapi_driver.c
+++ b/src/xenapi/xenapi_driver.c
@@ -1716,11 +1716,11 @@ write_func(void *ptr, size_t size, size_t nmemb, void *comms_)
{
xen_comms *comms = comms_;
size_t n = size * nmemb;
- #ifdef PRINT_XML
- printf("\n\n---Result from server -----------------------\n");
- printf("%s\n",((char*) ptr));
- fflush(stdout);
- #endif
+#ifdef PRINT_XML
+ printf("\n\n---Result from server -----------------------\n");
+ printf("%s\n",((char*) ptr));
+ fflush(stdout);
+#endif
return (size_t) (comms->func(ptr, n, comms->handle) ? n : 0);
}
@@ -1734,12 +1734,11 @@ call_func(const void *data, size_t len, void *user_handle,
{
//(void)user_handle;
struct _xenapiPrivate *priv = (struct _xenapiPrivate *)user_handle;
- #ifdef PRINT_XML
-
- printf("\n\n---Data to server: -----------------------\n");
- printf("%s\n",((char*) data));
- fflush(stdout);
- #endif
+#ifdef PRINT_XML
+ printf("\n\n---Data to server: -----------------------\n");
+ printf("%s\n",((char*) data));
+ fflush(stdout);
+#endif
CURL *curl = curl_easy_init();
if (!curl) {
return -1;
@@ -1750,9 +1749,9 @@ call_func(const void *data, size_t len, void *user_handle,
};
curl_easy_setopt(curl, CURLOPT_URL, priv->url);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
- #ifdef CURLOPT_MUTE
- curl_easy_setopt(curl, CURLOPT_MUTE, 1);
- #endif
+#ifdef CURLOPT_MUTE
+ curl_easy_setopt(curl, CURLOPT_MUTE, 1);
+#endif
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_func);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &comms);
curl_easy_setopt(curl, CURLOPT_POST, 1);
diff --git a/src/xenapi/xenapi_utils.c b/src/xenapi/xenapi_utils.c
index 4b9a6d8..59edbf3 100644
--- a/src/xenapi/xenapi_utils.c
+++ b/src/xenapi/xenapi_utils.c
@@ -548,7 +548,7 @@ createVMRecordFromXml (virConnectPtr conn, virDomainDefPtr def,
char macStr[VIR_MAC_STRING_BUFLEN];
virFormatMacAddr(def->nets[i]->mac, macStr);
if (!(mac = strdup(macStr))) {
- if (bridge) VIR_FREE(bridge);
+ VIR_FREE(bridge);
goto error_cleanup;
}
}
@@ -559,7 +559,7 @@ createVMRecordFromXml (virConnectPtr conn, virDomainDefPtr def,
VIR_FREE(bridge);
device_number++;
}
- if (bridge) VIR_FREE(bridge);
+ VIR_FREE(bridge);
}
}
return 0;
--
1.7.0.2
14 years, 8 months
[libvirt] [PATCH] Fix error messages in qemu text monitor
by Jiri Denemark
Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
src/qemu/qemu_monitor_text.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c
index e629c6b..b7c41a1 100644
--- a/src/qemu/qemu_monitor_text.c
+++ b/src/qemu/qemu_monitor_text.c
@@ -939,7 +939,7 @@ static int qemuMonitorTextSaveMemory(qemuMonitorPtr mon,
if (qemuMonitorCommand(mon, cmd, &reply) < 0) {
qemuReportError(VIR_ERR_OPERATION_FAILED,
- _("could save memory region to '%s'"), path);
+ _("could not save memory region to '%s'"), path);
goto cleanup;
}
@@ -986,7 +986,7 @@ int qemuMonitorTextSetMigrationSpeed(qemuMonitorPtr mon,
if (qemuMonitorCommand(mon, cmd, &info) < 0) {
qemuReportError(VIR_ERR_OPERATION_FAILED,
- "%s", _("could restrict migration speed"));
+ "%s", _("could not restrict migration speed"));
goto cleanup;
}
--
1.7.0.2
14 years, 8 months
Re: [libvirt] [PATCH 1/2] Addition of XenAPI support to libvirt
by Sharadha Prabhakar (3P)
Patch includes
1) Modification of xenapiDomainGetOSType
1) global url and SSL flags removed and placed in private driver struct.
2) SSL verify on url parsed using function similar to the one in ESX.
3) mapDomainPinVcpu updated in xenapi_utils.c
diff -Nur ./libvirt_org/src/xenapi/xenapi_driver.c ./libvirt/src/xenapi/xenapi_driver.c
--- ./libvirt_org/src/xenapi/xenapi_driver.c 1970-01-01 01:00:00.000000000 +0100
+++ ./libvirt/src/xenapi/xenapi_driver.c 2010-03-04 16:59:01.000000000 +0000
@@ -0,0 +1,1738 @@
+
+/*
+ * xenapi_driver.c: Xen API driver.
+ * Copyright (C) 2009 Citrix Ltd.
+ * Sharadha Prabhakar <sharadha.prabhakar(a)citrix.com>
+*/
+
+#include <config.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <libxml/uri.h>
+#include <xen_internal.h>
+#include <libxml/parser.h>
+#include <curl/curl.h>
+#include <xen/api/xen_common.h>
+#include <xen/api/xen_vm.h>
+#include <xen/api/xen_vm.h>
+#include <xen/api/xen_all.h>
+#include <xen/api/xen_vm_metrics.h>
+
+#include "libvirt_internal.h"
+#include "libvirt/libvirt.h"
+#include "domain_conf.h"
+#include "virterror_internal.h"
+#include "datatypes.h"
+#include "xenapi_driver.h"
+#include "xenapi_driver_private.h"
+#include "util.h"
+#include "uuid.h"
+#include "memory.h"
+#include "driver.h"
+#include "buf.h"
+#include "xenapi_utils.h"
+
+
+/*
+*getCapsObject
+*
+*Build the capabilities of the hypervisor
+*Return virCapsPtr on success or NULL on failure
+*/
+static virCapsPtr
+getCapsObject (void)
+{
+ virCapsPtr caps = virCapabilitiesNew("x86_64", 0, 0);
+ if (!caps) {
+ virReportOOMError();
+ return NULL;
+ }
+ virCapsGuestPtr guest1 = virCapabilitiesAddGuest(caps, "hvm", "x86_64", 0, "", "", 0, NULL);
+ if (!guest1)
+ goto error_cleanup;
+ virCapsGuestDomainPtr domain1 = virCapabilitiesAddGuestDomain(guest1, "xen", "", "", 0, NULL);
+ if (!domain1)
+ goto error_cleanup;
+ virCapsGuestPtr guest2 = virCapabilitiesAddGuest(caps, "xen", "x86_64", 0, "", "", 0, NULL);
+ if (!guest2)
+ goto error_cleanup;
+ virCapsGuestDomainPtr domain2 = virCapabilitiesAddGuestDomain(guest2, "xen", "", "", 0, NULL);
+ if (!domain2)
+ goto error_cleanup;
+
+ return caps;
+
+ error_cleanup:
+ virCapabilitiesFree(caps);
+ return NULL;
+}
+
+/*
+*XenapiOpen
+*
+*Authenticates and creates a session with the server
+*Return VIR_DRV_OPEN_SUCCESS on success, else VIR_DRV_OPEN_ERROR
+*/
+static virDrvOpenStatus
+xenapiOpen (virConnectPtr conn, virConnectAuthPtr auth , int flags ATTRIBUTE_UNUSED)
+{
+ char *passwd;
+ xen_session *session;
+ struct _xenapiPrivate *privP;
+ int noVerify=0;
+
+ if (!STRCASEEQ(conn->uri->scheme,"XenAPI")) {
+ xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED ,"Check URI format: 'XenAPI://user@server'");
+ return VIR_DRV_OPEN_DECLINED;
+ }
+ if (conn->uri->server==NULL) {
+ xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED ,"Server name not in URI");
+ return VIR_DRV_OPEN_ERROR;
+ }
+ if (auth) {
+ passwd = xenapiUtil_RequestPassword(auth,conn->uri->user,conn->uri->server);
+ } else {
+ xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED ,"Authentication Credentials not found");
+ return VIR_DRV_OPEN_ERROR;
+ }
+ if (!passwd && !conn->uri->user) {
+ xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED ,"Username/Password not valid");
+ return VIR_DRV_OPEN_ERROR;
+ }
+ if (VIR_ALLOC(privP) < 0) {
+ virReportOOMError();
+ return VIR_DRV_OPEN_ERROR;
+ }
+ if (virAsprintf(&(privP->url),"https://%s",conn->uri->server) < 0) {
+ virReportOOMError();
+ return VIR_DRV_OPEN_ERROR;
+ }
+ privP->SSLflag=2;
+ xenapiUtil_ParseQuery(conn, conn->uri,&noVerify);
+ if (noVerify==1) privP->SSLflag=0;
+ xmlInitParser();
+ xmlKeepBlanksDefault(0);
+ xen_init();
+ curl_global_init(CURL_GLOBAL_ALL);
+
+ session = xen_session_login_with_password (call_func, (void *)privP, conn->uri->user, "xenroot", xen_api_latest_version);
+
+ if ( session && session->ok ) {
+ privP->session = session;
+ virCapsPtr caps = getCapsObject();
+ if (caps)
+ privP->caps = caps;
+ conn->privateData = privP;
+ return VIR_DRV_OPEN_SUCCESS;
+ } else {
+ xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED ,"");
+ VIR_FREE(privP);
+ return VIR_DRV_OPEN_ERROR;
+ }
+}
+
+/*
+* xenapiClose:
+*
+* Returns 0 on successful session logout
+*
+*/
+static int
+xenapiClose (virConnectPtr conn)
+{
+ xen_session_logout(((struct _xenapiPrivate *)(conn->privateData))->session);
+ virCapabilitiesFree(((struct _xenapiPrivate *)(conn->privateData))->caps);
+ VIR_FREE(((struct _xenapiPrivate *)(conn->privateData))->url);
+ VIR_FREE(conn->privateData);
+ return 0;
+}
+
+/*
+*
+* xenapiSupportsFeature
+*
+* Returns 0
+*/
+static int
+xenapiSupportsFeature (virConnectPtr conn ATTRIBUTE_UNUSED, int feature)
+{
+ switch (feature) {
+ case VIR_DRV_FEATURE_MIGRATION_V2:
+ case VIR_DRV_FEATURE_MIGRATION_P2P:
+ default:
+ return 0;
+ }
+}
+
+/*
+* xenapiType:
+*
+*
+*Returns name of the driver
+*/
+static const char *
+xenapiType (virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+ return "XenAPI";
+}
+
+
+/*
+* xenapiGetVersion:
+*
+* Gets the version of XenAPI
+*
+*/
+static int
+xenapiGetVersion (virConnectPtr conn, unsigned long *hvVer)
+{
+ xen_host host;
+ xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+ xen_string_string_map *result=NULL;
+ if (!(xen_session_get_this_host(session, &host,session))) {
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR ,NULL);
+ return -1;
+ }
+ if (!(xen_host_get_software_version(session, &result, host))) {
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR ,NULL);
+ xen_host_free(host);
+ return -1;
+ }
+ xen_host_free(host);
+ if (result && result->size>0) {
+ int i;
+ char *version=NULL;
+ for (i=0; i<result->size; i++) {
+ if (STREQ(result->contents[i].key,"xen")) {
+ if (!(version = strdup(result->contents[i].val))) {
+ xen_string_string_map_free(result);
+ virReportOOMError();
+ return -1;
+ }
+ break;
+ }
+ }
+ if (version) {
+ unsigned long major=0,minor=0,release=0;
+ if (sscanf(version,"%ld.%ld.%ld",&major,&minor,&release)!=3) {
+ virReportOOMError();
+ xen_string_string_map_free(result);
+ VIR_FREE(version);
+ return -1;
+ }
+ *hvVer = major * 1000000 + minor * 1000 + release;
+ VIR_FREE(version);
+ xen_string_string_map_free(result);
+ return 0;
+ }
+ }
+ return -1;
+}
+
+
+/*
+* xenapiGetHostname:
+*
+*
+* Returns the hostname on success, or NULL on failure
+*/
+static char *
+xenapiGetHostname (virConnectPtr conn)
+{
+ char *result=NULL;
+ xen_host host;
+ xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+ if (!(xen_session_get_this_host(session, &host, session))) {
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR ,NULL);
+ return NULL;
+ }
+ if (!(xen_host_get_hostname(session, &result, host)))
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR ,NULL);
+ xen_host_free(host);
+ return result;
+}
+
+
+/*
+* xenapiGetMaxVcpus:
+*
+*
+* Returns a hardcoded value for Maximum VCPUS
+*/
+static int
+xenapiGetMaxVcpus (virConnectPtr conn ATTRIBUTE_UNUSED, const char *type ATTRIBUTE_UNUSED)
+{
+ /* this is hardcoded for simplicity and set to a resonable value compared
+ to the actual value */
+ return 16;
+}
+
+
+/*
+* xenapiNodeGetInfo:
+*
+*
+* Returns Node details on success or else -1
+*/
+static int
+xenapiNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info)
+{
+ int64_t memory,mhz;
+ xen_host_cpu_set *host_cpu_set;
+ xen_host_cpu host_cpu;
+ xen_host_metrics_set *xen_met_set;
+ char *modelname;
+ xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+ info->nodes = 1;
+ info->threads = 1;
+ info->sockets = 1;
+
+ if (xen_host_metrics_get_all(session, &xen_met_set)) {
+ xen_host_metrics_get_memory_total(session, &memory, xen_met_set->contents[0]);
+ info->memory = (unsigned long)(memory/1024);
+ xen_host_metrics_set_free(xen_met_set);
+ } else {
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR ,"Unable to get host metric Information");
+ return -1;
+ }
+ if (xen_host_cpu_get_all(session, &host_cpu_set)) {
+ host_cpu = host_cpu_set->contents[0];
+ xen_host_cpu_get_modelname(session, &modelname, host_cpu);
+ if (!virStrncpy(info->model,modelname,LIBVIRT_MODELNAME_LEN-1,LIBVIRT_MODELNAME_LEN)){
+ virReportOOMError();
+ xen_host_cpu_set_free(host_cpu_set);
+ VIR_FREE(modelname);
+ return -1;
+ }
+ xen_host_cpu_get_speed(session, &mhz, host_cpu);
+ info->mhz = (unsigned long)mhz;
+ info->cpus = host_cpu_set->size;
+ info->cores = host_cpu_set->size;
+
+ xen_host_cpu_set_free(host_cpu_set);
+ VIR_FREE(modelname);
+ return 0;
+ }
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR ,"Unable to get Host CPU set");
+ return -1;
+}
+
+/*
+* xenapiGetCapabilities:
+*
+*
+* Returns capabilities as an XML string
+*/
+static char *
+xenapiGetCapabilities (virConnectPtr conn)
+{
+ virCapsPtr caps = ((struct _xenapiPrivate *)(conn->privateData))->caps;
+ if (caps) {
+ char *xml = virCapabilitiesFormatXML(caps);
+ return xml;
+ }
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR ,"Capabilities not available");
+ return NULL;
+}
+
+
+/*
+* xenapiListDomains
+*
+* Collects the list of active domains, and store their ID in @maxids
+* Returns the number of domain found or -1 in case of error
+*/
+static int
+xenapiListDomains (virConnectPtr conn, int *ids, int maxids)
+{
+ /* vm.list */
+ xen_host host;
+ xen_vm_set *result=NULL;
+ xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+ if (xen_session_get_this_host(session, &host, session)) {
+ xen_host_get_resident_vms(session, &result, host);
+ xen_host_free(host);
+ } else
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR ,NULL);
+
+ if (result != NULL) {
+ int i;
+ for ( i=0; (i < (result->size)) && (i<maxids) ; i++ ) {
+ int64_t t0;
+ xen_vm_get_domid(session, &t0, result->contents[i]);
+ ids[i] = (int)(t0 & 0xffffffff);
+ }
+ xen_vm_set_free(result);
+ return i;
+ }
+ return -1;
+}
+
+/*
+* xenapiNumOfDomains
+*
+*
+* Returns the number of domains found or -1 in case of error
+*/
+static int
+xenapiNumOfDomains (virConnectPtr conn)
+{
+ /* #(vm.list) */
+ xen_vm_set *result=NULL;
+ xen_host host=NULL;
+ int numDomains=-1;
+ xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+
+ xen_session_get_this_host(session, &host, session);
+ if ( host!=NULL ) {
+ xen_host_get_resident_vms(session, &result, host);
+ if ( result != NULL) {
+ numDomains = result->size;
+ xen_vm_set_free(result);
+ }
+ xen_host_free(host);
+ }
+ if (!(session->ok))
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR ,NULL);
+ return numDomains;
+}
+
+/*
+* xenapiDomainCreateXML
+*
+* Launches a new domain based on the XML description
+* Returns the domain pointer or NULL in case of error
+*/
+static virDomainPtr
+xenapiDomainCreateXML (virConnectPtr conn,
+ const char *xmlDesc, ATTRIBUTE_UNUSED unsigned int flags)
+{
+ xen_vm_record *record=NULL;
+ xen_vm vm=NULL;
+ virDomainPtr domP=NULL;
+ xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+ virCapsPtr caps = ((struct _xenapiPrivate *)(conn->privateData))->caps;
+ if (!caps)
+ return NULL;
+
+ virDomainDefPtr defPtr = virDomainDefParseString(caps, xmlDesc, flags);
+ createVMRecordFromXml(conn, defPtr, &record, &vm);
+ virDomainDefFree(defPtr);
+ if (record) {
+ unsigned char raw_uuid[VIR_UUID_BUFLEN];
+ virUUIDParse(record->uuid,raw_uuid);
+ if (vm) {
+ if (xen_vm_start(session, vm, false, false)) {
+ domP = virGetDomain(conn, record->name_label, raw_uuid);
+ if (!domP) {
+ xen_vm_record_free(record);
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Domain Pointer is invalid");
+ return domP;
+ }
+ domP->id = record->domid;
+ xen_vm_free(vm);
+ }
+ else
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
+ }
+ xen_vm_record_free(record);
+ }
+ else
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
+ return domP;
+}
+
+/*
+* xenapiDomainLookupByID
+*
+*
+* Returns a valid domain pointer of the domain with ID same as the one passed
+* or NULL in case of error
+*/
+static virDomainPtr
+xenapiDomainLookupByID (virConnectPtr conn, int id)
+{
+ int i;
+ int64_t domID;
+ char *uuid;
+ xen_host host;
+ xen_vm_set *result;
+ xen_vm_record *record;
+ unsigned char raw_uuid[VIR_UUID_BUFLEN];
+ virDomainPtr domP=NULL;
+ xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+
+ xen_session_get_this_host(session, &host, session);
+ if (host!=NULL && session->ok) {
+ xen_host_get_resident_vms(session, &result, host);
+ if ( result !=NULL ) {
+ for( i=0; i < (result->size); i++) {
+ xen_vm_get_domid(session, &domID, result->contents[i]);
+ if ( domID == id ) {
+ xen_vm_get_record(session, &record, result->contents[i]);
+ xen_vm_get_uuid(session, &uuid, result->contents[i]);
+ virUUIDParse(uuid,raw_uuid);
+ domP = virGetDomain(conn, record->name_label, raw_uuid);
+ if (domP) {
+ int64_t domid=-1;
+ xen_vm_get_domid(session, &domid, result->contents[i]);
+ domP->id = domid;
+ } else {
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR , "Domain Pointer not valid");
+ domP = NULL;
+ }
+ xen_uuid_free(uuid);
+ xen_vm_record_free(record);
+ break;
+ }
+ }
+ xen_vm_set_free(result);
+ } else {
+ xenapiSessionErrorHandler(conn, VIR_ERR_NO_DOMAIN ,NULL);
+ }
+ xen_host_free(host);
+ } else {
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR ,NULL);
+ }
+ return domP;
+}
+
+/*
+* xenapiDomainLookupByUUID
+*
+* Returns the domain pointer of domain with matching UUID
+* or -1 in case of error
+*/
+static virDomainPtr
+xenapiDomainLookupByUUID (virConnectPtr conn,
+ const unsigned char *uuid)
+{
+ /* vm.get_by_uuid */
+ xen_vm vm;
+ xen_vm_record *record;
+ char uuidStr[VIR_UUID_STRING_BUFLEN];
+ virDomainPtr domP=NULL;
+ xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+ virUUIDFormat(uuid,uuidStr);
+ if (xen_vm_get_by_uuid(session, &vm, uuidStr)) {
+ xen_vm_get_record(session, &record, vm);
+ if (record != NULL) {
+ domP = virGetDomain(conn, record->name_label, uuid);
+ if (!domP) {
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR , "Domain Pointer not valid");
+ domP=NULL;
+ } else {
+ domP->id = record->domid;
+ }
+ xen_vm_record_free(record);
+ }
+ else
+ xenapiSessionErrorHandler(conn, VIR_ERR_NO_DOMAIN ,NULL);
+ xen_vm_free(vm);
+ } else
+ xenapiSessionErrorHandler(conn, VIR_ERR_NO_DOMAIN ,NULL);
+ return domP;
+}
+
+/*
+* xenapiDomainLookupByName
+*
+* Returns the domain pointer of domain with matching name
+* or -1 in case of error
+*/
+static virDomainPtr
+xenapiDomainLookupByName (virConnectPtr conn,
+ const char *name)
+{
+ /* vm.get_by_name_label */
+ xen_vm_set *vms=NULL;
+ xen_vm vm;
+ char *uuid=NULL;
+ unsigned char raw_uuid[VIR_UUID_BUFLEN];
+ virDomainPtr domP=NULL;
+ xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+ if (xen_vm_get_by_name_label(session, &vms, (char *)name)) {
+ if (vms->size!=1) {
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique");
+ xen_vm_set_free(vms);
+ return NULL;
+ }
+ vm = vms->contents[0];
+ xen_vm_get_uuid(session, &uuid, vm);
+ if (uuid!=NULL) {
+ virUUIDParse(uuid,raw_uuid);
+ domP = virGetDomain(conn, name, raw_uuid);
+ if (domP != NULL) {
+ int64_t domid=-1;
+ xen_vm_get_domid(session, &domid, vm);
+ domP->id = domid;
+ xen_uuid_free(uuid);
+ xen_vm_set_free(vms);
+ return domP;
+ } else {
+ xen_uuid_free(uuid);
+ xen_vm_set_free(vms);
+ if (!(session->ok))
+ xenapiSessionErrorHandler(conn, VIR_ERR_NO_DOMAIN, NULL);
+ return NULL;
+ }
+ }
+ }
+ xenapiSessionErrorHandler(conn, VIR_ERR_NO_DOMAIN, NULL);
+ return NULL;
+}
+
+/*
+* xenapiDomainSuspend
+*
+* a VM is paused
+* Returns 0 on success or -1 in case of error
+*/
+static int
+xenapiDomainSuspend (virDomainPtr dom)
+{
+ /* vm.pause() */
+ xen_vm vm;
+ xen_vm_set *vms;
+ xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+ if (!xen_vm_get_by_name_label(session, &vms, dom->name)) {
+ xenapiSessionErrorHandler(dom->conn,VIR_ERR_NO_DOMAIN,NULL);
+ return -1;
+ }
+ if (vms->size!=1) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique");
+ xen_vm_set_free(vms);
+ return -1;
+ } else {
+ vm = vms->contents[0];
+ if (!xen_vm_pause(session, vm)) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+ xen_vm_set_free(vms);
+ return -1;
+ }
+ xen_vm_set_free(vms);
+ }
+ return 0;
+}
+
+/*
+* xenapiDomainResume
+*
+* Resumes a VM
+* Returns 0 on success or -1 in case of error
+*/
+static int
+xenapiDomainResume (virDomainPtr dom)
+{
+ /* vm.unpause() */
+ xen_vm vm;
+ xen_vm_set *vms;
+ xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+ if (!xen_vm_get_by_name_label(session, &vms, dom->name)) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
+ return -1;
+ }
+ if (vms->size!=1) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique");
+ xen_vm_set_free(vms);
+ return -1;
+ } else {
+ vm = vms->contents[0];
+ if (!xen_vm_unpause(session, vm)) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+ xen_vm_set_free(vms);
+ return -1;
+ }
+ xen_vm_set_free(vms);
+ }
+ return 0;
+}
+
+/*
+* xenapiDomainShutdown
+*
+* shutsdown a VM
+* Returns 0 on success or -1 in case of error
+*/
+static int
+xenapiDomainShutdown (virDomainPtr dom)
+{
+ /* vm.clean_shutdown */
+ xen_vm vm;
+ xen_vm_set *vms;
+ xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+ if(!xen_vm_get_by_name_label(session, &vms, dom->name)) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
+ return -1;
+ }
+ if (vms->size!=1) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique");
+ xen_vm_set_free(vms);
+ return -1;
+ } else {
+ vm = vms->contents[0];
+ if (!xen_vm_clean_shutdown(session, vm)) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+ xen_vm_set_free(vms);
+ return -1;
+ }
+ xen_vm_set_free(vms);
+ }
+ return 0;
+}
+
+/*
+* xenapiDomainReboot
+*
+* Reboots a VM
+* Returns 0 on success or -1 in case of error
+*/
+static int
+xenapiDomainReboot (virDomainPtr dom, unsigned int flags ATTRIBUTE_UNUSED)
+{
+ /* vm.clean_reboot */
+ xen_vm vm;
+ struct xen_vm_set *vms;
+ xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+ if (!xen_vm_get_by_name_label(session, &vms, dom->name)) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
+ return -1;
+ }
+ if (vms->size!=1) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique");
+ xen_vm_set_free(vms);
+ return -1;
+ }
+ vm = vms->contents[0];
+ if (!xen_vm_clean_reboot(session, vm)) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+ xen_vm_set_free(vms);
+ return -1;
+ }
+ xen_vm_set_free(vms);
+ return 0;
+}
+
+/*
+* xenapiDomaindestroy
+*
+* A VM is hard shutdown
+* Returns 0 on success or -1 in case of error
+*/
+static int
+xenapiDomainDestroy (virDomainPtr dom)
+{
+ /* vm.hard_shutdown */
+ xen_vm vm;
+ struct xen_vm_set *vms;
+ xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+ if (!xen_vm_get_by_name_label(session, &vms, dom->name)) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
+ return -1;
+ }
+ if (vms->size!=1) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique");
+ xen_vm_set_free(vms);
+ return -1;
+ }
+ vm = vms->contents[0];
+ if (!xen_vm_hard_shutdown(session, vm)) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+ xen_vm_set_free(vms);
+ return -1;
+ }
+ xen_vm_set_free(vms);
+ return 0;
+}
+
+/*
+* xenapiDomainGetOSType
+*
+*
+* Returns OS version on success or NULL in case of error
+*/
+static char *
+xenapiDomainGetOSType (virDomainPtr dom)
+{
+ xen_vm vm=NULL;
+ xen_vm_set *vms;
+ char *ostype = NULL;
+ char *boot_policy=NULL;
+ xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+
+ if (!xen_vm_get_by_name_label(session, &vms, dom->name)){
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
+ return NULL;
+ }
+ if (vms->size!=1) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique");
+ xen_vm_set_free(vms);
+ return NULL;
+ }
+ vm = vms->contents[0];
+ if(!xen_vm_get_hvm_boot_policy(session, &boot_policy, vm)) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+ goto cleanup;
+ }
+ if (!(ostype=(STREQ(boot_policy,"BIOS order")?strdup("hvm"):strdup("xen"))))
+ virReportOOMError();
+ VIR_FREE(boot_policy);
+ cleanup:
+ xen_vm_set_free(vms);
+ return ostype;
+}
+/*
+* xenapiDomainGetMaxMemory
+*
+* Returns maximum static memory for VM on success
+* or 0 in case of error
+*/
+static unsigned long
+xenapiDomainGetMaxMemory (virDomainPtr dom)
+{
+ int64_t mem_static_max=0;
+ xen_vm vm;
+ xen_vm_set *vms;
+ xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+ if (xen_vm_get_by_name_label(session, &vms, dom->name)) {
+ if (vms->size!=1) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique");
+ xen_vm_set_free(vms);
+ return 0;
+ }
+ vm = vms->contents[0];
+ xen_vm_get_memory_static_max(session, &mem_static_max, vm);
+ xen_vm_set_free(vms);
+ return (unsigned long)(mem_static_max/1024);
+ } else {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
+ return 0;
+ }
+}
+
+/*
+* xenapiDomainSetMaxMemory
+*
+* Sets maximum static memory for VM on success
+* Returns 0 on success or -1 in case of error
+*/
+static int
+xenapiDomainSetMaxMemory (virDomainPtr dom, unsigned long memory)
+{
+ /* vm.set_memory_static_max */
+ xen_vm vm;
+ struct xen_vm_set *vms;
+ xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+ if (xen_vm_get_by_name_label(session, &vms, dom->name)) {
+ if (vms->size!=1) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique");
+ xen_vm_set_free(vms);
+ return -1;
+ }
+ vm = vms->contents[0];
+ if (!(xen_vm_set_memory_static_max(session, vm, memory))) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+ xen_vm_set_free(vms);
+ return -1;
+ }
+ xen_vm_set_free(vms);
+ } else {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+* xenapiDomainGetInfo:
+*
+* Fills a structure with domain information
+* Returns 0 on success or -1 in case of error
+*/
+static int
+xenapiDomainGetInfo (virDomainPtr dom, virDomainInfoPtr info)
+{
+ int64_t maxmem=0,memory=0,vcpu=0;
+ xen_vm vm;
+ xen_vm_record *record;
+ xen_vm_set *vms;
+ xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+ info->cpuTime = 0; /* CPU time is not advertised */
+ if (xen_vm_get_by_name_label(session, &vms, dom->name)) {
+ if (vms->size!=1) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique");
+ xen_vm_set_free(vms);
+ return -1;
+ }
+ vm = vms->contents[0];
+ xen_vm_get_memory_static_max(session, &maxmem, vm);
+ info->maxMem = (maxmem/1024);
+ enum xen_vm_power_state state = XEN_VM_POWER_STATE_UNKNOWN;
+ xen_vm_get_power_state(session, &state, vm);
+ info->state = mapPowerState(state);
+ xen_vm_get_record(session, &record, vm);
+ if (record!=NULL) {
+ xen_vm_metrics_get_memory_actual(session, &memory, record->metrics->u.handle);
+ info->memory = (memory/1024);
+ xen_vm_record_free(record);
+ }
+ xen_vm_get_vcpus_max(session, &vcpu, vm);
+ info->nrVirtCpu = vcpu;
+ xen_vm_set_free(vms);
+ return 0;
+ }
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
+ return -1;
+}
+
+
+/*
+* xenapiDomainSetVcpus
+*
+* Sets the VCPUs on the domain
+* Return 0 on success or -1 in case of error
+*/
+static int
+xenapiDomainSetVcpus (virDomainPtr dom, unsigned int nvcpus)
+{
+
+ /* vm.set_vcpus_max */
+ xen_vm vm;
+ xen_vm_set *vms;
+ xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+ if (xen_vm_get_by_name_label(session, &vms, dom->name)) {
+ if (vms->size!=1) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique");
+ xen_vm_set_free(vms);
+ return -1;
+ }
+ vm = vms->contents[0];
+ if (xen_vm_set_vcpus_number_live(session, vm, (int64_t)nvcpus)) {
+ xen_vm_set_free(vms);
+ return 0;
+ }
+ }
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
+ return -1;
+}
+
+/*
+* xenapiDomainPinVcpu
+*
+* Dynamically change the real CPUs which can be allocated to a virtual CPU
+* Returns 0 on success or -1 in case of error
+*/
+static int
+xenapiDomainPinVcpu (virDomainPtr dom, unsigned int vcpu ATTRIBUTE_UNUSED,
+ unsigned char *cpumap, int maplen)
+{
+ char *value=NULL;
+ xen_vm vm;
+ xen_vm_set *vms;
+ xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+ if (xen_vm_get_by_name_label(session, &vms, dom->name)) {
+ if (vms->size!=1) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique");
+ xen_vm_set_free(vms);
+ return -1;
+ }
+ vm = vms->contents[0];
+ if ((value = mapDomainPinVcpu(cpumap, maplen))) {
+ xen_vm_remove_from_vcpus_params(session, vm, (char *)"mask");
+ if (xen_vm_add_to_vcpus_params(session, vm, (char *)"mask", value)) {
+ xen_vm_set_free(vms);
+ VIR_FREE(value);
+ return 0;
+ }
+ VIR_FREE(value);
+ } else {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+ xen_vm_set_free(vms);
+ return -1;
+ }
+ }
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+ return -1;
+}
+
+/*
+* xenapiDomainGetVcpus
+*
+* Gets Vcpu information
+* Return number of structures filled on success or -1 in case of error
+*/
+static int
+xenapiDomainGetVcpus (virDomainPtr dom,
+ virVcpuInfoPtr info, int maxinfo,
+ unsigned char *cpumaps, int maplen)
+{
+
+ xen_vm_set *vms=NULL;
+ xen_vm vm=NULL;
+ xen_string_string_map *vcpu_params=NULL;
+ int nvcpus=0,cpus=0,i;
+ virDomainInfoPtr domInfo;
+ virNodeInfo nodeInfo;
+ virVcpuInfoPtr ifptr;
+ xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+ char *mask=NULL;
+ if((cpumaps!=NULL) && (maplen < 1))
+ return -1;
+ if (VIR_ALLOC(domInfo)<0) {
+ virReportOOMError();
+ return -1;
+ }
+ if (virDomainGetInfo(dom,domInfo)==0) {
+ nvcpus = domInfo->nrVirtCpu;
+ VIR_FREE(domInfo);
+ } else {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Couldn't fetch Domain Information");
+ return -1;
+ }
+ if ( virNodeGetInfo(dom->conn,&nodeInfo)==0)
+ cpus = nodeInfo.cpus;
+ else {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Couldn't fetch Node Information");
+ return -1;
+ }
+ if(nvcpus > maxinfo) nvcpus = maxinfo;
+
+ if (cpumaps != NULL)
+ memset(cpumaps, 0, maxinfo * maplen);
+ if (!xen_vm_get_by_name_label(session, &vms, dom->name)) return -1;
+ if (vms->size!=1) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique");
+ xen_vm_set_free(vms);
+ return -1;
+ }
+ vm = vms->contents[0];
+ if (!xen_vm_get_vcpus_params(session, &vcpu_params, vm)) {
+ xen_vm_set_free(vms);
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+ return -1;
+ }
+ for (i=0; i<vcpu_params->size; i++) {
+ if (STREQ(vcpu_params->contents[i].key,"mask")) {
+ if (!(mask = strdup(vcpu_params->contents[i].val))){
+ xen_vm_set_free(vms);
+ xen_string_string_map_free(vcpu_params);
+ virReportOOMError();
+ return -1;
+ }
+ break;
+ }
+ }
+ xen_string_string_map_free(vcpu_params);
+ for (i=0,ifptr=info ;i<nvcpus; i++,ifptr++) {
+ ifptr->number = i;
+ ifptr->state = VIR_VCPU_RUNNING;
+ ifptr->cpuTime = 0;
+ ifptr->cpu = 0;
+ if (mask !=NULL)
+ getCpuBitMapfromString(mask,VIR_GET_CPUMAP(cpumaps,maplen,i),maplen);
+ }
+ VIR_FREE(mask);
+ xen_vm_set_free(vms);
+ return i;
+}
+
+/*
+* xenapiDomainGetMaxVcpus
+*
+*
+* Returns maximum number of Vcpus on success or -1 in case of error
+*/
+static int
+xenapiDomainGetMaxVcpus (virDomainPtr dom)
+{
+ xen_vm vm;
+ xen_vm_set *vms;
+ int64_t maxvcpu=0;
+ enum xen_vm_power_state state;
+ xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+ if (xen_vm_get_by_name_label(session, &vms, dom->name)) {
+ if (vms->size!=1) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique");
+ xen_vm_set_free(vms);
+ return -1;
+ }
+ vm = vms->contents[0];
+ xen_vm_get_power_state(session, &state, vm);
+ if(state == XEN_VM_POWER_STATE_RUNNING) {
+ xen_vm_get_vcpus_max(session, &maxvcpu, vm);
+ } else {
+ maxvcpu = xenapiGetMaxVcpus(dom->conn, NULL);
+ }
+ xen_vm_set_free(vms);
+ return (int)maxvcpu;
+ }
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+ return -1;
+}
+
+/*
+* xenapiDomainDumpXML
+*
+*
+* Returns XML string of the domain configuration on success or -1 in case of error
+*/
+static char *
+xenapiDomainDumpXML (virDomainPtr dom, ATTRIBUTE_UNUSED int flags)
+{
+ xen_vm vm=NULL;
+ xen_vm_set *vms;
+ xen_string_string_map *result=NULL;
+ xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+ virDomainDefPtr defPtr = NULL;
+
+ if(!xen_vm_get_by_name_label(session, &vms, dom->name)) return NULL;
+ if (vms->size!=1) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique");
+ xen_vm_set_free(vms);
+ return NULL;
+ }
+ if (VIR_ALLOC(defPtr)<0) {
+ virReportOOMError();
+ xen_vm_set_free(vms);
+ return NULL;
+ }
+ vm = vms->contents[0];
+ defPtr->virtType = VIR_DOMAIN_VIRT_XEN;
+ defPtr->id = dom->id;
+ memcpy((char *)defPtr->uuid,(char *)dom->uuid,VIR_UUID_BUFLEN);
+ if (!(defPtr->name = strdup(dom->name)))
+ goto error_cleanup;
+ char *boot_policy=NULL;
+ xen_vm_get_hvm_boot_policy(session, &boot_policy, vm);
+ if (STREQ(boot_policy,"BIOS order")) {
+ if (!(defPtr->os.type = strdup("hvm"))) {
+ VIR_FREE(boot_policy);
+ goto error_cleanup;
+ }
+ xen_vm_get_hvm_boot_params(session, &result, vm);
+ if (result!=NULL) {
+ int i;
+ for (i=0; i<(result->size); i++) {
+ if (STREQ(result->contents[i].key,"order")) {
+ int cnt=0;
+ while(result->contents[i].val[cnt]!='\0') {
+ defPtr->os.bootDevs[cnt] = map2LibvirtBootOrder(result->contents[i].val[cnt]);
+ cnt++;
+ }
+ defPtr->os.nBootDevs = cnt;
+ }
+ }
+ xen_string_string_map_free(result);
+ }
+ VIR_FREE(boot_policy);
+ } else {
+ if(!(defPtr->os.type = strdup("xen"))) {
+ VIR_FREE(boot_policy);
+ goto error_cleanup;
+ }
+ if(!(defPtr->os.loader = strdup("pygrub"))) {
+ VIR_FREE(boot_policy);
+ goto error_cleanup;
+ }
+ char *value=NULL;
+ xen_vm_get_pv_kernel(session, &value, vm);
+ if (STRNEQ(value,"")) {
+ if(!(defPtr->os.kernel = strdup(value))) {
+ VIR_FREE(boot_policy);
+ VIR_FREE(value);
+ goto error_cleanup;
+ }
+ VIR_FREE(value);
+ }
+ xen_vm_get_pv_ramdisk(session, &value, vm);
+ if (STRNEQ(value,"")) {
+ if(!(defPtr->os.initrd = strdup(value))) {
+ VIR_FREE(boot_policy);
+ VIR_FREE(value);
+ goto error_cleanup;
+ }
+ VIR_FREE(value);
+ }
+ xen_vm_get_pv_args(session, &value, vm);
+ if (STRNEQ(value,"")) {
+ if(!(defPtr->os.cmdline = strdup(value))) {
+ VIR_FREE(boot_policy);
+ VIR_FREE(value);
+ goto error_cleanup;
+ }
+ VIR_FREE(value);
+ }
+ VIR_FREE(boot_policy);
+ if(!(defPtr->os.bootloader = strdup("pygrub")))
+ goto error_cleanup;
+ }
+ char *val=NULL;
+ xen_vm_get_pv_bootloader_args(session, &val, vm);
+ if (STRNEQ(val,"")) {
+ if(!(defPtr->os.bootloaderArgs = strdup(val))) {
+ VIR_FREE(val);
+ goto error_cleanup;
+ }
+ VIR_FREE(val);
+ }
+ unsigned long memory=0;
+ memory = xenapiDomainGetMaxMemory(dom);
+ defPtr->maxmem = memory;
+ int64_t dynamic_mem=0;
+ if (xen_vm_get_memory_dynamic_max(session, &dynamic_mem, vm)) {
+ defPtr->memory = (unsigned long) (dynamic_mem/1024);
+ } else {
+ defPtr->memory = memory;
+ }
+ defPtr->vcpus = xenapiDomainGetMaxVcpus(dom);
+ enum xen_on_normal_exit action;
+ if (xen_vm_get_actions_after_shutdown(session, &action, vm)) {
+ defPtr->onPoweroff = xenapiNormalExitEnum2virDomainLifecycle(action);
+ }
+ if (xen_vm_get_actions_after_reboot(session, &action, vm)) {
+ defPtr->onReboot = xenapiNormalExitEnum2virDomainLifecycle(action);
+ }
+ enum xen_on_crash_behaviour crash;
+ if (xen_vm_get_actions_after_crash(session, &crash, vm)) {
+ defPtr->onCrash = xenapiCrashExitEnum2virDomainLifecycle(action);
+ }
+ xen_vm_get_platform(session, &result, vm);
+ if (result!=NULL) {
+ int i;
+ for(i=0; i< (result->size); i++) {
+ if (STREQ(result->contents[i].val,"true")) {
+ if (STREQ(result->contents[i].key,"acpi"))
+ defPtr->features = defPtr->features | (1<<VIR_DOMAIN_FEATURE_ACPI);
+ else if (STREQ(result->contents[i].key,"apic"))
+ defPtr->features = defPtr->features | (1<<VIR_DOMAIN_FEATURE_APIC);
+ else if (STREQ(result->contents[i].key,"pae"))
+ defPtr->features = defPtr->features | (1<<VIR_DOMAIN_FEATURE_PAE);
+ }
+ }
+ xen_string_string_map_free(result);
+ }
+ struct xen_vif_set *vif_set=NULL;
+ xen_vm_get_vifs(session, &vif_set, vm);
+ if (vif_set) {
+ int i;
+ xen_vif vif;
+ xen_vif_record *vif_rec=NULL;
+ xen_network network;
+ char *bridge=NULL;
+ defPtr->nnets = vif_set->size;
+ if (VIR_ALLOC_N(defPtr->nets, vif_set->size)<0) {
+ xen_vif_set_free(vif_set);
+ goto error_cleanup;
+ }
+ for (i=0; i<vif_set->size; i++) {
+ if (VIR_ALLOC(defPtr->nets[i])<0) {
+ xen_vif_set_free(vif_set);
+ goto error_cleanup;
+ }
+ defPtr->nets[i]->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
+ vif = vif_set->contents[i];
+ xen_vif_get_network(session, &network, vif);
+ if (network!=NULL) {
+ xen_network_get_bridge(session, &bridge, network);
+ if (bridge!=NULL)
+ defPtr->nets[i]->data.bridge.brname = bridge;
+ xen_network_free(network);
+ }
+ xen_vif_get_record(session, &vif_rec, vif);
+ if (vif_rec!=NULL) {
+ if(virParseMacAddr((const char *)vif_rec->mac,defPtr->nets[i]->mac) < 0)
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Unable to parse given mac address");
+ xen_vif_record_free(vif_rec);
+ }
+ }
+ xen_vif_set_free(vif_set);
+ }
+ if (vms) xen_vm_set_free(vms);
+ char *xml = virDomainDefFormat(defPtr,0);
+ virDomainDefFree(defPtr);
+ return xml;
+
+ error_cleanup:
+ virReportOOMError();
+ xen_vm_set_free(vms);
+ virDomainDefFree(defPtr);
+ return NULL;
+
+}
+
+/*
+* xenapiListDefinedDomains
+*
+* list the defined but inactive domains, stores the pointers to the names in @names
+* Returns number of names provided in the array or -1 in case of error
+*/
+static int
+xenapiListDefinedDomains (virConnectPtr conn, char **const names,
+ int maxnames)
+{
+ int i,j=0,doms;
+ xen_vm_set *result;
+ xen_vm_record *record;
+ xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+ xen_vm_get_all(session, &result);
+ if (result != NULL) {
+ for (i=0; i< (result->size) && j< maxnames; i++) {
+ xen_vm_get_record(session, &record, result->contents[i]);
+ if ( record!=NULL ) {
+ if ( record->is_a_template == 0 ) {
+ char *usenames;
+ if (!(usenames = strdup(record->name_label))) {
+ virReportOOMError();
+ xen_vm_record_free(record);
+ xen_vm_set_free(result);
+ return -1;
+ }
+ names[j++]=usenames;
+ }
+ xen_vm_record_free(record);
+ } else {
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Couldn't get VM record");
+ xen_vm_set_free(result);
+ return -1;
+ }
+ }
+ doms=j;
+ xen_vm_set_free(result);
+ return doms;
+ }
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
+ return -1;
+}
+
+/*
+* xenapiNumOfDefinedDomains
+*
+* Provides the number of defined but inactive domains
+* Returns number of domains found on success or -1 in case of error
+*/
+static int
+xenapiNumOfDefinedDomains (virConnectPtr conn)
+{
+ xen_vm_set *result;
+ xen_vm_record *record;
+ int DomNum=0,i;
+ xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+ xen_vm_get_all(session, &result);
+ if ( result != NULL) {
+ for ( i=0; i< (result->size); i++ ) {
+ xen_vm_get_record(session, &record, result->contents[i]);
+ if (record==NULL && !session->ok) {
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
+ xen_vm_set_free(result);
+ return -1;
+ }
+ if (record->is_a_template == 0)
+ DomNum++;
+ xen_vm_record_free(record);
+ }
+ xen_vm_set_free(result);
+ return DomNum;
+ }
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
+ return -1;
+}
+
+/*
+* xenapiDomainCreate
+*
+* starts a VM
+* Return 0 on success or -1 in case of error
+*/
+static int
+xenapiDomainCreate (virDomainPtr dom)
+{
+ xen_vm_set *vms;
+ xen_vm vm;
+ xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+ if (xen_vm_get_by_name_label(session, &vms, dom->name)) {
+ if (vms->size!=1) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique");
+ xen_vm_set_free(vms);
+ return -1;
+ }
+ vm = vms->contents[0];
+ if (!xen_vm_start(session, vm, false, false)) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+ xen_vm_set_free(vms);
+ return -1;
+ }
+ xen_vm_set_free(vms);
+ } else {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+* xenapiDomainDefineXML
+*
+* Defines a domain from the given XML but does not start it
+* Returns 0 on success or -1 in case of error
+*/
+static virDomainPtr
+xenapiDomainDefineXML (virConnectPtr conn, const char *xml)
+{
+ xen_vm_record *record=NULL;
+ xen_vm vm=NULL;
+ virDomainPtr domP=NULL;
+ xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+ virCapsPtr caps = ((struct _xenapiPrivate *)(conn->privateData))->caps;
+ if (!caps)
+ return NULL;
+ virDomainDefPtr defPtr = virDomainDefParseString(caps, xml, 0);
+ if (!defPtr)
+ return NULL;
+ if (createVMRecordFromXml( conn, defPtr, &record, &vm)!=0) {
+ if (!(session->ok))
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
+ else
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Couldn't get VM information from XML");
+ virDomainDefFree(defPtr);
+ return NULL;
+ }
+ if (record!=NULL) {
+ unsigned char raw_uuid[VIR_UUID_BUFLEN];
+ virUUIDParse(record->uuid,raw_uuid);
+ domP = virGetDomain(conn, record->name_label, raw_uuid);
+ if (!domP && !(session->ok))
+ xenapiSessionErrorHandler(conn, VIR_ERR_NO_DOMAIN, NULL);
+ xen_vm_record_free(record);
+ }
+ else if (vm!=NULL)
+ xen_vm_free(vm);
+ virDomainDefFree(defPtr);
+ return domP;
+}
+
+/*
+* xenapiDomainUndefine
+*
+* destroys a domain
+* Return 0 on success or -1 in case of error
+*/
+static int
+xenapiDomainUndefine (virDomainPtr dom)
+{
+ struct xen_vm_set *vms;
+ xen_vm vm;
+ xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+ if (!xen_vm_get_by_name_label(session, &vms, dom->name)) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
+ return -1;
+ }
+ if (vms->size!=1) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique");
+ xen_vm_set_free(vms);
+ return -1;
+ }
+ vm = vms->contents[0];
+ if (!xen_vm_destroy(session, vm)) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+ xen_vm_set_free(vms);
+ return -1;
+ }
+ xen_vm_set_free(vms);
+ return 0;
+}
+
+/*
+* xenapiDomainGetAutostart
+*
+* Provides a boolean value indicating whether the domain configured
+* to be automatically started when the host machine boots
+* Return 0 on success or -1 in case of error
+*/
+static int
+xenapiDomainGetAutostart (virDomainPtr dom, int *autostart)
+{
+ int i,flag=0;
+ xen_vm_set *vms;
+ xen_vm vm;
+ xen_string_string_map *result;
+ xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+ if(!xen_vm_get_by_name_label(session, &vms, dom->name)) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
+ return -1;
+ }
+ if (vms->size!=1) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique");
+ xen_vm_set_free(vms);
+ return -1;
+ }
+ vm = vms->contents[0];
+ if (!xen_vm_get_other_config(session, &result, vm)) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+ xen_vm_set_free(vms);
+ return -1;
+ }
+ for (i=0; i < result->size; i++) {
+ if (STREQ(result->contents[i].key, "auto_poweron")) {
+ flag=1;
+ if (STREQ(result->contents[i].val, "true"))
+ *autostart = 1;
+ else
+ *autostart = 0;
+ }
+ }
+ xen_vm_set_free(vms);
+ xen_string_string_map_free(result);
+ if (flag==0) return -1;
+ return 0;
+}
+
+/*
+* xenapiDomainSetAutostart
+*
+* Configure the domain to be automatically started when the host machine boots
+* Return 0 on success or -1 in case of error
+*/
+static int
+xenapiDomainSetAutostart (virDomainPtr dom, int autostart)
+{
+ xen_vm_set *vms;
+ xen_vm vm;
+ char *value;
+ xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+ if (!xen_vm_get_by_name_label(session, &vms, dom->name)) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
+ return -1;
+ }
+ if (vms->size!=1) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique");
+ xen_vm_set_free(vms);
+ return -1;
+ }
+ vm = vms->contents[0];
+ xen_vm_remove_from_other_config(session, vm, (char *)"auto_poweron");
+ if (autostart==1)
+ value = (char *)"true";
+ else
+ value = (char *)"false";
+ if (!xen_vm_add_to_other_config(session, vm, (char *)"auto_poweron", value)) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+ xen_vm_set_free(vms);
+ return -1;
+ }
+ xen_vm_set_free(vms);
+ return 0;
+}
+
+static char *
+xenapiDomainGetSchedulerType (virDomainPtr dom ATTRIBUTE_UNUSED, int *nparams)
+{
+ *nparams = 0;
+ char *result=NULL;
+ if (!(result = strdup("credit")))
+ virReportOOMError();
+ return result;
+}
+
+/*
+* xenapiNodeGetFreeMemory
+*
+* provides the free memory available on the Node
+* Returns memory size on success or 0 in case of error
+*/
+static unsigned long long
+xenapiNodeGetFreeMemory (virConnectPtr conn)
+{
+ xen_host_metrics_set *xen_met_set;
+ unsigned long long freeMem=0;
+ xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+ xen_host_metrics_get_all(session, &xen_met_set);
+ if (xen_met_set != NULL) {
+ if (!xen_host_metrics_get_memory_free(session, (int64_t *)&freeMem, xen_met_set->contents[0])) {
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Couldn't get host metrics - memory information");
+ freeMem=0;
+ }
+ xen_host_metrics_set_free(xen_met_set);
+ } else {
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Couldn't get host metrics");
+ }
+ return freeMem;
+}
+
+/*
+* xenapiNodeGetCellsFreeMemory
+*
+*
+* Returns the number of entries filled in freeMems, or -1 in case of error.
+*/
+static int
+xenapiNodeGetCellsFreeMemory (virConnectPtr conn, unsigned long long *freeMems,
+ int startCell, int maxCells)
+{
+ if (maxCells >1 && startCell >0) {
+ xenapiSessionErrorHandler(conn, VIR_ERR_NO_SUPPORT, "");
+ return -1;
+ } else {
+ freeMems[0] = xenapiNodeGetFreeMemory(conn);
+ return 1;
+ }
+}
+
+/* The interface which we export upwards to libvirt.c. */
+static virDriver xenapiDriver = {
+ VIR_DRV_XENAPI,
+ "XenAPI",
+ xenapiOpen, /* open */
+ xenapiClose, /* close */
+ xenapiSupportsFeature, /* supports_feature */
+ xenapiType, /* type */
+ xenapiGetVersion, /* version */
+ NULL, /*getlibvirtVersion */
+ xenapiGetHostname, /* getHostname */
+ xenapiGetMaxVcpus, /* getMaxVcpus */
+ xenapiNodeGetInfo, /* nodeGetInfo */
+ xenapiGetCapabilities, /* getCapabilities */
+ xenapiListDomains, /* listDomains */
+ xenapiNumOfDomains, /* numOfDomains */
+ xenapiDomainCreateXML, /* domainCreateXML */
+ xenapiDomainLookupByID, /* domainLookupByID */
+ xenapiDomainLookupByUUID, /* domainLookupByUUID */
+ xenapiDomainLookupByName, /* domainLookupByName */
+ xenapiDomainSuspend, /* domainSuspend */
+ xenapiDomainResume, /* domainResume */
+ xenapiDomainShutdown, /* domainShutdown */
+ xenapiDomainReboot, /* domainReboot */
+ xenapiDomainDestroy, /* domainDestroy */
+ xenapiDomainGetOSType, /* domainGetOSType */
+ xenapiDomainGetMaxMemory, /* domainGetMaxMemory */
+ xenapiDomainSetMaxMemory, /* domainSetMaxMemory */
+ NULL, /* domainSetMemory */
+ xenapiDomainGetInfo, /* domainGetInfo */
+ NULL, /* domainSave */
+ NULL, /* domainRestore */
+ NULL, /* domainCoreDump */
+ xenapiDomainSetVcpus, /* domainSetVcpus */
+ xenapiDomainPinVcpu, /* domainPinVcpu */
+ xenapiDomainGetVcpus, /* domainGetVcpus */
+ xenapiDomainGetMaxVcpus, /* domainGetMaxVcpus */
+ NULL, /* domainGetSecurityLabel */
+ NULL, /* nodeGetSecurityModel */
+ xenapiDomainDumpXML, /* domainDumpXML */
+ NULL, /* domainXmlFromNative */
+ NULL, /* domainXmlToNative */
+ xenapiListDefinedDomains, /* listDefinedDomains */
+ xenapiNumOfDefinedDomains, /* numOfDefinedDomains */
+ xenapiDomainCreate, /* domainCreate */
+ xenapiDomainDefineXML, /* domainDefineXML */
+ xenapiDomainUndefine, /* domainUndefine */
+ NULL, /* domainAttachDevice */
+ NULL,
+ NULL, /* domainDetachDevice */
+ NULL,
+ xenapiDomainGetAutostart, /* domainGetAutostart */
+ xenapiDomainSetAutostart, /* domainSetAutostart */
+ xenapiDomainGetSchedulerType, /* domainGetSchedulerType */
+ NULL, /* domainGetSchedulerParameters */
+ NULL, /* domainSetSchedulerParameters */
+ NULL, /* domainMigratePrepare */
+ NULL, /* domainMigratePerform */
+ NULL, /* domainMigrateFinish */
+ NULL, /* domainBlockStats */
+ NULL, /* domainInterfaceStats */
+ NULL,
+ NULL, /* domainBlockPeek */
+ NULL, /* domainMemoryPeek */
+ xenapiNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
+ xenapiNodeGetFreeMemory, /* getFreeMemory */
+ NULL, /* domainEventRegister */
+ NULL, /* domainEventDeregister */
+ NULL, /* domainMigratePrepare2 */
+ NULL, /* domainMigrateFinish2 */
+ NULL, /* nodeDeviceDettach */
+ NULL, /* nodeDeviceReAttach */
+ NULL, /* nodeDeviceReset */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+/**
+ * xenapiRegister:
+ *
+ *
+ * Returns the driver priority or -1 in case of error.
+ */
+int
+xenapiRegister (void)
+{
+ return virRegisterDriver (&xenapiDriver);
+}
+
+/*
+* write_func
+* used by curl to read data from the server
+*/
+size_t
+write_func(void *ptr, size_t size, size_t nmemb, void *comms_)
+{
+ xen_comms *comms = comms_;
+ size_t n = size * nmemb;
+ #ifdef PRINT_XML
+ printf("\n\n---Result from server -----------------------\n");
+ printf("%s\n",((char*) ptr));
+ fflush(stdout);
+ #endif
+ return (size_t) (comms->func(ptr, n, comms->handle) ? n : 0);
+}
+
+/*
+* call_func
+* sets curl options, used with xen_session_login_with_password
+*/
+int
+call_func(const void *data, size_t len, void *user_handle,
+ void *result_handle, xen_result_func result_func)
+{
+ //(void)user_handle;
+ struct _xenapiPrivate *priv = (struct _xenapiPrivate *)user_handle;
+ #ifdef PRINT_XML
+
+ printf("\n\n---Data to server: -----------------------\n");
+ printf("%s\n",((char*) data));
+ fflush(stdout);
+ #endif
+ CURL *curl = curl_easy_init();
+ if (!curl) {
+ return -1;
+ }
+ xen_comms comms = {
+ .func = result_func,
+ .handle = result_handle
+ };
+ curl_easy_setopt(curl, CURLOPT_URL, priv->url);
+ curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
+ #ifdef CURLOPT_MUTE
+ curl_easy_setopt(curl, CURLOPT_MUTE, 1);
+ #endif
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_func);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &comms);
+ curl_easy_setopt(curl, CURLOPT_POST, 1);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, len);
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, priv->SSLflag);
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, priv->SSLflag);
+ CURLcode result = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ return result;
+
+}
+
+
+
diff -Nur ./libvirt_org/src/xenapi/xenapi_driver.h ./libvirt/src/xenapi/xenapi_driver.h
--- ./libvirt_org/src/xenapi/xenapi_driver.h 1970-01-01 01:00:00.000000000 +0100
+++ ./libvirt/src/xenapi/xenapi_driver.h 2010-02-26 13:21:50.000000000 +0000
@@ -0,0 +1,15 @@
+/*
+ * xenapi_driver.h.c: Xen API driver header file to be included in libvirt.c.
+ * Copyright (C) 2009 Citrix Ltd.
+ * Sharadha Prabhakar <sharadha.prabhakar(a)citrix.com>
+ */
+
+
+#ifndef __VIR_XENAPI_PRIV_H__
+#define __VIR_XENAPI_PRIV_H__
+
+
+extern int xenapiRegister (void);
+
+
+#endif /* __VIR_XENAPI_PRIV_H__ */
diff -Nur ./libvirt_org/src/xenapi/xenapi_driver_private.h ./libvirt/src/xenapi/xenapi_driver_private.h
--- ./libvirt_org/src/xenapi/xenapi_driver_private.h 1970-01-01 01:00:00.000000000 +0100
+++ ./libvirt/src/xenapi/xenapi_driver_private.h 2010-03-03 16:09:47.000000000 +0000
@@ -0,0 +1,49 @@
+/*
+ * xenapi_driver_private.h: Xen API driver's private header file.
+ * Copyright (C) 2009 Citrix Ltd.
+ * Sharadha Prabhakar <sharadha.prabhakar(a)citrix.com>
+ */
+
+
+#ifndef __VIR_XENAPI_H__
+#define __VIR_XENAPI_H__
+
+#include <xen/api/xen_common.h>
+#include <libxml/tree.h>
+#include "virterror_internal.h"
+
+//#define PRINT_XML
+#define VIR_FROM_THIS VIR_FROM_XENAPI
+#define LIBVIRT_MODELNAME_LEN (32)
+#define xenapiSessionErrorHandler(conn,errNum,buf) xenapiSessionErrorHandle(conn, errNum, \
+ buf,__FILE__,__FUNCTION__,__LINE__)
+
+void
+xenapiSessionErrorHandle(virConnectPtr conn, virErrorNumber errNum,
+ const char *buf, const char *filename, const char *func, size_t lineno);
+
+typedef struct
+{
+ xen_result_func func;
+ void *handle;
+} xen_comms;
+
+
+int
+call_func(const void *data, size_t len, void *user_handle,
+ void *result_handle, xen_result_func result_func);
+size_t
+write_func(void *ptr, size_t size, size_t nmemb, void *comms);
+
+/* xenAPI driver's private data structure */
+struct _xenapiPrivate {
+ xen_session *session;
+ void *handle;
+ char *uname;
+ char *pwd;
+ char *url;
+ int SSLflag;
+ virCapsPtr caps;
+};
+
+#endif /* __VIR_XENAPI_H__ */
diff -Nur ./libvirt_org/src/xenapi/xenapi_utils.c ./libvirt/src/xenapi/xenapi_utils.c
--- ./libvirt_org/src/xenapi/xenapi_utils.c 1970-01-01 01:00:00.000000000 +0100
+++ ./libvirt/src/xenapi/xenapi_utils.c 2010-03-03 18:01:06.000000000 +0000
@@ -0,0 +1,578 @@
+/*
+ * xenapi_utils.c: Xen API driver -- utils parts.
+ * Copyright (C) 2009 Citrix Ltd.
+ * Sharadha Prabhakar <sharadha.prabhakar(a)citrix.com>
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <config.h>
+
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <libxml/uri.h>
+#include <xen_internal.h>
+#include <libxml/parser.h>
+#include <curl/curl.h>
+#include <xen/api/xen_common.h>
+#include <xen/api/xen_vm.h>
+#include <xen/api/xen_vm.h>
+#include <xen/api/xen_all.h>
+#include <xen/api/xen_vm_metrics.h>
+
+#include "domain_conf.h"
+#include "libvirt_internal.h"
+#include "libvirt/libvirt.h"
+#include "virterror_internal.h"
+#include "datatypes.h"
+#include "xenapi_driver_private.h"
+#include "util.h"
+#include "uuid.h"
+#include "memory.h"
+#include "driver.h"
+#include "buf.h"
+#include "xenapi_utils.h"
+#include "util/logging.h"
+#include "qparams.h"
+
+
+char *
+xenapiUtil_RequestPassword(virConnectAuthPtr auth, const char *username,
+ const char *hostname)
+{
+ unsigned int ncred;
+ virConnectCredential cred;
+ char *prompt;
+
+ memset(&cred, 0, sizeof(virConnectCredential));
+
+ if (virAsprintf(&prompt, "Enter %s password for %s", username,
+ hostname) < 0) {
+ return NULL;
+ }
+
+ for (ncred = 0; ncred < auth->ncredtype; ncred++) {
+ if (auth->credtype[ncred] != VIR_CRED_PASSPHRASE &&
+ auth->credtype[ncred] != VIR_CRED_NOECHOPROMPT) {
+ continue;
+ }
+
+ cred.type = auth->credtype[ncred];
+ cred.prompt = prompt;
+ cred.challenge = hostname;
+ cred.defresult = NULL;
+ cred.result = NULL;
+ cred.resultlen = 0;
+
+ if ((*(auth->cb))(&cred, 1, auth->cbdata) < 0) {
+ VIR_FREE(cred.result);
+ }
+
+ break;
+ }
+
+ VIR_FREE(prompt);
+
+ return cred.result;
+}
+
+int
+xenapiUtil_ParseQuery(virConnectPtr conn, xmlURIPtr uri, int *noVerify)
+{
+ int result = 0;
+ int i;
+ struct qparam_set *queryParamSet = NULL;
+ struct qparam *queryParam = NULL;
+
+#ifdef HAVE_XMLURI_QUERY_RAW
+ queryParamSet = qparam_query_parse(uri->query_raw);
+#else
+ queryParamSet = qparam_query_parse(uri->query);
+#endif
+
+ if (queryParamSet == NULL) {
+ goto failure;
+ }
+
+ for (i = 0; i < queryParamSet->n; i++) {
+ queryParam = &queryParamSet->p[i];
+ if (STRCASEEQ(queryParam->name, "no_verify")) {
+ if (noVerify == NULL) {
+ continue;
+ }
+ if (virStrToLong_i(queryParam->value, NULL, 10, noVerify) < 0 ||
+ (*noVerify != 0 && *noVerify != 1)) {
+ xenapiSessionErrorHandler(conn, VIR_ERR_INVALID_ARG,
+ "Query parameter 'no_verify' has unexpected value (should be 0 or 1)");
+ goto failure;
+ }
+ }
+ }
+
+ cleanup:
+ if (queryParamSet != NULL) {
+ free_qparam_set(queryParamSet);
+ }
+
+ return result;
+
+ failure:
+ result = -1;
+
+ goto cleanup;
+}
+
+
+
+enum xen_on_normal_exit
+actionShutdownLibvirt2XenapiEnum(enum virDomainLifecycleAction action)
+{
+ enum xen_on_normal_exit num = XEN_ON_NORMAL_EXIT_RESTART;
+ if (action == VIR_DOMAIN_LIFECYCLE_DESTROY)
+ num = XEN_ON_NORMAL_EXIT_DESTROY;
+ else if (action == VIR_DOMAIN_LIFECYCLE_RESTART)
+ num = XEN_ON_NORMAL_EXIT_RESTART;
+ return num;
+}
+
+
+enum xen_on_crash_behaviour
+actionCrashLibvirt2XenapiEnum(enum virDomainLifecycleAction action)
+{
+ enum xen_on_crash_behaviour num = XEN_ON_CRASH_BEHAVIOUR_RESTART;
+ if (action == VIR_DOMAIN_LIFECYCLE_DESTROY)
+ num = XEN_ON_CRASH_BEHAVIOUR_DESTROY;
+ else if (action == VIR_DOMAIN_LIFECYCLE_RESTART)
+ num = XEN_ON_CRASH_BEHAVIOUR_RESTART;
+ else if (action == VIR_DOMAIN_LIFECYCLE_PRESERVE)
+ num = XEN_ON_CRASH_BEHAVIOUR_PRESERVE;
+ else if (action == VIR_DOMAIN_LIFECYCLE_RESTART_RENAME)
+ num = XEN_ON_CRASH_BEHAVIOUR_RENAME_RESTART;
+ return num;
+}
+
+/* generate XenAPI boot order format from libvirt format */
+char *
+createXenAPIBootOrderString(int nboot, int *bootDevs)
+{
+ virBuffer ret = VIR_BUFFER_INITIALIZER;
+ char *val = NULL;
+ int i;
+ for (i=0;i<nboot;i++) {
+ if (bootDevs[i] == VIR_DOMAIN_BOOT_FLOPPY)
+ val = (char *)"a";
+ else if (bootDevs[i] == VIR_DOMAIN_BOOT_DISK)
+ val = (char *)"c";
+ else if (bootDevs[i] == VIR_DOMAIN_BOOT_CDROM)
+ val = (char *)"d";
+ else if (bootDevs[i] == VIR_DOMAIN_BOOT_NET)
+ val = (char *)"n";
+ if (val)
+ virBufferEscapeString(&ret,"%s",val);
+ }
+ return virBufferContentAndReset(&ret);
+}
+
+/* convert boot order string to libvirt boot order enum */
+enum virDomainBootOrder
+map2LibvirtBootOrder(char c) {
+ switch(c) {
+ case 'a':
+ return VIR_DOMAIN_BOOT_FLOPPY;
+ case 'c':
+ return VIR_DOMAIN_BOOT_DISK;
+ case 'd':
+ return VIR_DOMAIN_BOOT_CDROM;
+ case 'n':
+ return VIR_DOMAIN_BOOT_NET;
+ default:
+ return -1;
+ }
+}
+
+enum virDomainLifecycleAction
+xenapiNormalExitEnum2virDomainLifecycle(enum xen_on_normal_exit action)
+{
+ enum virDomainLifecycleAction num = VIR_DOMAIN_LIFECYCLE_RESTART;
+ if (action == XEN_ON_NORMAL_EXIT_DESTROY)
+ num = VIR_DOMAIN_LIFECYCLE_DESTROY;
+ else if (action == XEN_ON_NORMAL_EXIT_RESTART)
+ num = VIR_DOMAIN_LIFECYCLE_RESTART;
+ return num;
+}
+
+
+enum virDomainLifecycleAction
+xenapiCrashExitEnum2virDomainLifecycle(enum xen_on_crash_behaviour action)
+{
+ enum virDomainLifecycleAction num = VIR_DOMAIN_LIFECYCLE_RESTART;
+ if (action == XEN_ON_CRASH_BEHAVIOUR_DESTROY)
+ num = VIR_DOMAIN_LIFECYCLE_DESTROY;
+ else if (action == XEN_ON_CRASH_BEHAVIOUR_RESTART)
+ num = VIR_DOMAIN_LIFECYCLE_RESTART;
+ else if (action == XEN_ON_CRASH_BEHAVIOUR_PRESERVE)
+ num = VIR_DOMAIN_LIFECYCLE_PRESERVE;
+ else if (action == XEN_ON_CRASH_BEHAVIOUR_RENAME_RESTART)
+ num = VIR_DOMAIN_LIFECYCLE_RESTART_RENAME;
+ return num;
+}
+
+
+
+/* returns 'file' or 'block' for the storage type */
+int
+getStorageVolumeType(char *type)
+{
+ if((STREQ(type,"lvmoiscsi")) ||
+ (STREQ(type,"lvmohba")) ||
+ (STREQ(type,"lvm")) ||
+ (STREQ(type,"file")) ||
+ (STREQ(type,"iso")) ||
+ (STREQ(type,"ext")) ||
+ (STREQ(type,"nfs")))
+ return (int)VIR_STORAGE_VOL_FILE;
+ else if((STREQ(type,"iscsi")) ||
+ (STREQ(type,"equal")) ||
+ (STREQ(type,"hba")) ||
+ (STREQ(type,"cslg")) ||
+ (STREQ(type,"udev")) ||
+ (STREQ(type,"netapp")))
+ return (int)VIR_STORAGE_VOL_BLOCK;
+ return -1;
+}
+
+/* returns error description if any received from the server */
+char *
+returnErrorFromSession(xen_session *session)
+{
+ int i;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ for (i=0; i<session->error_description_count-1; i++) {
+ if (!i)
+ virBufferEscapeString(&buf,"%s",session->error_description[i]);
+ else
+ virBufferEscapeString(&buf," : %s",session->error_description[i]);
+ }
+ return virBufferContentAndReset(&buf);
+}
+
+/* converts bitmap to string of the form '1,2...' */
+char *
+mapDomainPinVcpu(unsigned char *cpumap, int maplen)
+{
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ size_t len;
+ char *ret=NULL;
+ int i, j;
+ for (i = 0; i < maplen; i++) {
+ for (j = 0; j < 8; j++) {
+ if (cpumap[i] & (1 << j)) {
+ virBufferVSprintf(&buf,"%d,", (8*i)+j);
+ }
+ }
+ }
+ if (virBufferError(&buf)) {
+ virReportOOMError();
+ virBufferFreeAndReset(&buf);
+ return NULL;
+ }
+ ret = virBufferContentAndReset(&buf);
+ len = strlen(ret);
+ if (len > 0 && ret[len - 1] == ',')
+ ret[len - 1] = 0;
+ return ret;
+}
+
+/* obtains the CPU bitmap from the string passed */
+void
+getCpuBitMapfromString(char *mask, unsigned char *cpumap, int maplen)
+{
+ int pos;
+ int max_bits = maplen * 8;
+ char *num = NULL,*bp=NULL;
+ bzero(cpumap, maplen);
+ num = strtok_r (mask, ",", &bp);
+ while (num != NULL) {
+ if (sscanf (num, "%d", &pos)!=1)
+ virReportOOMError();
+ if (pos<0 || pos>max_bits-1)
+ VIR_WARN ("number in str %d exceeds cpumap's max bits %d\n", pos, max_bits);
+ else
+ (cpumap)[pos/8] |= (1<<(pos%8));
+ num = strtok_r (NULL, ",", &bp);
+ }
+}
+
+
+/* mapping XenServer power state to Libvirt power state */
+virDomainState
+mapPowerState(enum xen_vm_power_state state)
+{
+ virDomainState virState;
+ switch (state) {
+ case (XEN_VM_POWER_STATE_HALTED):
+ case (XEN_VM_POWER_STATE_SUSPENDED):
+ virState = VIR_DOMAIN_SHUTOFF;
+ break;
+ case (XEN_VM_POWER_STATE_PAUSED):
+ virState = VIR_DOMAIN_PAUSED;
+ break;
+ case (XEN_VM_POWER_STATE_RUNNING):
+ virState = VIR_DOMAIN_RUNNING;
+ break;
+ case (XEN_VM_POWER_STATE_UNKNOWN):
+ case (XEN_VM_POWER_STATE_UNDEFINED):
+ virState = VIR_DOMAIN_NOSTATE;
+ break;
+ default:
+ virState = VIR_DOMAIN_NOSTATE;
+ break;
+ }
+ return virState;
+}
+
+/* allocate a flexible array and fill values(key,val) */
+int
+allocStringMap (xen_string_string_map **strings, char *key, char *val)
+{
+ int sz = ((*strings) == NULL)?0:(*strings)->size;
+ sz++;
+ if(VIR_REALLOC_N(*strings, sizeof(xen_string_string_map)+
+ sizeof(xen_string_string_map_contents)*sz)<0) {
+ virReportOOMError();
+ return -1;
+ }
+ (*strings)->size = sz;
+ (*strings)->contents[sz-1].key = strdup(key);
+ (*strings)->contents[sz-1].val = strdup(val);
+ return 0;
+}
+
+/* Error handling function returns error messages from the server if any */
+void
+xenapiSessionErrorHandle(virConnectPtr conn, virErrorNumber errNum,
+ const char *buf, const char *filename, const char *func, size_t lineno)
+{
+ if (buf==NULL) {
+ char *ret=NULL;
+ ret = returnErrorFromSession(((struct _xenapiPrivate *)(conn->privateData))->session);
+ virReportErrorHelper (conn, VIR_FROM_XENAPI, errNum, filename, func, lineno, _("%s\n"), ret);
+ xen_session_clear_error(((struct _xenapiPrivate *)(conn->privateData))->session);
+ VIR_FREE(ret);
+ } else {
+ virReportErrorHelper (conn, VIR_FROM_XENAPI, errNum, filename, func, lineno, _("%s\n"), buf);
+ }
+}
+
+/* creates network intereface for VM */
+int
+createVifNetwork (virConnectPtr conn, xen_vm vm, char *device,
+ char *bridge, char *mac)
+{
+ xen_vm xvm = NULL;
+ char *uuid = NULL;
+ xen_vm_get_uuid(((struct _xenapiPrivate *)(conn->privateData))->session, &uuid, vm);
+ if (uuid) {
+ if(!xen_vm_get_by_uuid(((struct _xenapiPrivate *)(conn->privateData))->session,
+ &xvm, uuid))
+ return -1;
+ VIR_FREE(uuid);
+ }
+ xen_vm_record_opt *vm_opt = xen_vm_record_opt_alloc();
+ vm_opt->is_record = 0;
+ vm_opt->u.handle = xvm;
+ xen_network_set *net_set = NULL;
+ xen_network_record *net_rec = NULL;
+ int cnt=0;
+ if (xen_network_get_all(((struct _xenapiPrivate *)(conn->privateData))->session, &net_set)) {
+ for(cnt=0;cnt<(net_set->size);cnt++) {
+ if (xen_network_get_record(((struct _xenapiPrivate *)(conn->privateData))->session,
+ &net_rec, net_set->contents[cnt])) {
+ if (STREQ(net_rec->bridge,bridge)) {
+ break;
+ } else {
+ xen_network_record_free(net_rec);
+ }
+ }
+ }
+ }
+ if ( (cnt<net_set->size) && net_rec) {
+ xen_network network = NULL;
+ xen_network_get_by_uuid(((struct _xenapiPrivate *)(conn->privateData))->session,
+ &network, net_rec->uuid);
+ xen_network_record_opt *network_opt = xen_network_record_opt_alloc();
+ network_opt->is_record = 0;
+ network_opt->u.handle = network;
+ xen_vif_record *vif_record = xen_vif_record_alloc();
+ vif_record->mac = mac;
+ vif_record->vm = vm_opt;
+ vif_record->network = network_opt;
+ xen_vif vif=NULL;
+
+ vif_record->other_config = xen_string_string_map_alloc(0);
+ vif_record->runtime_properties = xen_string_string_map_alloc(0);
+ vif_record->qos_algorithm_params = xen_string_string_map_alloc(0);
+ vif_record->device = strdup(device);
+ xen_vif_create(((struct _xenapiPrivate *)(conn->privateData))->session,
+ &vif, vif_record);
+ if (!vif) {
+ xen_vif_free(vif);
+ xen_vif_record_free(vif_record);
+ xen_network_record_free(net_rec);
+ xen_network_set_free(net_set);
+ return 0;
+ }
+ xen_vif_record_free(vif_record);
+ xen_network_record_free(net_rec);
+ }
+ if (net_set!=NULL) xen_network_set_free(net_set);
+ return -1;
+}
+
+/* Create a VM record from the XML description */
+int
+createVMRecordFromXml (virConnectPtr conn, virDomainDefPtr def,
+ xen_vm_record **record, xen_vm *vm)
+{
+ char uuidStr[VIR_UUID_STRING_BUFLEN];
+ *record = xen_vm_record_alloc();
+ if (!((*record)->name_label = strdup(def->name)))
+ goto error_cleanup;
+ if (def->uuid) {
+ virUUIDFormat(def->uuid,uuidStr);
+ if (!((*record)->uuid = strdup(uuidStr)))
+ goto error_cleanup;
+ }
+ if (STREQ(def->os.type,"hvm")) {
+ if(!((*record)->hvm_boot_policy = strdup("BIOS order")))
+ goto error_cleanup;
+ char *boot_order = NULL;
+ if (def->os.nBootDevs!=0)
+ boot_order = createXenAPIBootOrderString(def->os.nBootDevs, &def->os.bootDevs[0]);
+ if (boot_order!=NULL) {
+ xen_string_string_map *hvm_boot_params=NULL;
+ allocStringMap(&hvm_boot_params, (char *)"order",boot_order);
+ (*record)->hvm_boot_params = hvm_boot_params;
+ VIR_FREE(boot_order);
+ }
+ } else if (STREQ(def->os.type,"xen")) {
+ if (!((*record)->pv_bootloader = strdup("pygrub")))
+ goto error_cleanup;
+ if (def->os.kernel){
+ if (!((*record)->pv_kernel = strdup(def->os.kernel)))
+ goto error_cleanup;
+ }
+ if (def->os.initrd) {
+ if (!((*record)->pv_ramdisk = strdup(def->os.initrd)))
+ goto error_cleanup;
+ }
+ if(def->os.cmdline) {
+ if (!((*record)->pv_args = strdup(def->os.cmdline)))
+ goto error_cleanup;
+ }
+ (*record)->hvm_boot_params = xen_string_string_map_alloc(0);
+ }
+ if (def->os.bootloaderArgs)
+ if(!((*record)->pv_bootloader_args = strdup(def->os.bootloaderArgs)))
+ goto error_cleanup;
+
+ if (def->memory)
+ (*record)->memory_static_max = (int64_t) (def->memory * 1024);
+ if (def->maxmem)
+ (*record)->memory_dynamic_max = (int64_t) (def->maxmem * 1024);
+ else
+ (*record)->memory_dynamic_max = (*record)->memory_static_max;
+
+ if (def->vcpus) {
+ (*record)->vcpus_max = (int64_t) def->vcpus;
+ (*record)->vcpus_at_startup = (int64_t) def->vcpus;
+ }
+ if (def->onPoweroff)
+ (*record)->actions_after_shutdown = actionShutdownLibvirt2XenapiEnum(def->onPoweroff);
+ if (def->onReboot)
+ (*record)->actions_after_reboot = actionShutdownLibvirt2XenapiEnum(def->onReboot);
+ if (def->onCrash)
+ (*record)->actions_after_crash = actionCrashLibvirt2XenapiEnum(def->onCrash);
+
+ xen_string_string_map *strings=NULL;
+ if (def->features) {
+ if (def->features & (1<<VIR_DOMAIN_FEATURE_ACPI))
+ allocStringMap(&strings,(char *)"acpi",(char *)"true");
+ if (def->features & (1<<VIR_DOMAIN_FEATURE_APIC))
+ allocStringMap(&strings,(char *)"apic",(char *)"true");
+ if (def->features & (1<<VIR_DOMAIN_FEATURE_PAE))
+ allocStringMap(&strings,(char *)"pae",(char *)"true");
+ }
+ if (strings!=NULL)
+ (*record)->platform = strings;
+
+ (*record)->vcpus_params = xen_string_string_map_alloc(0);
+ (*record)->other_config = xen_string_string_map_alloc(0);
+ (*record)->last_boot_cpu_flags = xen_string_string_map_alloc(0);
+ (*record)->xenstore_data = xen_string_string_map_alloc(0);
+ (*record)->hvm_shadow_multiplier = 1.000;
+ if (!xen_vm_create(((struct _xenapiPrivate *)(conn->privateData))->session,
+ vm, *record)) {
+ xenapiSessionErrorHandler(conn,VIR_ERR_INTERNAL_ERROR,NULL);
+ return -1;
+ }
+
+ int device_number=0;
+ char *bridge=NULL,*mac=NULL;
+ int i;
+ for (i=0;i<def->nnets;i++) {
+ if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
+ if (def->nets[i]->data.bridge.brname)
+ if(!(bridge = strdup(def->nets[i]->data.bridge.brname)))
+ goto error_cleanup;
+ if (def->nets[i]->mac) {
+ char macStr[VIR_MAC_STRING_BUFLEN];
+ virFormatMacAddr(def->nets[i]->mac, macStr);
+ if(!(mac = strdup(macStr))) {
+ if (bridge) VIR_FREE(bridge);
+ goto error_cleanup;
+ }
+ }
+ if (mac!=NULL && bridge!=NULL) {
+ char device[NETWORK_DEVID_SIZE]="\0";
+ sprintf(device,"%d",device_number);
+ createVifNetwork(conn, *vm, device, bridge, mac);
+ VIR_FREE(bridge);
+ device_number++;
+ }
+ if (bridge) VIR_FREE(bridge);
+ /*if (mac!=NULL && bridge!=NULL) {
+ char device[NETWORK_DEVID_SIZE]="\0";
+ sprintf(device,"%d",device_number);
+ if (createVifNetwork(conn, *vm, device, bridge, mac)<0) {
+ VIR_FREE(mac);
+ VIR_FREE(bridge);
+ xen_vm_record_free(*record);
+ xenapiSessionErrorHandler(conn,VIR_ERR_INTERNAL_ERROR,NULL);
+ return -1;
+ }
+ VIR_FREE(bridge);
+ device_number++;
+ } else {
+ if (bridge)
+ VIR_FREE(bridge);
+ if (mac)
+ VIR_FREE(mac);
+ xen_vm_record_free(*record);
+ xenapiSessionErrorHandler(conn,VIR_ERR_INTERNAL_ERROR,NULL);
+ return -1;
+ }*/
+ }
+ }
+ return 0;
+
+ error_cleanup:
+ virReportOOMError();
+ xen_vm_record_free(*record);
+ return -1;
+}
+
diff -Nur ./libvirt_org/src/xenapi/xenapi_utils.h ./libvirt/src/xenapi/xenapi_utils.h
--- ./libvirt_org/src/xenapi/xenapi_utils.h 1970-01-01 01:00:00.000000000 +0100
+++ ./libvirt/src/xenapi/xenapi_utils.h 2010-03-03 18:01:19.000000000 +0000
@@ -0,0 +1,93 @@
+/*
+ * xenapi_utils.h: Xen API driver -- utils header
+ * Copyright (C) 2009 Citrix Ltd.
+ * Sharadha Prabhakar <sharadha.prabhakar(a)citrix.com>
+ */
+
+#ifndef _VIR_XENAPI_UTILS_
+#define _VIR_XENAPI_UTILS_
+
+#include <stdio.h>
+#include <string.h>
+#include <config.h>
+
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <libxml/uri.h>
+#include <xen_internal.h>
+#include <libxml/parser.h>
+#include <curl/curl.h>
+#include <xen/api/xen_common.h>
+#include <xen/api/xen_vm.h>
+#include <xen/api/xen_vm.h>
+#include <xen/api/xen_all.h>
+#include <xen/api/xen_vm_metrics.h>
+
+#include "libvirt_internal.h"
+#include "libvirt/libvirt.h"
+#include "virterror_internal.h"
+#include "datatypes.h"
+#include "conf/domain_conf.h"
+#include "xenapi_driver_private.h"
+#include "util.h"
+#include "uuid.h"
+#include "memory.h"
+#include "driver.h"
+#include "buf.h"
+
+#define NETWORK_DEVID_SIZE (10)
+
+typedef uint64_t cpumap_t;
+
+char *
+xenapiUtil_RequestPassword(virConnectAuthPtr auth, const char *username,
+ const char *hostname);
+
+int
+xenapiUtil_ParseQuery(virConnectPtr conn, xmlURIPtr uri, int *noVerify);
+
+enum xen_on_normal_exit
+actionShutdownLibvirt2XenapiEnum(enum virDomainLifecycleAction action);
+
+enum xen_on_crash_behaviour
+actionCrashLibvirt2XenapiEnum(enum virDomainLifecycleAction action);
+
+char *
+createXenAPIBootOrderString(int nboot, int *bootDevs);
+
+enum virDomainBootOrder map2LibvirtBootOrder(char c);
+
+enum virDomainLifecycleAction
+xenapiNormalExitEnum2virDomainLifecycle(enum xen_on_normal_exit action);
+
+enum virDomainLifecycleAction
+xenapiCrashExitEnum2virDomainLifecycle(enum xen_on_crash_behaviour action);
+
+void getCpuBitMapfromString(char *mask, unsigned char *cpumap, int maplen);
+
+int getStorageVolumeType(char *type);
+
+char *returnErrorFromSession(xen_session *session);
+
+virDomainState
+mapPowerState(enum xen_vm_power_state state);
+
+char *
+mapDomainPinVcpu(unsigned char *cpumap, int maplen);
+
+int
+createVMRecordFromXml (virConnectPtr conn, virDomainDefPtr defPtr,
+ xen_vm_record **record, xen_vm *vm);
+
+int
+allocStringMap (xen_string_string_map **strings, char *key, char *val);
+
+int
+createVifNetwork(virConnectPtr conn, xen_vm vm, char *device,
+ char *bridge, char *mac);
+
+#endif //_VIR_XENAPI_UTILS_
14 years, 8 months
[libvirt] Regarding SPICE
by anuj rampal
Hi,
I have set up KVM on FC12.
I was wondering if its possible to Display the VM using spice + libvirt?
As in, if I can define my domain with graphics like:
<graphics type='spice' port='-1' autoport='yes' listen='0.0.0.0'/>
or
<graphics type='spice' port='5903' ' listen='0.0.0.0'/>
Thanks & Regards
Anuj
14 years, 8 months
[libvirt] qemu aio option
by Ruben Kerkhof
Hi all,
Qemu has the command line parameter aio=(native|threads).
I don't see a way to pass this option from libvirt. Would it be
possible to add support for this option?
Ruben
14 years, 8 months