This patch contains XenAPI driver specific files.
Files included are
xenapi_driver.c
xenapi_utils.c
xenapi_driver.h
xenapi_driver_private.h
xenapi_utils.h
This patch includes changes suggested in the first review.
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-02-26 15:27:00.000000000 +0000
@@ -0,0 +1,1564 @@
+
+/*
+ * 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 "esx/esx_util.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"
+
+char *url=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;
+
+ if (!STREQ(conn->uri->scheme,"XenAPI")) {
+ xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED ,"Check URI format:
'XenAPI://user@server'");
+ return VIR_DRV_OPEN_ERROR;
+ }
+ if (conn->uri->server==NULL) {
+ xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED ,"Server name not in
URI");
+ return VIR_DRV_OPEN_ERROR;
+ }
+ if (auth) {
+ passwd =
esxUtil_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;
+ }
+ virAsprintf(&url,"https://%s",conn->uri->server);
+ xmlInitParser();
+ xmlKeepBlanksDefault(0);
+ xen_init();
+ curl_global_init(CURL_GLOBAL_ALL);
+
+ session = xen_session_login_with_password (call_func, NULL, conn->uri->user,
passwd, xen_api_latest_version);
+
+ if ( session && session->ok ) {
+ if (VIR_ALLOC(privP)<0)
+ return VIR_DRV_OPEN_ERROR;
+ privP->session = session;
+ conn->privateData = privP;
+ return VIR_DRV_OPEN_SUCCESS;
+ } else {
+ xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED ,"");
+ 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);
+ VIR_FREE(conn->privateData);
+ VIR_FREE(url);
+ 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 ATTRIBUTE_UNUSED, unsigned long *hvVer)
+{
+ xen_host host;
+ xen_session *session = ((struct _xenapiPrivate
*)(conn->privateData))->session;
+ if (!(xen_session_get_this_host(session, &host,session))) {
+ xenapiSessionErrorHandler(conn, VIR_ERR_NO_DEVICE ,NULL);
+ return -1;
+ }
+ xen_string_string_map *result=NULL;
+ 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"))
+ version = strdup(result->contents[i].val);
+ }
+ if (version) {
+ unsigned long major=0,minor=0,release=0;
+ sscanf(version,"%ld.%ld.%ld",&major,&minor,&release);
+ *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_NO_DEVICE ,NULL);
+ return NULL;
+ }
+ xen_host_get_hostname(session, &result, host);
+ 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);
+ strncpy(info->model, modelname, LIBVIRT_MODELNAME_LEN-2);
+ info->model[LIBVIRT_MODELNAME_LEN-1]='\0';
+ 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;
+}
+
+static virCapsPtr
+getCapsObject(void)
+{
+ virCapsPtr caps;
+ if (VIR_ALLOC(caps) < 0)
+ return NULL;
+ caps->host.arch = strdup("x86_64");
+ caps->nguests = 2;
+ if (VIR_ALLOC_N(caps->guests,2) < 0)
+ return NULL;
+ int i;
+ for (i=0;i<2;i++) {
+ if (VIR_ALLOC(caps->guests[i]) < 0)
+ return NULL;
+ if (VIR_ALLOC_N(caps->guests[i]->arch.domains,1)<0)
+ return NULL;
+ if (VIR_ALLOC(caps->guests[i]->arch.domains[0])<0)
+ return NULL;
+ caps->guests[i]->arch.name = strdup("x86_64");
+ caps->guests[i]->arch.domains[0]->type = strdup("xen");
+ caps->guests[i]->arch.ndomains = 1;
+ }
+ caps->guests[0]->ostype = strdup("hvm");
+ caps->guests[1]->ostype = strdup("xen");
+ return caps;
+}
+
+
+/*
+* xenapiGetCapabilities:
+*
+*
+* Returns capabilities as an XML string
+*/
+static char *
+xenapiGetCapabilities (virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+ virCapsPtr caps = getCapsObject();
+ if (caps!=NULL) {
+ char *xml = virCapabilitiesFormatXML(caps);
+ VIR_FREE(caps);
+ return xml;
+ }
+ 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 */
+ int i,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_NO_DEVICE ,NULL);
+
+ if (result != NULL) {
+ 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);
+ }
+ list = result->size;
+ xen_vm_set_free(result);
+ return list;
+ }
+ 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_NO_DEVICE ,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 = getCapsObject();
+ if (!caps)
+ return NULL;
+
+ virDomainDefPtr defPtr = virDomainDefParseString(caps, xmlDesc, flags);
+ createVMRecordFromXml(conn, defPtr, &record, &vm);
+ if (record!=NULL) {
+ unsigned char raw_uuid[VIR_UUID_BUFLEN];
+ virUUIDParse(record->uuid,raw_uuid);
+ if (vm!=NULL) {
+ if (xen_vm_start(session, vm, false, false)) {
+ domP = virGetDomain(conn, record->name_label, raw_uuid);
+ 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!=NULL) {
+ int64_t domid=-1;
+ xen_vm_get_domid(session, &domid, result->contents[i]);
+ domP->id = domid;
+ }
+ xen_uuid_free(uuid);
+ xen_vm_record_free(record);
+ }
+ }
+ xen_vm_set_free(result);
+ } else {
+ xenapiSessionErrorHandler(conn, VIR_ERR_NO_DOMAIN ,NULL);
+ }
+ xen_host_free(host);
+ } else {
+ xenapiSessionErrorHandler(conn, VIR_ERR_NO_DEVICE ,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;
+ unsigned char raw_uuid[VIR_UUID_BUFLEN];
+ virDomainPtr domP=NULL;
+ xen_session *session = ((struct _xenapiPrivate
*)(conn->privateData))->session;
+ if (xen_vm_get_by_uuid(session, &vm, (char *)uuid)) {
+ xen_vm_get_record(session, &record, vm);
+ if (record != NULL) {
+ virUUIDParse((char *)uuid,raw_uuid);
+ domP = virGetDomain(conn, record->name_label, raw_uuid);
+ 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;
+ xen_vm_get_by_name_label(session, &vms, (char *)name);
+ if (vms!=NULL && vms->size!=0) {
+ 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;
+ }
+ }
+ }
+ if (!(session->ok))
+ xenapiSessionErrorHandler(conn, VIR_ERR_NO_DOMAIN, NULL);
+ else
+ xenapiSessionErrorHandler(conn, VIR_ERR_NO_DOMAIN,"Domain name not
found");
+ 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;
+ }
+ 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!=NULL && vms->size!=0) {
+ 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;
+ }
+ 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;
+ xen_vm_get_by_name_label(session, &vms, dom->name);
+ if (vms==NULL || vms->size==0) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
+ 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;
+ xen_vm_get_by_name_label(session, &vms, dom->name);
+ if (vms==NULL || vms->size==0) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
+ 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)
+{
+ /* vm.get_os-version */
+ int i;
+ xen_vm vm;
+ char *os_version=NULL;
+ xen_vm_record *record;
+ xen_string_string_map *result;
+ char uuid[VIR_UUID_STRING_BUFLEN];
+ xen_session *session = ((struct _xenapiPrivate
*)(dom->conn->privateData))->session;
+ virUUIDFormat(dom->uuid,uuid);
+ if (xen_vm_get_by_uuid(session, &vm, uuid)) {
+ xen_vm_get_record(session, &record, vm);
+ if (record) {
+ xen_vm_guest_metrics_get_os_version(session, &result,
record->guest_metrics->u.handle);
+ if (result) {
+ for (i=0; i<(result->size); i++) {
+ if (STREQ(result->contents[i].key, "distro")) {
+ if (STREQ(result->contents[i].val, "windows")) {
+ os_version = strdup("hvm");
+ } else {
+ os_version = strdup("xen");
+ }
+ }
+ }
+ xen_string_string_map_free(result);
+ } else
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_OS, NULL);
+ xen_vm_record_free(record);
+ } else
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
+ xen_vm_free(vm);
+ }
+ else
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
+ if ( os_version == NULL ) {
+ os_version = strdup("unknown");
+ }
+ return os_version;
+}
+
+/*
+* 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;
+ xen_vm_get_by_name_label(session, &vms, dom->name);
+ if (vms != NULL && vms->size!=0) {
+ /* vm.get_memory_static_max */
+ 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;
+ xen_vm_get_by_name_label(session, &vms, dom->name);
+ if (vms!=NULL && vms->size!=0) {
+ 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)) {
+ 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;
+ xen_vm_get_by_name_label(session, &vms, dom->name);
+ if (vms!=NULL && vms->size!=0) {
+ 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,
+ unsigned char *cpumap, int maplen)
+{
+ char *value;
+ xen_vm vm;
+ xen_vm_set *vms;
+ xen_session *session = ((struct _xenapiPrivate
*)(dom->conn->privateData))->session;
+ xen_vm_get_by_name_label(session, &vms, dom->name);
+ if (vms!=NULL && vms->size!=0) {
+ vm = vms->contents[0];
+ value = mapDomainPinVcpu(vcpu, 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);
+ return 0;
+ }
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+ xen_vm_set_free(vms);
+ }
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, 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) 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)) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
+ return -1;
+ }
+ vm = vms->contents[0];
+ if (!xen_vm_get_vcpus_params(session, &vcpu_params, vm)) {
+ 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")) {
+ mask = strdup(vcpu_params->contents[i].val);
+ }
+ }
+ 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);
+ }
+ 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)) {
+ 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;
+ struct _virDomainDef * defPtr = NULL;
+ if (VIR_ALLOC(defPtr)<0)
+ return NULL;
+
+ xen_vm_get_by_name_label(session, &vms, dom->name);
+ if (vms==NULL || vms->size==0) {
+ xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
+ return NULL;
+ }
+
+ vm = vms->contents[0];
+ defPtr->virtType = VIR_DOMAIN_VIRT_XEN;
+ defPtr->id = dom->id;
+ strcpy((char *)defPtr->uuid,(char *)dom->uuid);
+ defPtr->name = strdup(dom->name);
+
+ char *boot_policy=NULL;
+ xen_vm_get_hvm_boot_policy(session, &boot_policy, vm);
+ if (STREQ(boot_policy,"BIOS order")) {
+ defPtr->os.type = strdup("hvm");
+ 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 {
+ defPtr->os.type = strdup("linux");
+ defPtr->os.loader = strdup("pygrub");
+
+ char *value=NULL;
+ xen_vm_get_pv_kernel(session, &value, vm);
+ if (!STREQ(value,"")) {
+ defPtr->os.kernel = strdup(value);
+ VIR_FREE(value);
+ }
+ xen_vm_get_pv_ramdisk(session, &value, vm);
+ if (!STREQ(value,"")) {
+ defPtr->os.initrd = strdup(value);
+ VIR_FREE(value);
+ }
+ xen_vm_get_pv_args(session, &value, vm);
+ if (!STREQ(value,"")) {
+ defPtr->os.cmdline = strdup(value);
+ VIR_FREE(value);
+ }
+ VIR_FREE(boot_policy);
+ defPtr->os.bootloader = strdup("pygrub");
+ }
+ char *val=NULL;
+ xen_vm_get_pv_bootloader_args(session, &val, vm);
+ if (!STREQ(val,"")) {
+ defPtr->os.bootloaderArgs = strdup(val);
+ 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<<0);
+ else if (STREQ(result->contents[i].key,"apic"))
+ defPtr->features = defPtr->features | (1<<1);
+ else if (STREQ(result->contents[i].key,"pae"))
+ defPtr->features = defPtr->features | (1<<2);
+ }
+ }
+ 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) {
+ return NULL;
+ }
+ for (i=0; i<vif_set->size; i++) {
+ if (VIR_ALLOC(defPtr->nets[i])<0) {
+ return NULL;
+ }
+ 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 = strdup(bridge);
+ VIR_FREE(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);
+ return virDomainDefFormat(defPtr,0);
+}
+
+/*
+* 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;
+ usenames = strdup(record->name_label);
+ 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_NO_DEVICE, 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_NO_DEVICE, 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;
+ xen_vm_get_by_name_label(session, &vms, dom->name);
+ if (vms!=NULL && vms->size!=0) {
+ 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;
+ virCapsPtr caps = getCapsObject();
+ if (!caps)
+ return NULL;
+ virDomainDefPtr defPtr = virDomainDefParseString(caps, xml, 0);
+ if (!defPtr)
+ return NULL;
+ if(createVMRecordFromXml( conn, defPtr, &record, &vm)!=0) {
+ if (!(((struct _xenapiPrivate *)(conn->privateData))->session->ok))
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
+ else
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Couldn't
get VM information from XML");
+ 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==NULL && !(((struct _xenapiPrivate
*)(conn->privateData))->session->ok))
+ xenapiSessionErrorHandler(conn, VIR_ERR_NO_DOMAIN, NULL);
+ xen_vm_record_free(record);
+ }
+ else if (vm!=NULL)
+ xen_vm_free(vm);
+ 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;
+ }
+ 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;
+ }
+ 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;
+ }
+ 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;
+ return (char *)"credit";
+}
+
+/*
+* 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
ATTRIBUTE_UNUSED,
+ 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;
+ #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, 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, 1);
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 1);
+ 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-02-26 15:15:55.000000000
+0000
@@ -0,0 +1,44 @@
+/*
+ * 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>
+
+#define PRINT_XML
+#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;
+};
+
+#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-02-26 15:49:24.000000000 +0000
@@ -0,0 +1,433 @@
+/*
+ * 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"
+
+
+
+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 int vcpu, unsigned char *cpumap, int maplen)
+{
+ char buf[VIR_UUID_BUFLEN], mapstr[sizeof(cpumap_t) * 64];
+ char *ret=NULL;
+ int i, j;
+ mapstr[0] = 0;
+ for (i = 0; i < maplen; i++) {
+ for (j = 0; j < 8; j++) {
+ if (cpumap[i] & (1 << j)) {
+ snprintf(buf, sizeof(buf), "%d,", (8 * i) + j);
+ strcat(mapstr, buf);
+ }
+ }
+ }
+ mapstr[strlen(mapstr) - 1] = 0;
+ snprintf(buf, sizeof(buf), "%d", vcpu);
+ ret = strdup(mapstr);
+ 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) {
+ sscanf (num, "%d", &pos);
+ 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)
+ 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!=NULL) {
+ 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)
+{
+ *record = xen_vm_record_alloc();
+ (*record)->name_label = strdup(def->name);
+ if (STREQ(def->os.type,"hvm")) {
+ (*record)->hvm_boot_policy = strdup("BIOS order");
+ 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")) {
+ (*record)->pv_bootloader = strdup("pygrub");
+ (*record)->pv_kernel = def->os.kernel;
+ (*record)->pv_ramdisk = def->os.initrd;
+ (*record)->pv_args = def->os.cmdline;
+ (*record)->hvm_boot_params = xen_string_string_map_alloc(0);
+ }
+ if (def->os.bootloaderArgs)
+ (*record)->pv_bootloader_args = def->os.bootloaderArgs;
+
+ 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<<0))
+ allocStringMap(&strings,(char *)"acpi",(char
*)"true");
+ if (def->features & (1<<1))
+ allocStringMap(&strings,(char *)"apci",(char
*)"true");
+ if (def->features & (1<<2))
+ 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)
+ bridge = strdup(def->nets[i]->data.bridge.brname);
+ if (def->nets[i]->mac) {
+ char macStr[VIR_MAC_STRING_BUFLEN];
+ virFormatMacAddr(def->nets[i]->mac, macStr);
+ mac = strdup(macStr);
+ }
+ 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++;
+ }
+
+ }
+ }
+ return 0;
+}
+
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-02-26 13:24:19.000000000 +0000
@@ -0,0 +1,86 @@
+/*
+ * 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;
+
+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 int vcpu, 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_