diff -Nur ./libvirt_org/src/xenapi/xenapi_driver.c ./libvirt/src/xenapi/xenapi_driver.c --- ./libvirt_org/src/xenapi/xenapi_driver.c 1970-01-01 01:00:00.000000000 +0100 +++ ./libvirt/src/xenapi/xenapi_driver.c 2010-03-09 15:58:00.000000000 +0000 @@ -0,0 +1,1779 @@ +/* + * xenapi_driver.c: Xen API driver. + * Copyright (C) 2009, 2010 Citrix Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Sharadha Prabhakar + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libvirt_internal.h" +#include "libvirt/libvirt.h" +#include "domain_conf.h" +#include "virterror_internal.h" +#include "datatypes.h" +#include "xenapi_driver.h" +#include "xenapi_driver_private.h" +#include "util.h" +#include "uuid.h" +#include "memory.h" +#include "driver.h" +#include "buf.h" +#include "xenapi_utils.h" + + +/* +*getCapsObject +* +*Build the capabilities of the hypervisor +*Return virCapsPtr on success or NULL on failure +*/ +static virCapsPtr +getCapsObject (void) +{ + virCapsPtr caps = virCapabilitiesNew("x86_64", 0, 0); + if (!caps) { + virReportOOMError(); + return NULL; + } + virCapsGuestPtr guest1 = virCapabilitiesAddGuest(caps, "hvm", "x86_64", 0, "", "", 0, NULL); + if (!guest1) + goto error_cleanup; + virCapsGuestDomainPtr domain1 = virCapabilitiesAddGuestDomain(guest1, "xen", "", "", 0, NULL); + if (!domain1) + goto error_cleanup; + virCapsGuestPtr guest2 = virCapabilitiesAddGuest(caps, "xen", "x86_64", 0, "", "", 0, NULL); + if (!guest2) + goto error_cleanup; + virCapsGuestDomainPtr domain2 = virCapabilitiesAddGuestDomain(guest2, "xen", "", "", 0, NULL); + if (!domain2) + goto error_cleanup; + + return caps; + + error_cleanup: + virCapabilitiesFree(caps); + return NULL; +} + +/* +*XenapiOpen +* +*Authenticates and creates a session with the server +*Return VIR_DRV_OPEN_SUCCESS on success, else VIR_DRV_OPEN_ERROR +*/ +static virDrvOpenStatus +xenapiOpen (virConnectPtr conn, virConnectAuthPtr auth , int flags ATTRIBUTE_UNUSED) +{ + char *passwd=NULL; + xen_session *session; + struct _xenapiPrivate *privP; + + if (!STRCASEEQ(conn->uri->scheme,"XenAPI")) { + return VIR_DRV_OPEN_DECLINED; + } + if (conn->uri->server==NULL) { + xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED ,"Server name not in URI"); + return VIR_DRV_OPEN_ERROR; + } + if (auth) { + passwd = xenapiUtil_RequestPassword(auth,conn->uri->user,conn->uri->server); + } else { + xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED ,"Authentication Credentials not found"); + return VIR_DRV_OPEN_ERROR; + } + if (!passwd || !conn->uri->user) { + xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED ,"Username/Password not valid"); + if(passwd) VIR_FREE(passwd); + return VIR_DRV_OPEN_ERROR; + } + if (VIR_ALLOC(privP) < 0) { + virReportOOMError(); + return VIR_DRV_OPEN_ERROR; + } + if (virAsprintf(&(privP->url),"https://%s",conn->uri->server) < 0) { + virReportOOMError(); + VIR_FREE(passwd); + return VIR_DRV_OPEN_ERROR; + } + xenapiUtil_ParseQuery(conn, conn->uri,&(privP->noVerify)); + xmlInitParser(); + xmlKeepBlanksDefault(0); + xen_init(); + curl_global_init(CURL_GLOBAL_ALL); + + session = xen_session_login_with_password (call_func, privP, conn->uri->user, passwd, xen_api_latest_version); + + if ( session && session->ok ) { + privP->session = session; + if (!(privP->caps = getCapsObject())) { + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Capabilities not found"); + VIR_FREE(passwd); + return VIR_DRV_OPEN_ERROR; + } + conn->privateData = privP; + VIR_FREE(passwd); + return VIR_DRV_OPEN_SUCCESS; + } else { + xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED ,""); + if (session) xenSessionFree(session); + VIR_FREE(privP); + VIR_FREE(passwd); + return VIR_DRV_OPEN_ERROR; + } +} + +/* +* xenapiClose: +* +* Returns 0 on successful session logout +* +*/ +static int +xenapiClose (virConnectPtr conn) +{ + xen_session_logout(((struct _xenapiPrivate *)(conn->privateData))->session); + virCapabilitiesFree(((struct _xenapiPrivate *)(conn->privateData))->caps); + VIR_FREE(((struct _xenapiPrivate *)(conn->privateData))->url); + VIR_FREE(conn->privateData); + return 0; +} + +/* +* +* xenapiSupportsFeature +* +* Returns 0 +*/ +static int +xenapiSupportsFeature (virConnectPtr conn ATTRIBUTE_UNUSED, int feature) +{ + switch (feature) { + case VIR_DRV_FEATURE_MIGRATION_V2: + case VIR_DRV_FEATURE_MIGRATION_P2P: + default: + return 0; + } +} + +/* +* xenapiType: +* +* +*Returns name of the driver +*/ +static const char * +xenapiType (virConnectPtr conn ATTRIBUTE_UNUSED) +{ + return "XenAPI"; +} + + +/* +* xenapiGetVersion: +* +* Gets the version of XenAPI +* +*/ +static int +xenapiGetVersion (virConnectPtr conn, unsigned long *hvVer) +{ + xen_host host; + xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session; + xen_string_string_map *result=NULL; + int i; + char *version=NULL; + unsigned long major=0,minor=0,release=0; + if (!(xen_session_get_this_host(session, &host,session))) { + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR ,NULL); + return -1; + } + if (!(xen_host_get_software_version(session, &result, host))) { + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR ,NULL); + xen_host_free(host); + return -1; + } + xen_host_free(host); + if (result && result->size>0) { + for (i=0; isize; i++) { + if (STREQ(result->contents[i].key,"xen")) { + if (!(version = strdup(result->contents[i].val))) { + xen_string_string_map_free(result); + virReportOOMError(); + return -1; + } + break; + } + } + if (version) { + if (sscanf(version,"%ld.%ld.%ld",&major,&minor,&release)!=3) { + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR , "Couldn't get version info"); + xen_string_string_map_free(result); + VIR_FREE(version); + return -1; + } + *hvVer = major * 1000000 + minor * 1000 + release; + VIR_FREE(version); + xen_string_string_map_free(result); + return 0; + } + } + return -1; +} + + +/* +* xenapiGetHostname: +* +* +* Returns the hostname on success, or NULL on failure +*/ +static char * +xenapiGetHostname (virConnectPtr conn) +{ + char *result=NULL; + xen_host host; + xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session; + if (!(xen_session_get_this_host(session, &host, session))) { + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR ,NULL); + return NULL; + } + if (!(xen_host_get_hostname(session, &result, host))) + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR ,NULL); + xen_host_free(host); + return result; +} + + +/* +* xenapiGetMaxVcpus: +* +* +* Returns a hardcoded value for Maximum VCPUS +*/ +static int +xenapiGetMaxVcpus (virConnectPtr conn ATTRIBUTE_UNUSED, const char *type ATTRIBUTE_UNUSED) +{ + /* this is hardcoded for simplicity and set to a resonable value compared + to the actual value */ + return 16; +} + + +/* +* xenapiNodeGetInfo: +* +* +* Returns Node details on success or else -1 +*/ +static int +xenapiNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info) +{ + int64_t memory,mhz; + xen_host_cpu_set *host_cpu_set; + xen_host_cpu host_cpu; + xen_host_metrics_set *xen_met_set; + char *modelname; + xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session; + info->nodes = 1; + info->threads = 1; + info->sockets = 1; + + if (xen_host_metrics_get_all(session, &xen_met_set)) { + xen_host_metrics_get_memory_total(session, &memory, xen_met_set->contents[0]); + info->memory = (unsigned long)(memory/1024); + xen_host_metrics_set_free(xen_met_set); + } else { + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR ,"Unable to get host metric Information"); + return -1; + } + if (xen_host_cpu_get_all(session, &host_cpu_set)) { + host_cpu = host_cpu_set->contents[0]; + xen_host_cpu_get_modelname(session, &modelname, host_cpu); + if (!virStrncpy(info->model,modelname,LIBVIRT_MODELNAME_LEN-1,LIBVIRT_MODELNAME_LEN)){ + virReportOOMError(); + xen_host_cpu_set_free(host_cpu_set); + VIR_FREE(modelname); + return -1; + } + xen_host_cpu_get_speed(session, &mhz, host_cpu); + info->mhz = (unsigned long)mhz; + info->cpus = host_cpu_set->size; + info->cores = host_cpu_set->size; + + xen_host_cpu_set_free(host_cpu_set); + VIR_FREE(modelname); + return 0; + } + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR ,"Unable to get Host CPU set"); + return -1; +} + +/* +* xenapiGetCapabilities: +* +* +* Returns capabilities as an XML string +*/ +static char * +xenapiGetCapabilities (virConnectPtr conn) +{ + virCapsPtr caps = ((struct _xenapiPrivate *)(conn->privateData))->caps; + if (caps) { + char *xml = virCapabilitiesFormatXML(caps); + if (!xml) goto cleanup; + return xml; + } + cleanup: + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR ,"Capabilities not available"); + return NULL; +} + + +/* +* xenapiListDomains +* +* Collects the list of active domains, and store their ID in @maxids +* Returns the number of domain found or -1 in case of error +*/ +static int +xenapiListDomains (virConnectPtr conn, int *ids, int maxids) +{ + /* vm.list */ + xen_host host; + xen_vm_set *result=NULL; + int64_t t0; + int i; + xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session; + if (xen_session_get_this_host(session, &host, session)) { + xen_host_get_resident_vms(session, &result, host); + xen_host_free(host); + } else + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR ,NULL); + if (result != NULL) { + for ( i=0; (i < (result->size)) && (icontents[i]); + fprintf(stderr,"\nt0:%lld",t0); + if (t0> (int64_t)INT_MAX || t0< (int64_t)INT_MIN) { + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "DomainID can't fit in 32 bits"); + xen_vm_set_free(result); + return -1; + } + ids[i] = (int)t0; + } + xen_vm_set_free(result); + return i; + } + return -1; +} + +/* +* xenapiNumOfDomains +* +* +* Returns the number of domains found or -1 in case of error +*/ +static int +xenapiNumOfDomains (virConnectPtr conn) +{ + /* #(vm.list) */ + xen_vm_set *result=NULL; + xen_host host=NULL; + int numDomains=-1; + xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session; + + xen_session_get_this_host(session, &host, session); + if ( host!=NULL ) { + xen_host_get_resident_vms(session, &result, host); + if ( result != NULL) { + numDomains = result->size; + xen_vm_set_free(result); + } + xen_host_free(host); + } + if (!(session->ok)) + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR ,NULL); + return numDomains; +} + +/* +* xenapiDomainCreateXML +* +* Launches a new domain based on the XML description +* Returns the domain pointer or NULL in case of error +*/ +static virDomainPtr +xenapiDomainCreateXML (virConnectPtr conn, + const char *xmlDesc, + unsigned int flags ATTRIBUTE_UNUSED) +{ + xen_vm_record *record=NULL; + xen_vm vm=NULL; + virDomainPtr domP=NULL; + xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session; + virCapsPtr caps = ((struct _xenapiPrivate *)(conn->privateData))->caps; + if (!caps) + return NULL; + + virDomainDefPtr defPtr = virDomainDefParseString(caps, xmlDesc, flags); + createVMRecordFromXml(conn, defPtr, &record, &vm); + virDomainDefFree(defPtr); + if (record) { + unsigned char raw_uuid[VIR_UUID_BUFLEN]; + virUUIDParse(record->uuid,raw_uuid); + if (vm) { + if (xen_vm_start(session, vm, false, false)) { + domP = virGetDomain(conn, record->name_label, raw_uuid); + if (!domP) { + xen_vm_record_free(record); + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Domain Pointer is invalid"); + return domP; + } + domP->id = record->domid; + xen_vm_free(vm); + } + else + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL); + } + xen_vm_record_free(record); + } + else + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL); + return domP; +} + +/* +* xenapiDomainLookupByID +* +* +* Returns a valid domain pointer of the domain with ID same as the one passed +* or NULL in case of error +*/ +static virDomainPtr +xenapiDomainLookupByID (virConnectPtr conn, int id) +{ + int i; + int64_t domID; + char *uuid; + xen_host host; + xen_vm_set *result; + xen_vm_record *record; + unsigned char raw_uuid[VIR_UUID_BUFLEN]; + virDomainPtr domP=NULL; + xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session; + + xen_session_get_this_host(session, &host, session); + if (host!=NULL && session->ok) { + xen_host_get_resident_vms(session, &result, host); + if ( result !=NULL ) { + for( i=0; i < (result->size); i++) { + xen_vm_get_domid(session, &domID, result->contents[i]); + if ( domID == id ) { + xen_vm_get_record(session, &record, result->contents[i]); + xen_vm_get_uuid(session, &uuid, result->contents[i]); + virUUIDParse(uuid,raw_uuid); + domP = virGetDomain(conn, record->name_label, raw_uuid); + if (domP) { + int64_t domid=-1; + xen_vm_get_domid(session, &domid, result->contents[i]); + domP->id = domid; + } else { + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR , "Domain Pointer not valid"); + domP = NULL; + } + xen_uuid_free(uuid); + xen_vm_record_free(record); + break; + } + } + xen_vm_set_free(result); + } else { + xenapiSessionErrorHandler(conn, VIR_ERR_NO_DOMAIN ,NULL); + } + xen_host_free(host); + } else { + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR ,NULL); + } + return domP; +} + +/* +* xenapiDomainLookupByUUID +* +* Returns the domain pointer of domain with matching UUID +* or -1 in case of error +*/ +static virDomainPtr +xenapiDomainLookupByUUID (virConnectPtr conn, + const unsigned char *uuid) +{ + /* vm.get_by_uuid */ + xen_vm vm; + xen_vm_record *record; + char uuidStr[VIR_UUID_STRING_BUFLEN]; + virDomainPtr domP=NULL; + xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session; + virUUIDFormat(uuid,uuidStr); + if (xen_vm_get_by_uuid(session, &vm, uuidStr)) { + xen_vm_get_record(session, &record, vm); + if (record != NULL) { + domP = virGetDomain(conn, record->name_label, uuid); + if (!domP) { + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR , "Domain Pointer not valid"); + domP=NULL; + } else { + domP->id = record->domid; + } + xen_vm_record_free(record); + } + else + xenapiSessionErrorHandler(conn, VIR_ERR_NO_DOMAIN ,NULL); + xen_vm_free(vm); + } else + xenapiSessionErrorHandler(conn, VIR_ERR_NO_DOMAIN ,NULL); + return domP; +} + +/* +* xenapiDomainLookupByName +* +* Returns the domain pointer of domain with matching name +* or -1 in case of error +*/ +static virDomainPtr +xenapiDomainLookupByName (virConnectPtr conn, + const char *name) +{ + /* vm.get_by_name_label */ + xen_vm_set *vms=NULL; + xen_vm vm; + char *uuid=NULL; + unsigned char raw_uuid[VIR_UUID_BUFLEN]; + virDomainPtr domP=NULL; + xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session; + if (xen_vm_get_by_name_label(session, &vms, (char *)name) && vms->size>0) { + if (vms->size!=1) { + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Domain name is not unique"); + xen_vm_set_free(vms); + return NULL; + } + vm = vms->contents[0]; + xen_vm_get_uuid(session, &uuid, vm); + if (uuid!=NULL) { + virUUIDParse(uuid,raw_uuid); + domP = virGetDomain(conn, name, raw_uuid); + if (domP != NULL) { + int64_t domid=-1; + xen_vm_get_domid(session, &domid, vm); + domP->id = domid; + xen_uuid_free(uuid); + xen_vm_set_free(vms); + return domP; + } else { + xen_uuid_free(uuid); + xen_vm_set_free(vms); + if (!(session->ok)) + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Couldn't get the Domain Pointer"); + return NULL; + } + } + } + if (vms) xen_vm_set_free(vms); + xenapiSessionErrorHandler(conn, VIR_ERR_NO_DOMAIN, ""); + 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=NULL; + xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session; + if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size>0) { + if (vms->size!=1) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique"); + xen_vm_set_free(vms); + return -1; + } else { + vm = vms->contents[0]; + if (!xen_vm_pause(session, vm)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL); + xen_vm_set_free(vms); + return -1; + } + xen_vm_set_free(vms); + return 0; + } + } + if (vms) xen_vm_set_free(vms); + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, ""); + return -1; +} + +/* +* 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) && vms->size>0) { + if (vms->size!=1) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique"); + xen_vm_set_free(vms); + return -1; + } else { + vm = vms->contents[0]; + if (!xen_vm_unpause(session, vm)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL); + xen_vm_set_free(vms); + return -1; + } + xen_vm_set_free(vms); + return 0; + } + } + if (vms) xen_vm_set_free(vms); + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, ""); + return -1; +} + +/* +* 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) && vms->size>0 ) { + if (vms->size!=1) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique"); + xen_vm_set_free(vms); + return -1; + } else { + vm = vms->contents[0]; + if (!xen_vm_clean_shutdown(session, vm)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL); + xen_vm_set_free(vms); + return -1; + } + xen_vm_set_free(vms); + return 0; + } + } + if (vms) xen_vm_set_free(vms); + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, ""); + return -1; +} + +/* +* xenapiDomainReboot +* +* Reboots a VM +* Returns 0 on success or -1 in case of error +*/ +static int +xenapiDomainReboot (virDomainPtr dom, unsigned int flags ATTRIBUTE_UNUSED) +{ + /* vm.clean_reboot */ + xen_vm vm; + struct xen_vm_set *vms; + xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session; + if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size>0) { + if (vms->size!=1) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique"); + xen_vm_set_free(vms); + return -1; + } + vm = vms->contents[0]; + if (!xen_vm_clean_reboot(session, vm)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL); + xen_vm_set_free(vms); + return -1; + } + xen_vm_set_free(vms); + return 0; + } + if (vms) xen_vm_set_free(vms); + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, ""); + return -1; +} + +/* +* xenapiDomaindestroy +* +* A VM is hard shutdown +* Returns 0 on success or -1 in case of error +*/ +static int +xenapiDomainDestroy (virDomainPtr dom) +{ + /* vm.hard_shutdown */ + xen_vm vm; + struct xen_vm_set *vms; + xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session; + if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size>0) { + if (vms->size!=1) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique"); + xen_vm_set_free(vms); + return -1; + } + vm = vms->contents[0]; + if (!xen_vm_hard_shutdown(session, vm)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL); + xen_vm_set_free(vms); + return -1; + } + xen_vm_set_free(vms); + return 0; + } + if (vms) xen_vm_set_free(vms); + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, ""); + return -1; +} + +/* +* xenapiDomainGetOSType +* +* +* Returns OS version on success or NULL in case of error +*/ +static char * +xenapiDomainGetOSType (virDomainPtr dom) +{ + xen_vm vm=NULL; + xen_vm_set *vms; + char *ostype = NULL; + char *boot_policy=NULL; + xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session; + + if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size>0 ){ + if (vms->size!=1) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique"); + xen_vm_set_free(vms); + return NULL; + } + vm = vms->contents[0]; + if(!xen_vm_get_hvm_boot_policy(session, &boot_policy, vm)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL); + goto cleanup; + } + if (!(ostype=(STREQ(boot_policy,"BIOS order")?strdup("hvm"):strdup("xen")))) + virReportOOMError(); + VIR_FREE(boot_policy); + } else + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, ""); + + cleanup: + if(vms) xen_vm_set_free(vms); + return ostype; +} +/* +* xenapiDomainGetMaxMemory +* +* Returns maximum static memory for VM on success +* or 0 in case of error +*/ +static unsigned long +xenapiDomainGetMaxMemory (virDomainPtr dom) +{ + int64_t mem_static_max=0; + xen_vm vm; + xen_vm_set *vms; + xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session; + if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size>0) { + if (vms->size!=1) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique"); + xen_vm_set_free(vms); + return 0; + } + vm = vms->contents[0]; + xen_vm_get_memory_static_max(session, &mem_static_max, vm); + xen_vm_set_free(vms); + return (unsigned long)(mem_static_max/1024); + } else { + if(vms) xen_vm_set_free(vms); + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL); + return 0; + } +} + +/* +* xenapiDomainSetMaxMemory +* +* Sets maximum static memory for VM on success +* Returns 0 on success or -1 in case of error +*/ +static int +xenapiDomainSetMaxMemory (virDomainPtr dom, unsigned long memory) +{ + /* vm.set_memory_static_max */ + xen_vm vm; + struct xen_vm_set *vms; + xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session; + if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size>0) { + if (vms->size!=1) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique"); + xen_vm_set_free(vms); + return -1; + } + vm = vms->contents[0]; + if (!(xen_vm_set_memory_static_max(session, vm, memory*1024))) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL); + xen_vm_set_free(vms); + return -1; + } + xen_vm_set_free(vms); + } else { + if(vms) xen_vm_set_free(vms); + 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) && vms->size>0) { + if (vms->size!=1) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique"); + xen_vm_set_free(vms); + return -1; + } + vm = vms->contents[0]; + xen_vm_get_memory_static_max(session, &maxmem, vm); + info->maxMem = (maxmem/1024); + enum xen_vm_power_state state = XEN_VM_POWER_STATE_UNKNOWN; + xen_vm_get_power_state(session, &state, vm); + info->state = mapPowerState(state); + xen_vm_get_record(session, &record, vm); + if (record!=NULL) { + xen_vm_metrics_get_memory_actual(session, &memory, record->metrics->u.handle); + info->memory = (memory/1024); + xen_vm_record_free(record); + } + xen_vm_get_vcpus_max(session, &vcpu, vm); + info->nrVirtCpu = vcpu; + xen_vm_set_free(vms); + return 0; + } + if(vms) xen_vm_set_free(vms); + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL); + return -1; +} + + +/* +* xenapiDomainSetVcpus +* +* Sets the VCPUs on the domain +* Return 0 on success or -1 in case of error +*/ +static int +xenapiDomainSetVcpus (virDomainPtr dom, unsigned int nvcpus) +{ + + /* vm.set_vcpus_max */ + xen_vm vm; + xen_vm_set *vms; + xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session; + if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size>0) { + if (vms->size!=1) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique"); + xen_vm_set_free(vms); + return -1; + } + vm = vms->contents[0]; + if (xen_vm_set_vcpus_number_live(session, vm, (int64_t)nvcpus)) { + xen_vm_set_free(vms); + return 0; + } + } + if(vms) xen_vm_set_free(vms); + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL); + return -1; +} + +/* +* xenapiDomainPinVcpu +* +* Dynamically change the real CPUs which can be allocated to a virtual CPU +* Returns 0 on success or -1 in case of error +*/ +static int +xenapiDomainPinVcpu (virDomainPtr dom, unsigned int vcpu ATTRIBUTE_UNUSED, + unsigned char *cpumap, int maplen) +{ + char *value=NULL; + xen_vm vm; + xen_vm_set *vms; + xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session; + if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size>0) { + if (vms->size!=1) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique"); + xen_vm_set_free(vms); + return -1; + } + vm = vms->contents[0]; + if ((value = mapDomainPinVcpu(cpumap, maplen))) { + xen_vm_remove_from_vcpus_params(session, vm, (char *)"mask"); + if (xen_vm_add_to_vcpus_params(session, vm, (char *)"mask", value)) { + xen_vm_set_free(vms); + VIR_FREE(value); + return 0; + } + VIR_FREE(value); + } else { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL); + xen_vm_set_free(vms); + return -1; + } + } + if(vms) xen_vm_set_free(vms); + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL); + return -1; +} + +/* +* xenapiDomainGetVcpus +* +* Gets Vcpu information +* Return number of structures filled on success or -1 in case of error +*/ +static int +xenapiDomainGetVcpus (virDomainPtr dom, + virVcpuInfoPtr info, int maxinfo, + unsigned char *cpumaps, int maplen) +{ + + xen_vm_set *vms=NULL; + xen_vm vm=NULL; + xen_string_string_map *vcpu_params=NULL; + int nvcpus=0,cpus=0,i; + virDomainInfo 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 (xenapiDomainGetInfo(dom,&domInfo)==0) { + nvcpus = domInfo.nrVirtCpu; + } else { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Couldn't fetch Domain Information"); + return -1; + } + if ( xenapiNodeGetInfo(dom->conn,&nodeInfo)==0) + cpus = nodeInfo.cpus; + else { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Couldn't fetch Node Information"); + return -1; + } + if(nvcpus > maxinfo) nvcpus = maxinfo; + + if (cpumaps != NULL) + memset(cpumaps, 0, maxinfo * maplen); + if (!xen_vm_get_by_name_label(session, &vms, dom->name)) return -1; + if (vms->size!=1) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique"); + xen_vm_set_free(vms); + return -1; + } + vm = vms->contents[0]; + if (!xen_vm_get_vcpus_params(session, &vcpu_params, vm)) { + xen_vm_set_free(vms); + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL); + return -1; + } + for (i=0; isize; i++) { + if (STREQ(vcpu_params->contents[i].key,"mask")) { + if (!(mask = strdup(vcpu_params->contents[i].val))){ + xen_vm_set_free(vms); + xen_string_string_map_free(vcpu_params); + virReportOOMError(); + return -1; + } + break; + } + } + xen_string_string_map_free(vcpu_params); + for (i=0,ifptr=info ;inumber = i; + ifptr->state = VIR_VCPU_RUNNING; + ifptr->cpuTime = 0; + ifptr->cpu = 0; + if (mask !=NULL) + getCpuBitMapfromString(mask,VIR_GET_CPUMAP(cpumaps,maplen,i),maplen); + } + VIR_FREE(mask); + xen_vm_set_free(vms); + return i; +} + +/* +* xenapiDomainGetMaxVcpus +* +* +* Returns maximum number of Vcpus on success or -1 in case of error +*/ +static int +xenapiDomainGetMaxVcpus (virDomainPtr dom) +{ + xen_vm vm; + xen_vm_set *vms; + int64_t maxvcpu=0; + enum xen_vm_power_state state; + xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session; + if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size>0) { + if (vms->size!=1) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique"); + xen_vm_set_free(vms); + return -1; + } + vm = vms->contents[0]; + xen_vm_get_power_state(session, &state, vm); + if(state == XEN_VM_POWER_STATE_RUNNING) { + xen_vm_get_vcpus_max(session, &maxvcpu, vm); + } else { + maxvcpu = xenapiGetMaxVcpus(dom->conn, NULL); + } + xen_vm_set_free(vms); + return (int)maxvcpu; + } + if(vms) xen_vm_set_free(vms); + 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, int flags ATTRIBUTE_UNUSED) +{ + xen_vm vm=NULL; + xen_vm_set *vms; + xen_string_string_map *result=NULL; + xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session; + virDomainDefPtr defPtr = NULL; + + if(!xen_vm_get_by_name_label(session, &vms, dom->name)) return NULL; + if (vms->size!=1) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique"); + xen_vm_set_free(vms); + return NULL; + } + if (VIR_ALLOC(defPtr)<0) { + virReportOOMError(); + xen_vm_set_free(vms); + return NULL; + } + vm = vms->contents[0]; + defPtr->virtType = VIR_DOMAIN_VIRT_XEN; + defPtr->id = dom->id; + memcpy((char *)defPtr->uuid,(char *)dom->uuid,VIR_UUID_BUFLEN); + if (!(defPtr->name = strdup(dom->name))) + goto error_cleanup; + char *boot_policy=NULL; + xen_vm_get_hvm_boot_policy(session, &boot_policy, vm); + if (STREQ(boot_policy,"BIOS order")) { + if (!(defPtr->os.type = strdup("hvm"))) { + VIR_FREE(boot_policy); + goto error_cleanup; + } + xen_vm_get_hvm_boot_params(session, &result, vm); + if (result!=NULL) { + int i; + for (i=0; i<(result->size); i++) { + if (STREQ(result->contents[i].key,"order")) { + int cnt=0; + while(result->contents[i].val[cnt]!='\0') { + defPtr->os.bootDevs[cnt] = map2LibvirtBootOrder(result->contents[i].val[cnt]); + cnt++; + } + defPtr->os.nBootDevs = cnt; + break; + } + } + xen_string_string_map_free(result); + } + VIR_FREE(boot_policy); + } else { + if(!(defPtr->os.type = strdup("xen"))) { + VIR_FREE(boot_policy); + goto error_cleanup; + } + if(!(defPtr->os.loader = strdup("pygrub"))) { + VIR_FREE(boot_policy); + goto error_cleanup; + } + char *value=NULL; + xen_vm_get_pv_kernel(session, &value, vm); + if (STRNEQ(value,"")) { + if(!(defPtr->os.kernel = strdup(value))) { + VIR_FREE(boot_policy); + VIR_FREE(value); + goto error_cleanup; + } + VIR_FREE(value); + } + xen_vm_get_pv_ramdisk(session, &value, vm); + if (STRNEQ(value,"")) { + if(!(defPtr->os.initrd = strdup(value))) { + VIR_FREE(boot_policy); + VIR_FREE(value); + goto error_cleanup; + } + VIR_FREE(value); + } + xen_vm_get_pv_args(session, &value, vm); + if (STRNEQ(value,"")) { + if(!(defPtr->os.cmdline = strdup(value))) { + VIR_FREE(boot_policy); + VIR_FREE(value); + goto error_cleanup; + } + VIR_FREE(value); + } + VIR_FREE(boot_policy); + if(!(defPtr->os.bootloader = strdup("pygrub"))) + goto error_cleanup; + } + char *val=NULL; + xen_vm_get_pv_bootloader_args(session, &val, vm); + if (STRNEQ(val,"")) { + if(!(defPtr->os.bootloaderArgs = strdup(val))) { + VIR_FREE(val); + goto error_cleanup; + } + VIR_FREE(val); + } + unsigned long memory=0; + memory = xenapiDomainGetMaxMemory(dom); + defPtr->maxmem = memory; + int64_t dynamic_mem=0; + if (xen_vm_get_memory_dynamic_max(session, &dynamic_mem, vm)) { + defPtr->memory = (unsigned long) (dynamic_mem/1024); + } else { + defPtr->memory = memory; + } + defPtr->vcpus = xenapiDomainGetMaxVcpus(dom); + enum xen_on_normal_exit action; + if (xen_vm_get_actions_after_shutdown(session, &action, vm)) { + defPtr->onPoweroff = xenapiNormalExitEnum2virDomainLifecycle(action); + } + if (xen_vm_get_actions_after_reboot(session, &action, vm)) { + defPtr->onReboot = xenapiNormalExitEnum2virDomainLifecycle(action); + } + enum xen_on_crash_behaviour crash; + if (xen_vm_get_actions_after_crash(session, &crash, vm)) { + defPtr->onCrash = xenapiCrashExitEnum2virDomainLifecycle(action); + } + xen_vm_get_platform(session, &result, vm); + if (result!=NULL) { + int i; + for(i=0; i< (result->size); i++) { + if (STREQ(result->contents[i].val,"true")) { + if (STREQ(result->contents[i].key,"acpi")) + defPtr->features = defPtr->features | (1<contents[i].key,"apic")) + defPtr->features = defPtr->features | (1<contents[i].key,"pae")) + defPtr->features = defPtr->features | (1<nnets = vif_set->size; + if (VIR_ALLOC_N(defPtr->nets, vif_set->size)<0) { + xen_vif_set_free(vif_set); + goto error_cleanup; + } + for (i=0; isize; i++) { + if (VIR_ALLOC(defPtr->nets[i])<0) { + xen_vif_set_free(vif_set); + goto error_cleanup; + } + defPtr->nets[i]->type = VIR_DOMAIN_NET_TYPE_BRIDGE; + vif = vif_set->contents[i]; + xen_vif_get_network(session, &network, vif); + if (network!=NULL) { + xen_network_get_bridge(session, &bridge, network); + if (bridge!=NULL) + defPtr->nets[i]->data.bridge.brname = bridge; + xen_network_free(network); + } + xen_vif_get_record(session, &vif_rec, vif); + if (vif_rec!=NULL) { + if(virParseMacAddr((const char *)vif_rec->mac,defPtr->nets[i]->mac) < 0) + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Unable to parse given mac address"); + xen_vif_record_free(vif_rec); + } + } + xen_vif_set_free(vif_set); + } + if (vms) xen_vm_set_free(vms); + char *xml = virDomainDefFormat(defPtr,0); + virDomainDefFree(defPtr); + return xml; + + error_cleanup: + virReportOOMError(); + xen_vm_set_free(vms); + virDomainDefFree(defPtr); + return NULL; + +} + +/* +* xenapiListDefinedDomains +* +* list the defined but inactive domains, stores the pointers to the names in @names +* Returns number of names provided in the array or -1 in case of error +*/ +static int +xenapiListDefinedDomains (virConnectPtr conn, char **const names, + int maxnames) +{ + int i,j=0,doms; + xen_vm_set *result; + xen_vm_record *record; + xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session; + xen_vm_get_all(session, &result); + if (result != NULL) { + for (i=0; i< (result->size) && j< maxnames; i++) { + xen_vm_get_record(session, &record, result->contents[i]); + if ( record!=NULL ) { + if ( record->is_a_template == 0 ) { + char *usenames=NULL; + if (!(usenames = strdup(record->name_label))) { + virReportOOMError(); + xen_vm_record_free(record); + xen_vm_set_free(result); + while (--j>=0) free(names[j]); + return -1; + } + names[j++]=usenames; + } + xen_vm_record_free(record); + } else { + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Couldn't get VM record"); + xen_vm_set_free(result); + while (--j>=0) free(names[j]); + return -1; + } + } + doms=j; + xen_vm_set_free(result); + return doms; + } + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL); + return -1; +} + +/* +* xenapiNumOfDefinedDomains +* +* Provides the number of defined but inactive domains +* Returns number of domains found on success or -1 in case of error +*/ +static int +xenapiNumOfDefinedDomains (virConnectPtr conn) +{ + xen_vm_set *result; + xen_vm_record *record; + int DomNum=0,i; + xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session; + xen_vm_get_all(session, &result); + if ( result != NULL) { + for ( i=0; i< (result->size); i++ ) { + xen_vm_get_record(session, &record, result->contents[i]); + if (record==NULL && !session->ok) { + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL); + xen_vm_set_free(result); + return -1; + } + if (record->is_a_template == 0) + DomNum++; + xen_vm_record_free(record); + } + xen_vm_set_free(result); + return DomNum; + } + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL); + return -1; +} + +/* +* xenapiDomainCreate +* +* starts a VM +* Return 0 on success or -1 in case of error +*/ +static int +xenapiDomainCreate (virDomainPtr dom) +{ + xen_vm_set *vms; + xen_vm vm; + xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session; + if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size>0) { + if (vms->size!=1) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique"); + xen_vm_set_free(vms); + return -1; + } + vm = vms->contents[0]; + if (!xen_vm_start(session, vm, false, false)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL); + xen_vm_set_free(vms); + return -1; + } + xen_vm_set_free(vms); + } else { + if(vms) xen_vm_set_free(vms); + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL); + return -1; + } + return 0; +} + +/* +* xenapiDomainDefineXML +* +* Defines a domain from the given XML but does not start it +* Returns 0 on success or -1 in case of error +*/ +static virDomainPtr +xenapiDomainDefineXML (virConnectPtr conn, const char *xml) +{ + xen_vm_record *record=NULL; + xen_vm vm=NULL; + virDomainPtr domP=NULL; + xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session; + virCapsPtr caps = ((struct _xenapiPrivate *)(conn->privateData))->caps; + if (!caps) + return NULL; + virDomainDefPtr defPtr = virDomainDefParseString(caps, xml, 0); + if (!defPtr) + return NULL; + if (createVMRecordFromXml( conn, defPtr, &record, &vm)!=0) { + if (!(session->ok)) + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL); + else + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Couldn't get VM information from XML"); + virDomainDefFree(defPtr); + return NULL; + } + if (record!=NULL) { + unsigned char raw_uuid[VIR_UUID_BUFLEN]; + virUUIDParse(record->uuid,raw_uuid); + domP = virGetDomain(conn, record->name_label, raw_uuid); + if (!domP && !(session->ok)) + xenapiSessionErrorHandler(conn, VIR_ERR_NO_DOMAIN, NULL); + xen_vm_record_free(record); + } + else if (vm!=NULL) + xen_vm_free(vm); + virDomainDefFree(defPtr); + return domP; +} + +/* +* xenapiDomainUndefine +* +* destroys a domain +* Return 0 on success or -1 in case of error +*/ +static int +xenapiDomainUndefine (virDomainPtr dom) +{ + struct xen_vm_set *vms; + xen_vm vm; + xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session; + if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size>0) { + if (vms->size!=1) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique"); + xen_vm_set_free(vms); + return -1; + } + vm = vms->contents[0]; + if (!xen_vm_destroy(session, vm)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL); + xen_vm_set_free(vms); + return -1; + } + xen_vm_set_free(vms); + return 0; + } + if(vms) xen_vm_set_free(vms); + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, ""); + 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; + xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session; + if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size>0) { + if (vms->size!=1) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique"); + xen_vm_set_free(vms); + return -1; + } + vm = vms->contents[0]; + if (!xen_vm_get_other_config(session, &result, vm)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL); + xen_vm_set_free(vms); + return -1; + } + for (i=0; i < result->size; i++) { + if (STREQ(result->contents[i].key, "auto_poweron")) { + flag=1; + if (STREQ(result->contents[i].val, "true")) + *autostart = 1; + else + *autostart = 0; + break; + } + } + xen_vm_set_free(vms); + xen_string_string_map_free(result); + if (flag==0) return -1; + return 0; + } + if(vms) xen_vm_set_free(vms); + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, ""); + return -1; +} + +/* +* 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) && vms->size>0) { + if (vms->size!=1) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,"Domain name is not unique"); + xen_vm_set_free(vms); + return -1; + } + vm = vms->contents[0]; + xen_vm_remove_from_other_config(session, vm, (char *)"auto_poweron"); + if (autostart==1) + value = (char *)"true"; + else + value = (char *)"false"; + if (!xen_vm_add_to_other_config(session, vm, (char *)"auto_poweron", value)) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL); + xen_vm_set_free(vms); + return -1; + } + xen_vm_set_free(vms); + return 0; + } + if(vms) xen_vm_set_free(vms); + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, ""); + return -1; +} + +static char * +xenapiDomainGetSchedulerType (virDomainPtr dom ATTRIBUTE_UNUSED, int *nparams) +{ + *nparams = 0; + char *result=NULL; + if (!(result = strdup("credit"))) + virReportOOMError(); + return result; +} + +/* +* xenapiNodeGetFreeMemory +* +* provides the free memory available on the Node +* Returns memory size on success or 0 in case of error +*/ +static unsigned long long +xenapiNodeGetFreeMemory (virConnectPtr conn) +{ + xen_host_metrics_set *xen_met_set; + unsigned long long freeMem=0; + xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session; + xen_host_metrics_get_all(session, &xen_met_set); + if (xen_met_set != NULL) { + if (!xen_host_metrics_get_memory_free(session, (int64_t *)&freeMem, xen_met_set->contents[0])) { + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Couldn't get host metrics - memory information"); + freeMem=0; + } + xen_host_metrics_set_free(xen_met_set); + } else { + xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Couldn't get host metrics"); + } + return freeMem; +} + +/* +* xenapiNodeGetCellsFreeMemory +* +* +* Returns the number of entries filled in freeMems, or -1 in case of error. +*/ +static int +xenapiNodeGetCellsFreeMemory (virConnectPtr conn, unsigned long long *freeMems, + int startCell, int maxCells) +{ + if (maxCells >1 && startCell >0) { + xenapiSessionErrorHandler(conn, VIR_ERR_NO_SUPPORT, ""); + return -1; + } else { + freeMems[0] = xenapiNodeGetFreeMemory(conn); + return 1; + } +} + +/* The interface which we export upwards to libvirt.c. */ +static virDriver xenapiDriver = { + VIR_DRV_XENAPI, + "XenAPI", + xenapiOpen, /* open */ + xenapiClose, /* close */ + xenapiSupportsFeature, /* supports_feature */ + xenapiType, /* type */ + xenapiGetVersion, /* version */ + NULL, /*getlibvirtVersion */ + xenapiGetHostname, /* getHostname */ + xenapiGetMaxVcpus, /* getMaxVcpus */ + xenapiNodeGetInfo, /* nodeGetInfo */ + xenapiGetCapabilities, /* getCapabilities */ + xenapiListDomains, /* listDomains */ + xenapiNumOfDomains, /* numOfDomains */ + xenapiDomainCreateXML, /* domainCreateXML */ + xenapiDomainLookupByID, /* domainLookupByID */ + xenapiDomainLookupByUUID, /* domainLookupByUUID */ + xenapiDomainLookupByName, /* domainLookupByName */ + xenapiDomainSuspend, /* domainSuspend */ + xenapiDomainResume, /* domainResume */ + xenapiDomainShutdown, /* domainShutdown */ + xenapiDomainReboot, /* domainReboot */ + xenapiDomainDestroy, /* domainDestroy */ + xenapiDomainGetOSType, /* domainGetOSType */ + xenapiDomainGetMaxMemory, /* domainGetMaxMemory */ + xenapiDomainSetMaxMemory, /* domainSetMaxMemory */ + NULL, /* domainSetMemory */ + xenapiDomainGetInfo, /* domainGetInfo */ + NULL, /* domainSave */ + NULL, /* domainRestore */ + NULL, /* domainCoreDump */ + xenapiDomainSetVcpus, /* domainSetVcpus */ + xenapiDomainPinVcpu, /* domainPinVcpu */ + xenapiDomainGetVcpus, /* domainGetVcpus */ + xenapiDomainGetMaxVcpus, /* domainGetMaxVcpus */ + NULL, /* domainGetSecurityLabel */ + NULL, /* nodeGetSecurityModel */ + xenapiDomainDumpXML, /* domainDumpXML */ + NULL, /* domainXmlFromNative */ + NULL, /* domainXmlToNative */ + xenapiListDefinedDomains, /* listDefinedDomains */ + xenapiNumOfDefinedDomains, /* numOfDefinedDomains */ + xenapiDomainCreate, /* domainCreate */ + xenapiDomainDefineXML, /* domainDefineXML */ + xenapiDomainUndefine, /* domainUndefine */ + NULL, /* domainAttachDevice */ + NULL, + NULL, /* domainDetachDevice */ + NULL, + xenapiDomainGetAutostart, /* domainGetAutostart */ + xenapiDomainSetAutostart, /* domainSetAutostart */ + xenapiDomainGetSchedulerType, /* domainGetSchedulerType */ + NULL, /* domainGetSchedulerParameters */ + NULL, /* domainSetSchedulerParameters */ + NULL, /* domainMigratePrepare */ + NULL, /* domainMigratePerform */ + NULL, /* domainMigrateFinish */ + NULL, /* domainBlockStats */ + NULL, /* domainInterfaceStats */ + NULL, + NULL, /* domainBlockPeek */ + NULL, /* domainMemoryPeek */ + xenapiNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */ + xenapiNodeGetFreeMemory, /* getFreeMemory */ + NULL, /* domainEventRegister */ + NULL, /* domainEventDeregister */ + NULL, /* domainMigratePrepare2 */ + NULL, /* domainMigrateFinish2 */ + NULL, /* nodeDeviceDettach */ + NULL, /* nodeDeviceReAttach */ + NULL, /* nodeDeviceReset */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +/** + * xenapiRegister: + * + * + * Returns the driver priority or -1 in case of error. + */ +int +xenapiRegister (void) +{ + return virRegisterDriver (&xenapiDriver); +} + +/* +* write_func +* used by curl to read data from the server +*/ +size_t +write_func(void *ptr, size_t size, size_t nmemb, void *comms_) +{ + xen_comms *comms = comms_; + size_t n = size * nmemb; + #ifdef PRINT_XML + printf("\n\n---Result from server -----------------------\n"); + printf("%s\n",((char*) ptr)); + fflush(stdout); + #endif + return (size_t) (comms->func(ptr, n, comms->handle) ? n : 0); +} + +/* +* call_func +* sets curl options, used with xen_session_login_with_password +*/ +int +call_func(const void *data, size_t len, void *user_handle, + void *result_handle, xen_result_func result_func) +{ + //(void)user_handle; + struct _xenapiPrivate *priv = (struct _xenapiPrivate *)user_handle; + #ifdef PRINT_XML + + printf("\n\n---Data to server: -----------------------\n"); + printf("%s\n",((char*) data)); + fflush(stdout); + #endif + CURL *curl = curl_easy_init(); + if (!curl) { + return -1; + } + xen_comms comms = { + .func = result_func, + .handle = result_handle + }; + curl_easy_setopt(curl, CURLOPT_URL, priv->url); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1); + #ifdef CURLOPT_MUTE + curl_easy_setopt(curl, CURLOPT_MUTE, 1); + #endif + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_func); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &comms); + curl_easy_setopt(curl, CURLOPT_POST, 1); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data); + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, len); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, priv->noVerify?0:1); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, priv->noVerify?0:2); + 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-03-08 12:44:19.000000000 +0000 @@ -0,0 +1,29 @@ +/* + * xenapi_driver.h.c: Xen API driver header file to be included in libvirt.c. + * Copyright (C) 2009, 2010 Citrix Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Sharadha Prabhakar + */ + + +#ifndef __VIR_XENAPI_PRIV_H__ +#define __VIR_XENAPI_PRIV_H__ + + +extern int xenapiRegister (void); + +#endif /* __VIR_XENAPI_PRIV_H__ */ diff -Nur ./libvirt_org/src/xenapi/xenapi_driver_private.h ./libvirt/src/xenapi/xenapi_driver_private.h --- ./libvirt_org/src/xenapi/xenapi_driver_private.h 1970-01-01 01:00:00.000000000 +0100 +++ ./libvirt/src/xenapi/xenapi_driver_private.h 2010-03-08 14:54:11.000000000 +0000 @@ -0,0 +1,61 @@ +/* + * xenapi_driver_private.h: Xen API driver's private header file. + * Copyright (C) 2009, 2010 Citrix Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Sharadha Prabhakar + */ + + +#ifndef __VIR_XENAPI_H__ +#define __VIR_XENAPI_H__ + +#include +#include +#include "virterror_internal.h" + +//#define PRINT_XML +#define VIR_FROM_THIS VIR_FROM_XENAPI +#define LIBVIRT_MODELNAME_LEN (32) +#define xenapiSessionErrorHandler(conn,errNum,buf) xenapiSessionErrorHandle(conn, errNum, \ + buf,__FILE__,__FUNCTION__,__LINE__) + +void +xenapiSessionErrorHandle(virConnectPtr conn, virErrorNumber errNum, + const char *buf, const char *filename, const char *func, size_t lineno); + +typedef struct +{ + xen_result_func func; + void *handle; +} xen_comms; + + +int +call_func(const void *data, size_t len, void *user_handle, + void *result_handle, xen_result_func result_func); +size_t +write_func(void *ptr, size_t size, size_t nmemb, void *comms); + +/* xenAPI driver's private data structure */ +struct _xenapiPrivate { + xen_session *session; + char *url; + int noVerify; + virCapsPtr caps; +}; + +#endif /* __VIR_XENAPI_H__ */ diff -Nur ./libvirt_org/src/xenapi/xenapi_utils.c ./libvirt/src/xenapi/xenapi_utils.c --- ./libvirt_org/src/xenapi/xenapi_utils.c 1970-01-01 01:00:00.000000000 +0100 +++ ./libvirt/src/xenapi/xenapi_utils.c 2010-03-09 15:08:41.000000000 +0000 @@ -0,0 +1,589 @@ +/* + * xenapi_utils.c: Xen API driver -- utils parts. + * Copyright (C) 2009, 2010 Citrix Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Sharadha Prabhakar + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "domain_conf.h" +#include "libvirt_internal.h" +#include "libvirt/libvirt.h" +#include "virterror_internal.h" +#include "datatypes.h" +#include "xenapi_driver_private.h" +#include "util.h" +#include "uuid.h" +#include "memory.h" +#include "driver.h" +#include "buf.h" +#include "xenapi_utils.h" +#include "util/logging.h" +#include "qparams.h" + +void +xenSessionFree(xen_session *session) +{ + int i; + if (session->error_description != NULL) + { + for (i = 0; i < session->error_description_count; i++) + free(session->error_description[i]); + free(session->error_description); + } + free((char *)session->session_id); + free(session); +} + +char * +xenapiUtil_RequestPassword(virConnectAuthPtr auth, const char *username, + const char *hostname) +{ + unsigned int ncred; + virConnectCredential cred; + char *prompt; + + memset(&cred, 0, sizeof(virConnectCredential)); + + if (virAsprintf(&prompt, "Enter %s password for %s", username, + hostname) < 0) { + return NULL; + } + + for (ncred = 0; ncred < auth->ncredtype; ncred++) { + if (auth->credtype[ncred] != VIR_CRED_PASSPHRASE && + auth->credtype[ncred] != VIR_CRED_NOECHOPROMPT) { + continue; + } + + cred.type = auth->credtype[ncred]; + cred.prompt = prompt; + cred.challenge = hostname; + cred.defresult = NULL; + cred.result = NULL; + cred.resultlen = 0; + + if ((*(auth->cb))(&cred, 1, auth->cbdata) < 0) { + VIR_FREE(cred.result); + } + + break; + } + + VIR_FREE(prompt); + + return cred.result; +} + +int +xenapiUtil_ParseQuery(virConnectPtr conn, xmlURIPtr uri, int *noVerify) +{ + int result = 0; + int i; + struct qparam_set *queryParamSet = NULL; + struct qparam *queryParam = NULL; + +#ifdef HAVE_XMLURI_QUERY_RAW + queryParamSet = qparam_query_parse(uri->query_raw); +#else + queryParamSet = qparam_query_parse(uri->query); +#endif + + if (queryParamSet == NULL) { + goto failure; + } + + for (i = 0; i < queryParamSet->n; i++) { + queryParam = &queryParamSet->p[i]; + if (STRCASEEQ(queryParam->name, "no_verify")) { + if (noVerify == NULL) { + continue; + } + if (virStrToLong_i(queryParam->value, NULL, 10, noVerify) < 0 || + (*noVerify != 0 && *noVerify != 1)) { + xenapiSessionErrorHandler(conn, VIR_ERR_INVALID_ARG, + "Query parameter 'no_verify' has unexpected value (should be 0 or 1)"); + goto failure; + } + } + } + + cleanup: + if (queryParamSet != NULL) { + free_qparam_set(queryParamSet); + } + + return result; + + failure: + result = -1; + + goto cleanup; +} + + + +enum xen_on_normal_exit +actionShutdownLibvirt2XenapiEnum(enum virDomainLifecycleAction action) +{ + enum xen_on_normal_exit num = XEN_ON_NORMAL_EXIT_RESTART; + if (action == VIR_DOMAIN_LIFECYCLE_DESTROY) + num = XEN_ON_NORMAL_EXIT_DESTROY; + else if (action == VIR_DOMAIN_LIFECYCLE_RESTART) + num = XEN_ON_NORMAL_EXIT_RESTART; + return num; +} + + +enum xen_on_crash_behaviour +actionCrashLibvirt2XenapiEnum(enum virDomainLifecycleAction action) +{ + enum xen_on_crash_behaviour num = XEN_ON_CRASH_BEHAVIOUR_RESTART; + if (action == VIR_DOMAIN_LIFECYCLE_DESTROY) + num = XEN_ON_CRASH_BEHAVIOUR_DESTROY; + else if (action == VIR_DOMAIN_LIFECYCLE_RESTART) + num = XEN_ON_CRASH_BEHAVIOUR_RESTART; + else if (action == VIR_DOMAIN_LIFECYCLE_PRESERVE) + num = XEN_ON_CRASH_BEHAVIOUR_PRESERVE; + else if (action == VIR_DOMAIN_LIFECYCLE_RESTART_RENAME) + num = XEN_ON_CRASH_BEHAVIOUR_RENAME_RESTART; + return num; +} + +/* generate XenAPI boot order format from libvirt format */ +char * +createXenAPIBootOrderString(int nboot, int *bootDevs) +{ + virBuffer ret = VIR_BUFFER_INITIALIZER; + char *val = NULL; + int i; + for (i=0;ierror_description_count-1; i++) { + if (!i) + virBufferEscapeString(&buf,"%s",session->error_description[i]); + else + virBufferEscapeString(&buf," : %s",session->error_description[i]); + } + return virBufferContentAndReset(&buf); +} + +/* converts bitmap to string of the form '1,2...' */ +char * +mapDomainPinVcpu(unsigned char *cpumap, int maplen) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + size_t len; + char *ret=NULL; + int i, j; + for (i = 0; i < maplen; i++) { + for (j = 0; j < 8; j++) { + if (cpumap[i] & (1 << j)) { + virBufferVSprintf(&buf,"%d,", (8*i)+j); + } + } + } + if (virBufferError(&buf)) { + virReportOOMError(); + virBufferFreeAndReset(&buf); + return NULL; + } + ret = virBufferContentAndReset(&buf); + len = strlen(ret); + if (len > 0 && ret[len - 1] == ',') + ret[len - 1] = 0; + return ret; +} + +/* obtains the CPU bitmap from the string passed */ +void +getCpuBitMapfromString(char *mask, unsigned char *cpumap, int maplen) +{ + int pos; + int max_bits = maplen * 8; + char *num = NULL,*bp=NULL; + bzero(cpumap, maplen); + num = strtok_r (mask, ",", &bp); + while (num != NULL) { + if (sscanf (num, "%d", &pos)!=1) + return; + if (pos<0 || pos>max_bits-1) + VIR_WARN ("number in str %d exceeds cpumap's max bits %d", pos, max_bits); + else + (cpumap)[pos/8] |= (1<<(pos%8)); + num = strtok_r (NULL, ",", &bp); + } +} + + +/* mapping XenServer power state to Libvirt power state */ +virDomainState +mapPowerState(enum xen_vm_power_state state) +{ + virDomainState virState; + switch (state) { + case (XEN_VM_POWER_STATE_HALTED): + case (XEN_VM_POWER_STATE_SUSPENDED): + virState = VIR_DOMAIN_SHUTOFF; + break; + case (XEN_VM_POWER_STATE_PAUSED): + virState = VIR_DOMAIN_PAUSED; + break; + case (XEN_VM_POWER_STATE_RUNNING): + virState = VIR_DOMAIN_RUNNING; + break; + case (XEN_VM_POWER_STATE_UNKNOWN): + case (XEN_VM_POWER_STATE_UNDEFINED): + virState = VIR_DOMAIN_NOSTATE; + break; + default: + virState = VIR_DOMAIN_NOSTATE; + break; + } + return virState; +} + +/* allocate a flexible array and fill values(key,val) */ +int +allocStringMap (xen_string_string_map **strings, char *key, char *val) +{ + int sz = ((*strings) == NULL)?0:(*strings)->size; + sz++; + if(VIR_REALLOC_N(*strings, sizeof(xen_string_string_map)+ + sizeof(xen_string_string_map_contents)*sz)<0) { + virReportOOMError(); + return -1; + } + (*strings)->size = sz; + if (!((*strings)->contents[sz-1].key = strdup(key))) goto cleanup; + if (!((*strings)->contents[sz-1].val = strdup(val))) goto cleanup; + return 0; + cleanup: + xen_string_string_map_free(*strings); + virReportOOMError(); + return -1; +} + +/* 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"), ret); + xen_session_clear_error(((struct _xenapiPrivate *)(conn->privateData))->session); + VIR_FREE(ret); + } else { + virReportErrorHelper (conn, VIR_FROM_XENAPI, errNum, filename, func, lineno, _("%s"), 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 ( (cntsize) && net_rec) { + xen_network network = NULL; + xen_network_get_by_uuid(((struct _xenapiPrivate *)(conn->privateData))->session, + &network, net_rec->uuid); + xen_network_record_opt *network_opt = xen_network_record_opt_alloc(); + network_opt->is_record = 0; + network_opt->u.handle = network; + xen_vif_record *vif_record = xen_vif_record_alloc(); + vif_record->mac = mac; + vif_record->vm = vm_opt; + vif_record->network = network_opt; + xen_vif vif=NULL; + + vif_record->other_config = xen_string_string_map_alloc(0); + vif_record->runtime_properties = xen_string_string_map_alloc(0); + vif_record->qos_algorithm_params = xen_string_string_map_alloc(0); + vif_record->device = strdup(device); + xen_vif_create(((struct _xenapiPrivate *)(conn->privateData))->session, + &vif, vif_record); + if (!vif) { + xen_vif_free(vif); + xen_vif_record_free(vif_record); + xen_network_record_free(net_rec); + xen_network_set_free(net_set); + return 0; + } + xen_vif_record_free(vif_record); + xen_network_record_free(net_rec); + } + if (net_set!=NULL) xen_network_set_free(net_set); + return -1; +} + +/* Create a VM record from the XML description */ +int +createVMRecordFromXml (virConnectPtr conn, virDomainDefPtr def, + xen_vm_record **record, xen_vm *vm) +{ + char uuidStr[VIR_UUID_STRING_BUFLEN]; + *record = xen_vm_record_alloc(); + if (!((*record)->name_label = strdup(def->name))) + goto error_cleanup; + if (def->uuid) { + virUUIDFormat(def->uuid,uuidStr); + if (!((*record)->uuid = strdup(uuidStr))) + goto error_cleanup; + } + if (STREQ(def->os.type,"hvm")) { + if(!((*record)->hvm_boot_policy = strdup("BIOS order"))) + goto error_cleanup; + char *boot_order = NULL; + if (def->os.nBootDevs!=0) + boot_order = createXenAPIBootOrderString(def->os.nBootDevs, &def->os.bootDevs[0]); + if (boot_order!=NULL) { + xen_string_string_map *hvm_boot_params=NULL; + allocStringMap(&hvm_boot_params, (char *)"order",boot_order); + (*record)->hvm_boot_params = hvm_boot_params; + VIR_FREE(boot_order); + } + } else if (STREQ(def->os.type,"xen")) { + if (!((*record)->pv_bootloader = strdup("pygrub"))) + goto error_cleanup; + if (def->os.kernel){ + if (!((*record)->pv_kernel = strdup(def->os.kernel))) + goto error_cleanup; + } + if (def->os.initrd) { + if (!((*record)->pv_ramdisk = strdup(def->os.initrd))) + goto error_cleanup; + } + if(def->os.cmdline) { + if (!((*record)->pv_args = strdup(def->os.cmdline))) + goto error_cleanup; + } + (*record)->hvm_boot_params = xen_string_string_map_alloc(0); + } + if (def->os.bootloaderArgs) + if(!((*record)->pv_bootloader_args = strdup(def->os.bootloaderArgs))) + goto error_cleanup; + + if (def->memory) + (*record)->memory_static_max = (int64_t) (def->memory * 1024); + if (def->maxmem) + (*record)->memory_dynamic_max = (int64_t) (def->maxmem * 1024); + else + (*record)->memory_dynamic_max = (*record)->memory_static_max; + + if (def->vcpus) { + (*record)->vcpus_max = (int64_t) def->vcpus; + (*record)->vcpus_at_startup = (int64_t) def->vcpus; + } + if (def->onPoweroff) + (*record)->actions_after_shutdown = actionShutdownLibvirt2XenapiEnum(def->onPoweroff); + if (def->onReboot) + (*record)->actions_after_reboot = actionShutdownLibvirt2XenapiEnum(def->onReboot); + if (def->onCrash) + (*record)->actions_after_crash = actionCrashLibvirt2XenapiEnum(def->onCrash); + + xen_string_string_map *strings=NULL; + if (def->features) { + if (def->features & (1<features & (1<features & (1<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;innets;i++) { + if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE) { + if (def->nets[i]->data.bridge.brname) + if(!(bridge = strdup(def->nets[i]->data.bridge.brname))) + goto error_cleanup; + if (def->nets[i]->mac) { + char macStr[VIR_MAC_STRING_BUFLEN]; + virFormatMacAddr(def->nets[i]->mac, macStr); + if(!(mac = strdup(macStr))) { + if (bridge) VIR_FREE(bridge); + goto error_cleanup; + } + } + if (mac!=NULL && bridge!=NULL) { + char device[NETWORK_DEVID_SIZE]="\0"; + sprintf(device,"%d",device_number); + createVifNetwork(conn, *vm, device, bridge, mac); + VIR_FREE(bridge); + device_number++; + } + if (bridge) VIR_FREE(bridge); + } + } + return 0; + + error_cleanup: + virReportOOMError(); + xen_vm_record_free(*record); + return -1; +} + diff -Nur ./libvirt_org/src/xenapi/xenapi_utils.h ./libvirt/src/xenapi/xenapi_utils.h --- ./libvirt_org/src/xenapi/xenapi_utils.h 1970-01-01 01:00:00.000000000 +0100 +++ ./libvirt/src/xenapi/xenapi_utils.h 2010-03-09 15:58:33.000000000 +0000 @@ -0,0 +1,112 @@ +/* + * xenapi_utils.h: Xen API driver -- utils header + * Copyright (C) 2009, 2010 Citrix Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Sharadha Prabhakar + */ + + +#ifndef _VIR_XENAPI_UTILS_ +#define _VIR_XENAPI_UTILS_ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 (12) + +typedef uint64_t cpumap_t; + +void +xenSessionFree(xen_session *session); + +char * +xenapiUtil_RequestPassword(virConnectAuthPtr auth, const char *username, + const char *hostname); + +int +xenapiUtil_ParseQuery(virConnectPtr conn, xmlURIPtr uri, int *noVerify); + +enum xen_on_normal_exit +actionShutdownLibvirt2XenapiEnum(enum virDomainLifecycleAction action); + +enum xen_on_crash_behaviour +actionCrashLibvirt2XenapiEnum(enum virDomainLifecycleAction action); + +char * +createXenAPIBootOrderString(int nboot, int *bootDevs); + +enum virDomainBootOrder map2LibvirtBootOrder(char c); + +enum virDomainLifecycleAction +xenapiNormalExitEnum2virDomainLifecycle(enum xen_on_normal_exit action); + +enum virDomainLifecycleAction +xenapiCrashExitEnum2virDomainLifecycle(enum xen_on_crash_behaviour action); + +void getCpuBitMapfromString(char *mask, unsigned char *cpumap, int maplen); + +int getStorageVolumeType(char *type); + +char *returnErrorFromSession(xen_session *session); + +virDomainState +mapPowerState(enum xen_vm_power_state state); + +char * +mapDomainPinVcpu(unsigned char *cpumap, int maplen); + +int +createVMRecordFromXml (virConnectPtr conn, virDomainDefPtr defPtr, + xen_vm_record **record, xen_vm *vm); + +int +allocStringMap (xen_string_string_map **strings, char *key, char *val); + +int +createVifNetwork(virConnectPtr conn, xen_vm vm, char *device, + char *bridge, char *mac); + +#endif //_VIR_XENAPI_UTILS_