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-18 16:26:13.000000000 +0000 @@ -0,0 +1,1774 @@ + +/* + * xenapi_driver.c: Xen API driver. + * Copyright (C) 2009 Citrix Ltd. + * Sharadha Prabhakar <sharadha.prabhakar@xxxxxxxxxx> +*/ + +#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 "xenapi_driver.h" +#include "util.h" +#include "uuid.h" +#include "memory.h" +#include "driver.h" +#include "buf.h" +#include "xenapi_utils.h" + +char *url; + +/* +*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 ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED) +{ + char *user,*passwd; + char delims[]=":"; + xen_session *session; + struct _xenapiPrivate *privP; + + if (!STREQ(conn->uri->scheme,"XenAPI")) { + xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED ,"Check URI format: 'XenAPI://user:password@server'", __FILE__, __FUNCTION__, __LINE__); + return VIR_DRV_OPEN_ERROR; + } + if (conn->uri->server==NULL) { + xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED ,"Server name not in URI", __FILE__, __FUNCTION__, __LINE__); + return VIR_DRV_OPEN_ERROR; + } + + user = strtok(conn->uri->user,delims); + passwd = strtok(NULL,delims); + + + + url = (char *)malloc(strlen("https://")+strlen(conn->uri->server)+1); + strcpy(url,"https://"); + strcat(url,conn->uri->server); + url[strlen("https://")+strlen(conn->uri->server)]='\0'; + + xmlInitParser(); + xmlKeepBlanksDefault(0); + xen_init(); + curl_global_init(CURL_GLOBAL_ALL); + + session = xen_session_login_with_password( call_func, NULL, user, passwd, xen_api_latest_version); + + if ( session != NULL && session->ok ) { + privP = malloc(sizeof(struct _xenapiPrivate)); + privP->session = session; + conn->privateData = privP; + return VIR_DRV_OPEN_SUCCESS; + } else { + xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED ,"", __FILE__, __FUNCTION__, __LINE__); + 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); + 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) +{ + *hvVer = 1; + return 0; +} + + +/* +* xenapiGetHostname: +* +* +* Returns the hostname on success, or NULL on failure +*/ +static char * +xenapiGetHostname (virConnectPtr conn) +{ + char *result; + xen_host host; + + if (!(xen_session_get_this_host(((struct _xenapiPrivate *)(conn->privateData))->session, &host, + ((struct _xenapiPrivate *)(conn->privateData))->session))) { + if (!(((struct _xenapiPrivate *)(conn->privateData))->session->ok)) + xenapiSessionErrorHandler(conn, VIR_ERR_NO_DEVICE ,NULL, __FILE__, __FUNCTION__, __LINE__); + else + xenapiSessionErrorHandler(conn, VIR_ERR_NO_DEVICE ,"Unable to find host", __FILE__, __FUNCTION__, __LINE__); + return NULL; + } + xen_host_get_hostname(((struct _xenapiPrivate *)(conn->privateData))->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; + info->nodes = 1; + info->threads = 1; + info->sockets = 1; + + if (xen_host_metrics_get_all(((struct _xenapiPrivate *)(conn->privateData))->session, + &xen_met_set)) { + xen_host_metrics_get_memory_total(((struct _xenapiPrivate *)(conn->privateData))->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", + __FILE__, __FUNCTION__, __LINE__); + return -1; + } + if (xen_host_cpu_get_all(((struct _xenapiPrivate *)(conn->privateData))->session, + &host_cpu_set)) { + host_cpu = host_cpu_set->contents[0]; + xen_host_cpu_get_modelname(((struct _xenapiPrivate *)(conn->privateData))->session, + &modelname, host_cpu); + strncpy(info->model, modelname, LIBVIRT_MODELNAME_LEN-2); + info->model[LIBVIRT_MODELNAME_LEN-1]='\0'; + xen_host_cpu_get_speed(((struct _xenapiPrivate *)(conn->privateData))->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); + free(modelname); + return 0; + } + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR ,"Unable to get Host CPU set", + __FILE__, __FUNCTION__, __LINE__); + return -1; +} + + +/* +* xenapiGetCapabilities: +* +* +* Returns capabilities as an XML string +*/ +static char * +xenapiGetCapabilities (virConnectPtr conn ATTRIBUTE_UNUSED) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + virBufferAddLit(&buf, "<capabilities>\n"); + virBufferAddLit(&buf, "<host>\n"); + virBufferAddLit(&buf, " <cpu></cpu>\n"); + virBufferAddLit(&buf, "</host>"); + virBufferAddLit(&buf, "<guest>\n"); + virBufferAddLit(&buf, "<os_type>hvm</os_type>\n"); + virBufferAddLit(&buf, "<arch>\n"); + virBufferAddLit(&buf, "<domain type='xenapi'></domain>\n"); + virBufferAddLit(&buf, "</arch>\n"); + virBufferAddLit(&buf, "</guest>\n"); + virBufferAddLit(&buf, "</capabilities>\n"); + return virBufferContentAndReset(&buf); +} + +/* +* 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; + if (xen_session_get_this_host(((struct _xenapiPrivate *)(conn->privateData))->session, &host, + ((struct _xenapiPrivate *)(conn->privateData))->session)) { + xen_host_get_resident_vms(((struct _xenapiPrivate *)(conn->privateData))->session, &result, host); + xen_host_free(host); + } else { + xenapiSessionErrorHandler(conn, VIR_ERR_NO_DEVICE ,NULL, __FILE__, __FUNCTION__, __LINE__); + } + if (result != NULL) { + for ( i=0; (i < (result->size)) && (i<maxids) ; i++ ) { + int64_t t0; + xen_vm_get_domid(((struct _xenapiPrivate *)(conn->privateData))->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_get_this_host(((struct _xenapiPrivate *)(conn->privateData))->session, &host, + ((struct _xenapiPrivate *)(conn->privateData))->session); + if ( host!=NULL ) { + xen_host_get_resident_vms(((struct _xenapiPrivate *)(conn->privateData))->session, &result, host); + if ( result != NULL) { + numDomains = result->size; + xen_vm_set_free(result); + } + xen_host_free(host); + } + if (!(((struct _xenapiPrivate *)(conn->privateData))->session->ok)) + xenapiSessionErrorHandler(conn, VIR_ERR_NO_DEVICE ,NULL, __FILE__, __FUNCTION__, __LINE__); + 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; + createVMRecordFromXml( conn, xmlDesc, &record, &vm); + if (record!=NULL) { + unsigned char raw_uuid[RAW_UUID_BUFLEN]; + virUUIDParse(record->uuid,raw_uuid); + if (vm!=NULL) { + if (xen_vm_start(((struct _xenapiPrivate *)(conn->privateData))->session, + vm, false, false)) { + domP = virGetDomain(conn, record->name_label, raw_uuid); + xen_vm_free(vm); + } + else + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL, __FILE__, __FUNCTION__, __LINE__); + } + xen_vm_record_free(record); + } + else + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL, __FILE__, __FUNCTION__, __LINE__); + 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[RAW_UUID_BUFLEN]; + virDomainPtr domP=NULL; + + xen_session_get_this_host(((struct _xenapiPrivate *)(conn->privateData))->session, &host, + ((struct _xenapiPrivate *)(conn->privateData))->session); + if (host!=NULL && ((struct _xenapiPrivate *)(conn->privateData))->session->ok) { + xen_host_get_resident_vms(((struct _xenapiPrivate *)(conn->privateData))->session, &result, host); + if ( result !=NULL ) { + for( i=0; i < (result->size); i++) { + xen_vm_get_domid(((struct _xenapiPrivate *)(conn->privateData))->session, &domID, result->contents[i]); + if ( domID == id ) { + xen_vm_get_record(((struct _xenapiPrivate *)(conn->privateData))->session, + &record, result->contents[i]); + xen_vm_get_uuid(((struct _xenapiPrivate *)(conn->privateData))->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(((struct _xenapiPrivate *)(conn->privateData))->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, __FILE__, __FUNCTION__, __LINE__); + } + xen_host_free(host); + } else { + xenapiSessionErrorHandler(conn, VIR_ERR_NO_DEVICE ,NULL, __FILE__, __FUNCTION__, __LINE__); + } + 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[RAW_UUID_BUFLEN]; + virDomainPtr domP=NULL; + if (xen_vm_get_by_uuid(((struct _xenapiPrivate *)(conn->privateData))->session, + &vm, (char *)uuid)) { + xen_vm_get_record(((struct _xenapiPrivate *)(conn->privateData))->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, __FILE__, __FUNCTION__, __LINE__); + xen_vm_free(vm); + } else + xenapiSessionErrorHandler(conn, VIR_ERR_NO_DOMAIN ,NULL, __FILE__, __FUNCTION__, __LINE__); + 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[RAW_UUID_BUFLEN]; + virDomainPtr domP=NULL; + + xen_vm_get_by_name_label(((struct _xenapiPrivate *)(conn->privateData))->session, + &vms, (char *)name); + if (vms!=NULL && vms->size!=0) { + vm = vms->contents[0]; + xen_vm_get_uuid(((struct _xenapiPrivate *)(conn->privateData))->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(((struct _xenapiPrivate *)(conn->privateData))->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 (!(((struct _xenapiPrivate *)(conn->privateData))->session->ok)) { + xenapiSessionErrorHandler(conn, VIR_ERR_NO_DOMAIN, NULL, __FILE__, __FUNCTION__, __LINE__); + } + return NULL; + } + } + } + if (!(((struct _xenapiPrivate *)(conn->privateData))->session->ok)) { + xenapiSessionErrorHandler(conn,VIR_ERR_NO_DOMAIN,NULL,__FILE__,__FUNCTION__, __LINE__); + } else { + xenapiSessionErrorHandler(conn,VIR_ERR_NO_DOMAIN,"Domain name not found",__FILE__,__FUNCTION__, __LINE__); + } + 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; + if (!xen_vm_get_by_name_label(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &vms, dom->name)) { + xenapiSessionErrorHandler(dom->conn,VIR_ERR_NO_DOMAIN,NULL,__FILE__,__FUNCTION__, __LINE__); + return -1; + } + vm = vms->contents[0]; + if (!xen_vm_pause(((struct _xenapiPrivate *)(dom->conn->privateData))->session, vm)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL, __FILE__, __FUNCTION__, __LINE__); + 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; + if (!xen_vm_get_by_name_label(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &vms, dom->name)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL, __FILE__, __FUNCTION__, __LINE__); + return -1; + } + if (vms!=NULL && vms->size!=0) { + vm = vms->contents[0]; + if (!xen_vm_unpause(((struct _xenapiPrivate *)(dom->conn->privateData))->session, vm)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL, __FILE__, __FUNCTION__, __LINE__); + 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; + if(!xen_vm_get_by_name_label(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &vms, dom->name)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL, __FILE__, __FUNCTION__, __LINE__); + return -1; + } + vm = vms->contents[0]; + if (!xen_vm_clean_shutdown(((struct _xenapiPrivate *)(dom->conn->privateData))->session, vm)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL, __FILE__, __FUNCTION__, __LINE__); + 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_vm_get_by_name_label(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &vms, dom->name); + if (vms==NULL || vms->size==0) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL, __FILE__, __FUNCTION__, __LINE__); + return -1; + } + vm = vms->contents[0]; + if (!xen_vm_clean_reboot(((struct _xenapiPrivate *)(dom->conn->privateData))->session, vm)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL, __FILE__, __FUNCTION__, __LINE__); + 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_vm_get_by_name_label(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &vms, dom->name); + if (vms==NULL || vms->size==0) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL, __FILE__, __FUNCTION__, __LINE__); + return -1; + } + vm = vms->contents[0]; + if (!xen_vm_hard_shutdown(((struct _xenapiPrivate *)(dom->conn->privateData))->session, vm)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL, __FILE__, __FUNCTION__, __LINE__); + 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]; + virUUIDFormat(dom->uuid,uuid); + if (xen_vm_get_by_uuid(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &vm, uuid)) { + xen_vm_get_record(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &record, vm); + if (record!=NULL) { + xen_vm_guest_metrics_get_os_version(((struct _xenapiPrivate *)(dom->conn->privateData))->session, &result, + record->guest_metrics->u.handle); + if (result != NULL) { + for (i=0; i<(result->size); i++) { + if (STREQ(result->contents[i].key, "distro")) { + if (STREQ(result->contents[i].val, "windows")) { + os_version = strdup(result->contents[i].val); + } else { + os_version = strdup("linux"); + } + } + } + xen_string_string_map_free(result); + } else + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_OS, NULL, __FILE__, __FUNCTION__, __LINE__); + xen_vm_record_free(record); + } else + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL, __FILE__, __FUNCTION__, __LINE__); + xen_vm_free(vm); + } + else + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL, __FILE__, __FUNCTION__, __LINE__); + 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_vm_get_by_name_label(((struct _xenapiPrivate *)(dom->conn->privateData))->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(((struct _xenapiPrivate *)(dom->conn->privateData))->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, __FILE__, __FUNCTION__, __LINE__); + 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_vm_get_by_name_label(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &vms, dom->name); + if (vms!=NULL && vms->size!=0) { + vm = vms->contents[0]; + if (!(xen_vm_set_memory_static_max(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + vm, memory))) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL, __FILE__, __FUNCTION__, __LINE__); + xen_vm_set_free(vms); + return -1; + } + xen_vm_set_free(vms); + } else { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL, __FILE__, __FUNCTION__, __LINE__); + return -1; + } + return 0; +} + +static int +xenapiDomainSetMemory (virDomainPtr dom, unsigned long memory ATTRIBUTE_UNUSED) +{ + /* XenAPI doesn't allow this function */ + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_SUPPORT, "", __FILE__, __FUNCTION__, __LINE__); + return -1; +} + +/* +* 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; + info->cpuTime = 0; /* CPU time is not advertised */ + if (xen_vm_get_by_name_label(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &vms, dom->name)) { + vm = vms->contents[0]; + xen_vm_get_memory_static_max(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &maxmem, vm); + info->maxMem = (maxmem/1024); + enum xen_vm_power_state state = XEN_VM_POWER_STATE_UNKNOWN; + xen_vm_get_power_state(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &state, vm); + info->state = mapPowerState(state); + xen_vm_get_record(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &record, vm); + if (record!=NULL) { + xen_vm_metrics_get_memory_actual(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &memory, record->metrics->u.handle); + info->memory = (memory/1024); + xen_vm_record_free(record); + } + xen_vm_get_vcpus_max(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &vcpu, vm); + info->nrVirtCpu = vcpu; + xen_vm_set_free(vms); + return 0; + } + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL, __FILE__, __FUNCTION__, __LINE__); + return -1; +} + +/* +* xenapiDomainSave +* +* suspends a VM +* Return 0 on success or -1 in case of error +*/ +static int +xenapiDomainSave (virDomainPtr dom, const char *to ATTRIBUTE_UNUSED) +{ + int ret_code = -1; + ret_code = xenapiDomainSuspend(dom); + return ret_code; +} + +/* +* xenapiDomainRestore +* +* Resumes a VM +* Return 0 on success or -1 in case of error +*/ +static int +xenapiDomainRestore (virConnectPtr conn, const char *from ATTRIBUTE_UNUSED) +{ + /* resume from : NI */ + xen_vm_set *result=NULL; + xen_host host=NULL; + xen_vm_record *record = NULL; + unsigned char raw_uuid[RAW_UUID_BUFLEN]; + virDomainPtr domP=NULL; + int ret_code=-1; + + xen_session_get_this_host(((struct _xenapiPrivate *)(conn->privateData))->session, &host, + ((struct _xenapiPrivate *)(conn->privateData))->session); + if ( host!=NULL ) { + xen_host_get_resident_vms(((struct _xenapiPrivate *)(conn->privateData))->session, &result, host); + if ( result != NULL ) { + xen_vm_get_record(((struct _xenapiPrivate *)(conn->privateData))->session, + &record, result->contents[0]); + if (record!=NULL) { + virUUIDParse(record->uuid,raw_uuid); + domP = virGetDomain(conn, record->name_label, raw_uuid); + if (domP!=NULL) + ret_code = xenapiDomainResume(domP); + else + xenapiSessionErrorHandler(conn, VIR_ERR_NO_DOMAIN, NULL, __FILE__, __FUNCTION__, __LINE__); + xen_vm_record_free(record); + } + xen_vm_set_free(result); + } + xen_host_free(host); + } + if (!(((struct _xenapiPrivate *)(conn->privateData))->session->ok)) + xenapiSessionErrorHandler(conn, VIR_ERR_NO_DOMAIN, NULL, __FILE__, __FUNCTION__, __LINE__); + return ret_code; +} + +static int +xenapiDomainCoreDump (virDomainPtr dom, const char *to ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED) +{ + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_SUPPORT, NULL, __FILE__, __FUNCTION__, __LINE__); + 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_vm_get_by_name_label(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &vms, dom->name); + if (vms!=NULL && vms->size!=0) { + vm = vms->contents[0]; + if (xen_vm_set_vcpus_number_live(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + vm, (int64_t)nvcpus)) { + xen_vm_set_free(vms); + return 0; + } + } + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL, __FILE__, __FUNCTION__, __LINE__); + 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_vm_get_by_name_label(((struct _xenapiPrivate *)(dom->conn->privateData))->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(((struct _xenapiPrivate *)(dom->conn->privateData))->session, vm, (char *)"mask"); + if (xen_vm_add_to_vcpus_params(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + vm, (char *)"mask", value)) { + xen_vm_set_free(vms); + return 0; + } + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL, __FILE__, __FUNCTION__, __LINE__); + xen_vm_set_free(vms); + } + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL, __FILE__, __FUNCTION__, __LINE__); + 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; + char *mask=NULL; + if((cpumaps!=NULL) && (maplen < 1)) + return -1; + domInfo =(struct _virDomainInfo *) malloc(sizeof(struct _virDomainInfo)); + if (virDomainGetInfo(dom,domInfo)==0) { + nvcpus = domInfo->nrVirtCpu; + free(domInfo); + } else { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Couldn't fetch Domain Information", + __FILE__, __FUNCTION__, __LINE__); + return -1; + } + if ( virNodeGetInfo(dom->conn,&nodeInfo)==0) + cpus = nodeInfo.cpus; + else { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Couldn't fetch Node Information", + __FILE__, __FUNCTION__, __LINE__); + return -1; + } + if(nvcpus > maxinfo) nvcpus = maxinfo; + + if (cpumaps != NULL) + memset(cpumaps, 0, maxinfo * maplen); + + if (!xen_vm_get_by_name_label(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &vms, dom->name)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL, __FILE__, __FUNCTION__, __LINE__); + return -1; + } + vm = vms->contents[0]; + if (!xen_vm_get_vcpus_params(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &vcpu_params, vm)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL, __FILE__, __FUNCTION__, __LINE__); + 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; + + if (xen_vm_get_by_name_label(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &vms, dom->name)) { + vm = vms->contents[0]; + xen_vm_get_power_state(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &state, vm); + if(state == XEN_VM_POWER_STATE_RUNNING) { + xen_vm_get_vcpus_max(((struct _xenapiPrivate *)(dom->conn->privateData))->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, __FILE__, __FUNCTION__, __LINE__); + 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) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + char uuid_string[VIR_UUID_STRING_BUFLEN]; + xen_vm vm=NULL; + xen_vm_set *vms; + xen_string_string_map *result=NULL; + + xen_vm_get_by_name_label(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &vms, dom->name); + if (vms==NULL || vms->size==0) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL, __FILE__, __FUNCTION__, __LINE__); + return NULL; + } + + vm = vms->contents[0]; + virBufferAddLit(&buf, "<domain type='xenapi'>\n"); + virBufferEscapeString(&buf, " <name>%s</name>\n", "testVM"); + virUUIDFormat(dom->uuid,uuid_string); + virBufferEscapeString(&buf, " <uuid>%s</uuid>\n",uuid_string); + + + virBufferAddLit(&buf, " <os>\n"); + char *boot_policy=NULL; + xen_vm_get_hvm_boot_policy(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &boot_policy, vm); + if (STREQ(boot_policy,"BIOS order")) { + virBufferAddLit(&buf, " <type>hvm</type>\n"); + xen_vm_get_hvm_boot_params(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &result, vm); + if (result!=NULL) { + int i; + for (i=0; i<(result->size); i++) { + if (STREQ(result->contents[i].key,"order")) { + int j=0; + while(result->contents[i].val[j]!='\0') { + virBufferEscapeString(&buf, " <boot dev='%s' />\n", + mapXmlBootOrder(result->contents[i].val[j])); + j++; + } + } + } + xen_string_string_map_free(result); + } + VIR_FREE(boot_policy); + } else { + virBufferAddLit(&buf, " <type>linux</type>\n"); + virBufferAddLit(&buf, " <loader>pygrub</loader>\n"); + char *value=NULL; + xen_vm_get_pv_kernel(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &value, vm); + if (!STREQ(value,"")) { + virBufferEscapeString(&buf," <kernel>%s</kernel>\n",value); + VIR_FREE(value); + } + xen_vm_get_pv_ramdisk(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &value, vm); + if (!STREQ(value,"")) { + virBufferEscapeString(&buf," <initrd>%s</initrd>\n",value); + VIR_FREE(value); + } + xen_vm_get_pv_args(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &value, vm); + if (!STREQ(value,"")) { + virBufferEscapeString(&buf," <cmdline>%s</cmdline>\n",value); + VIR_FREE(value); + } + VIR_FREE(boot_policy); + } + virBufferAddLit(&buf, " </os>\n"); + virBufferAddLit(&buf, " <bootloader>pygrub</bootloader>\n"); + char *val=NULL; + xen_vm_get_pv_bootloader_args(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &val, vm); + if (!STREQ(val,"")) { + virBufferEscapeString(&buf," <bootloader_args>%s</bootloader_args>\n",val); + VIR_FREE(val); + } + unsigned long memory=0; + memory = xenapiDomainGetMaxMemory(dom); + virBufferVSprintf(&buf," <memory>%lu</memory>\n",memory); + int64_t dynamic_mem=0; + if (xen_vm_get_memory_dynamic_max(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &dynamic_mem, vm)) { + virBufferVSprintf(&buf," <currentmemory>%lld</currentmemory>\n",(dynamic_mem/1024)); + } else { + virBufferVSprintf(&buf," <currentmemory>%lu</currentmemory>\n",memory); + } + virBufferVSprintf(&buf," <vcpu>%d</vcpu>\n",xenapiDomainGetMaxVcpus(dom)); + enum xen_on_normal_exit action; + if (xen_vm_get_actions_after_shutdown(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &action, vm)) { + virBufferEscapeString(&buf," <on_poweroff>%s</on_poweroff>\n",xen_on_normal_exit_to_string(action)); + } + if (xen_vm_get_actions_after_reboot(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &action, vm)) { + virBufferEscapeString(&buf," <on_reboot>%s</on_reboot>\n",xen_on_normal_exit_to_string(action)); + } + enum xen_on_crash_behaviour crash; + if (xen_vm_get_actions_after_crash(((struct _xenapiPrivate *)(dom->conn->privateData))->session, &crash, vm)) { + virBufferEscapeString(&buf," <on_crash>%s</on_crash>\n",xen_on_crash_behaviour_to_string(crash)); + } + xen_vm_get_platform(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &result, vm); + if (result!=NULL) { + int i; + virBufferAddLit(&buf, " <features>\n"); + for(i=0; i< (result->size); i++) { + if (STREQ(result->contents[i].val,"true")) { + virBufferVSprintf(&buf," <%s/>\n",result->contents[i].key); + } + } + virBufferAddLit(&buf, " </features>\n"); + xen_string_string_map_free(result); + } + struct xen_vif_set *vif_set=NULL; + xen_vm_get_vifs(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &vif_set, vm); + if (vif_set) { + int i; + xen_vif vif; + xen_vif_record *vif_rec=NULL; + xen_network network; + char *bridge=NULL; + for (i=0; i<vif_set->size; i++) { + virBufferAddLit(&buf, " <interface type='bridge'>\n"); + vif = vif_set->contents[i]; + xen_vif_get_network(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &network, vif); + if (network!=NULL) { + xen_network_get_bridge(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &bridge, network); + if (bridge!=NULL) { + virBufferEscapeString(&buf," <source bridge='%s' />\n",bridge); + VIR_FREE(bridge); + } + xen_network_free(network); + } + xen_vif_get_record(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &vif_rec, vif); + if (vif_rec!=NULL) { + virBufferEscapeString(&buf," <mac address='%s' />\n", vif_rec->mac); + xen_vif_record_free(vif_rec); + } + virBufferAddLit(&buf, " </interface>\n"); + } + xen_vif_set_free(vif_set); + } + virBufferAddLit(&buf, "</domain>"); + if (vms) xen_vm_set_free(vms); + return virBufferContentAndReset(&buf); +} + +static char * +xenapiDomainXMLFromNative(virConnectPtr conn, + const char *format ATTRIBUTE_UNUSED, + const char *config ATTRIBUTE_UNUSED, + unsigned int flags ATTRIBUTE_UNUSED) +{ + xenapiSessionErrorHandler(conn, VIR_ERR_NO_SUPPORT, "", __FILE__, __FUNCTION__, __LINE__); + return NULL; +} + + +static char * +xenapiDomainXMLToNative(virConnectPtr conn, + const char *format ATTRIBUTE_UNUSED, + const char *xmlData ATTRIBUTE_UNUSED, + unsigned int flags ATTRIBUTE_UNUSED) +{ + xenapiSessionErrorHandler(conn, VIR_ERR_NO_SUPPORT, "", __FILE__, __FUNCTION__, __LINE__); + 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_vm_get_all(((struct _xenapiPrivate *)(conn->privateData))->session, &result); + if (result != NULL) { + for (i=0; i< (result->size) && j< maxnames; i++) { + xen_vm_get_record(((struct _xenapiPrivate *)(conn->privateData))->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", __FILE__, __FUNCTION__, __LINE__); + xen_vm_set_free(result); + return -1; + } + } + doms=j; + xen_vm_set_free(result); + return doms; + } + xenapiSessionErrorHandler(conn, VIR_ERR_NO_DEVICE, NULL, __FILE__, __FUNCTION__, __LINE__); + 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_vm_get_all(((struct _xenapiPrivate *)(conn->privateData))->session, &result); + if ( result != NULL) { + for ( i=0; i< (result->size); i++ ) { + xen_vm_get_record(((struct _xenapiPrivate *)(conn->privateData))->session, + &record, result->contents[i]); + if (record==NULL && !(((struct _xenapiPrivate *)(conn->privateData))->session->ok)) { + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL, __FILE__, __FUNCTION__, __LINE__); + 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, __FILE__, __FUNCTION__, __LINE__); + 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_vm_get_by_name_label(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &vms, dom->name); + if (vms!=NULL && vms->size!=0) { + vm = vms->contents[0]; + if (!xen_vm_start(((struct _xenapiPrivate *)(dom->conn->privateData))->session, vm, false, false)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL, __FILE__, __FUNCTION__, __LINE__); + xen_vm_set_free(vms); + return -1; + } + xen_vm_set_free(vms); + } else { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL, __FILE__, __FUNCTION__, __LINE__); + 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; + if(createVMRecordFromXml( conn, xml, &record, &vm)!=0) { + if (!(((struct _xenapiPrivate *)(conn->privateData))->session->ok)) + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL, __FILE__, __FUNCTION__, __LINE__); + else + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Couldn't get VM information from XML", + __FILE__, __FUNCTION__, __LINE__); + return NULL; + } + if (record!=NULL) { + unsigned char raw_uuid[RAW_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, __FILE__, __FUNCTION__, __LINE__); + 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; + if (!xen_vm_get_by_name_label(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &vms, dom->name)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL, __FILE__, __FUNCTION__, __LINE__); + return -1; + } + vm = vms->contents[0]; + if (!xen_vm_destroy(((struct _xenapiPrivate *)(dom->conn->privateData))->session, vm)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL, __FILE__, __FUNCTION__, __LINE__); + xen_vm_set_free(vms); + return -1; + } + xen_vm_set_free(vms); + return 0; +} + +static int +xenapiDomainAttachDevice (virDomainPtr dom, const char *xml ATTRIBUTE_UNUSED) +{ + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_SUPPORT, "", __FILE__, __FUNCTION__, __LINE__); + return -1; +} + +static int +xenapiDomainDetachDevice (virDomainPtr dom, const char *xml ATTRIBUTE_UNUSED) +{ + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_SUPPORT, "", __FILE__, __FUNCTION__, __LINE__); + return -1; +} + +/* +* 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; + if(!xen_vm_get_by_name_label(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &vms, dom->name)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL, __FILE__, __FUNCTION__, __LINE__); + return -1; + } + vm = vms->contents[0]; + if (!xen_vm_get_other_config(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &result, vm)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL, __FILE__, __FUNCTION__, __LINE__); + 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; + if (!xen_vm_get_by_name_label(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + &vms, dom->name)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL, __FILE__, __FUNCTION__, __LINE__); + return -1; + } + vm = vms->contents[0]; + xen_vm_remove_from_other_config(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + vm, (char *)"auto_poweron"); + if (autostart==1) + value = (char *)"true"; + else + value = (char *)"false"; + if (!xen_vm_add_to_other_config(((struct _xenapiPrivate *)(dom->conn->privateData))->session, + vm, (char *)"auto_poweron", value)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL, __FILE__, __FUNCTION__, __LINE__); + 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"; +} + +static int +xenapiDomainGetSchedulerParameters (virDomainPtr dom, + virSchedParameterPtr params ATTRIBUTE_UNUSED, + int *nparams ATTRIBUTE_UNUSED) +{ + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_SUPPORT, "", __FILE__, __FUNCTION__, __LINE__); + return -1; +} + +static int +xenapiDomainSetSchedulerParameters (virDomainPtr dom, + virSchedParameterPtr params ATTRIBUTE_UNUSED, + int nparams ATTRIBUTE_UNUSED) +{ + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_SUPPORT, "", __FILE__, __FUNCTION__, __LINE__); + return -1; +} + +static int +xenapiDomainMigratePrepare (virConnectPtr dconn, + char **cookie ATTRIBUTE_UNUSED, + int *cookielen ATTRIBUTE_UNUSED, + const char *uri_in ATTRIBUTE_UNUSED, + char **uri_out ATTRIBUTE_UNUSED, + unsigned long flags ATTRIBUTE_UNUSED, + const char *dname ATTRIBUTE_UNUSED, + unsigned long resource ATTRIBUTE_UNUSED) +{ + xenapiSessionErrorHandler(dconn, VIR_ERR_NO_SUPPORT, "", __FILE__, __FUNCTION__, __LINE__); + return -1; +} + +static int +xenapiDomainMigratePerform (virDomainPtr dom, + const char *cookie ATTRIBUTE_UNUSED, + int cookielen ATTRIBUTE_UNUSED, + const char *uri ATTRIBUTE_UNUSED, + unsigned long flags ATTRIBUTE_UNUSED, + const char *dname ATTRIBUTE_UNUSED, + unsigned long resource ATTRIBUTE_UNUSED) +{ + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_SUPPORT, "", __FILE__, __FUNCTION__, __LINE__); + return -1; +} + +static virDomainPtr +xenapiDomainMigrateFinish (virConnectPtr dconn, + const char *dname, + const char *cookie ATTRIBUTE_UNUSED, + int cookielen ATTRIBUTE_UNUSED, + const char *uri ATTRIBUTE_UNUSED, + unsigned long flags ATTRIBUTE_UNUSED) +{ + return xenapiDomainLookupByName (dconn, dname); +} + +static int +xenapiDomainBlockStats (virDomainPtr dom, const char *path ATTRIBUTE_UNUSED, + struct _virDomainBlockStats *stats ATTRIBUTE_UNUSED) +{ + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_SUPPORT, "", __FILE__, __FUNCTION__, __LINE__); + return -1; +} + +static int +xenapiDomainInterfaceStats (virDomainPtr dom, const char *path ATTRIBUTE_UNUSED, + struct _virDomainInterfaceStats *stats ATTRIBUTE_UNUSED) +{ + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_SUPPORT, "", __FILE__, __FUNCTION__, __LINE__); + return -1; +} + +static int +xenapiDomainBlockPeek (virDomainPtr dom, const char *path ATTRIBUTE_UNUSED, + unsigned long long offset ATTRIBUTE_UNUSED, size_t size ATTRIBUTE_UNUSED, + void *buffer ATTRIBUTE_UNUSED, unsigned int flags ATTRIBUTE_UNUSED) +{ + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_SUPPORT, "", __FILE__, __FUNCTION__, __LINE__); + return -1; +} + +/* +* 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_host_metrics_get_all(((struct _xenapiPrivate *)(conn->privateData))->session, + &xen_met_set); + if (xen_met_set != NULL) { + if (!xen_host_metrics_get_memory_free(((struct _xenapiPrivate *)(conn->privateData))->session, + (int64_t *)&freeMem, xen_met_set->contents[0])) { + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Couldn't get host metrics - memory information", + __FILE__, __FUNCTION__, __LINE__); + freeMem=0; + } + xen_host_metrics_set_free(xen_met_set); + } else { + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Couldn't get host metrics", + __FILE__, __FUNCTION__, __LINE__); + } + 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, "", __FILE__, __FUNCTION__, __LINE__); + return -1; + } else { + freeMems[0] = xenapiNodeGetFreeMemory(conn); + return 1; + } +} + + +static int +xenapiDomainEventRegister (virConnectPtr conn, + virConnectDomainEventCallback callback ATTRIBUTE_UNUSED, + void *opaque ATTRIBUTE_UNUSED, + void (*freefunc)(void *) ATTRIBUTE_UNUSED) +{ + xenapiSessionErrorHandler(conn, VIR_ERR_NO_SUPPORT, "", __FILE__, __FUNCTION__, __LINE__); + return -1; +} + +static int +xenapiDomainEventDeregister (virConnectPtr conn, + virConnectDomainEventCallback callback ATTRIBUTE_UNUSED) +{ + xenapiSessionErrorHandler(conn, VIR_ERR_NO_SUPPORT, "", __FILE__, __FUNCTION__, __LINE__); + return -1; +} + +static int +xenapiNodeDeviceDettach (virNodeDevicePtr dev) +{ + xenapiSessionErrorHandler(dev->conn, VIR_ERR_NO_SUPPORT, "", __FILE__, __FUNCTION__, __LINE__); + return -1; +} + +static int +xenapiNodeDeviceReAttach (virNodeDevicePtr dev) +{ + xenapiSessionErrorHandler(dev->conn, VIR_ERR_NO_SUPPORT, "", __FILE__, __FUNCTION__, __LINE__); + return -1; +} + +static int +xenapiNodeDeviceReset (virNodeDevicePtr dev) +{ + xenapiSessionErrorHandler(dev->conn, VIR_ERR_NO_SUPPORT, "", __FILE__, __FUNCTION__, __LINE__); + 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 */ + xenapiDomainSetMemory, /* domainSetMemory */ + xenapiDomainGetInfo, /* domainGetInfo */ + xenapiDomainSave, /* domainSave */ + xenapiDomainRestore, /* domainRestore */ + xenapiDomainCoreDump, /* domainCoreDump */ + xenapiDomainSetVcpus, /* domainSetVcpus */ + xenapiDomainPinVcpu, /* domainPinVcpu */ + xenapiDomainGetVcpus, /* domainGetVcpus */ + xenapiDomainGetMaxVcpus, /* domainGetMaxVcpus */ + NULL, /* domainGetSecurityLabel */ + NULL, /* nodeGetSecurityModel */ + xenapiDomainDumpXML, /* domainDumpXML */ + xenapiDomainXMLFromNative, /* domainXmlFromNative */ + xenapiDomainXMLToNative, /* domainXmlToNative */ + xenapiListDefinedDomains, /* listDefinedDomains */ + xenapiNumOfDefinedDomains, /* numOfDefinedDomains */ + xenapiDomainCreate, /* domainCreate */ + xenapiDomainDefineXML, /* domainDefineXML */ + xenapiDomainUndefine, /* domainUndefine */ + xenapiDomainAttachDevice, /* domainAttachDevice */ + NULL, + xenapiDomainDetachDevice, /* domainDetachDevice */ + NULL, + xenapiDomainGetAutostart, /* domainGetAutostart */ + xenapiDomainSetAutostart, /* domainSetAutostart */ + xenapiDomainGetSchedulerType, /* domainGetSchedulerType */ + xenapiDomainGetSchedulerParameters, /* domainGetSchedulerParameters */ + xenapiDomainSetSchedulerParameters, /* domainSetSchedulerParameters */ + xenapiDomainMigratePrepare, /* domainMigratePrepare */ + xenapiDomainMigratePerform, /* domainMigratePerform */ + xenapiDomainMigrateFinish, /* domainMigrateFinish */ + xenapiDomainBlockStats, /* domainBlockStats */ + xenapiDomainInterfaceStats, /* domainInterfaceStats */ + NULL, + xenapiDomainBlockPeek, /* domainBlockPeek */ + NULL, /* domainMemoryPeek */ + xenapiNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */ + xenapiNodeGetFreeMemory, /* getFreeMemory */ + xenapiDomainEventRegister, /* domainEventRegister */ + xenapiDomainEventDeregister, /* domainEventDeregister */ + NULL, /* domainMigratePrepare2 */ + NULL, /* domainMigrateFinish2 */ + xenapiNodeDeviceDettach, /* nodeDeviceDettach */ + xenapiNodeDeviceReAttach, /* nodeDeviceReAttach */ + xenapiNodeDeviceReset, /* 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); + //curl_easy_setopt(curl, CURLOPT_VERBOSE, 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, 0); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); + 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-18 15:37:49.000000000 +0000 @@ -0,0 +1,44 @@ +/* + * xenapi.c: Xen API driver. + * Copyright (C) 2009 Citrix Ltd. + * Sharadha Prabhakar <sharadha.prabhakar@xxxxxxxxxx> + */ + + +#ifndef __VIR_XENAPI_H__ +#define __VIR_XENAPI_H__ + +#include <xen/api/xen_common.h> +#include <libxml/tree.h> + +//#define PRINT_XML +#define RAW_UUID_BUFLEN (16) +#define LIBVIRT_MODELNAME_LEN (32) + + +extern int xenapiRegister (void); + +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; + xen_api_version version; +}; + +#endif /* __VIR_XENAPI_H__ */ -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list