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_