Devel
Threads by month
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
February 2010
- 46 participants
- 257 discussions
This is an update to / deprecates the patchset I sent last night:
https://www.redhat.com/archives/libvir-list/2010-February/msg00580.html
I have corrected the problem found by Dan Berrange (neglecting to
restore the signal mask when fork() fails). Aside from that, and
corresponding comments in the commit logs, it is unchanged.
Here's the original intro email:
This was partly prompted by DV's suggestion last week.
The first of these patches creates a new function called virFork()
which behaves (almost) like fork() but takes care of some important
details that pretty much any call to fork() should be doing. The 2nd
switches three fork-calling functions in util.c over to using
virFork() instead of fork().
In the future, except for odd circumstances, code that needs to fork
should call virFork() instead, and if there is anything determined to
be universally necessary at fork-time, it should be added to virFork()
rather than to the callers of virFork(); hopefully this will ease
maintenance and reduce replicated bugs.
(Note that, while this is just an overall "code health" patch, a
couple bug fix patches I'll be submitting either tomorrow or Thursday
will assume it as a prerequisite).
2
3
Hello,
I would like to use -redir argument for qemu-kvm guest, but I can't find any
mention in docs about this option. Is there any way how to arrange port
redirection with libvirt? I can't use a bridge for networking, because I
can't use an IP address from host's range.
Thank you,
Jaromír Červenka
Official openSUSE community member
Web: http://www.cervajz.com/
Jabber: cervajz(a)cervajz.com
MSN: jara.cervenka(a)seznam.cz
Tel.: +420 607 592 687
Alt. e-mails:
jaromir.cervenka(a)opensuse.org,
jaromir.cervenka(a)speel.cz
1
0
How can I set viridian=1 using libvirt? Is it possible?
I haven't seen any reference about it on the xml format documentation
Best Regards,
Diego Dias
1
0
18 Feb '10
Resending patch 3/4 which didn't reach the first time seemingly.
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(a)citrix.com>
+*/
+
+#include <config.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <libxml/uri.h>
+#include <xen_internal.h>
+#include <libxml/parser.h>
+#include <curl/curl.h>
+#include <xen/api/xen_common.h>
+#include <xen/api/xen_vm.h>
+#include <xen/api/xen_vm.h>
+#include <xen/api/xen_all.h>
+#include <xen/api/xen_vm_metrics.h>
+
+#include "libvirt_internal.h"
+#include "libvirt/libvirt.h"
+#include "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(a)citrix.com>
+ */
+
+
+#ifndef __VIR_XENAPI_H__
+#define __VIR_XENAPI_H__
+
+#include <xen/api/xen_common.h>
+#include <libxml/tree.h>
+
+//#define PRINT_XML
+#define 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__ */
1
0
18 Feb '10
diff -Nur ./libvirt_org/src/xenapi/xenapi_utils.c ./libvirt/src/xenapi/xenapi_utils.c
--- ./libvirt_org/src/xenapi/xenapi_utils.c 1970-01-01 01:00:00.000000000 +0100
+++ ./libvirt/src/xenapi/xenapi_utils.c 2010-02-18 16:26:52.000000000 +0000
@@ -0,0 +1,507 @@
+/*
+ * xenapi_utils.c: Xen API driver -- utils parts.
+ * Copyright (C) 2009 Citrix Ltd.
+ * Sharadha Prabhakar <sharadha.prabhakar(a)citrix.com>
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <config.h>
+
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <libxml/uri.h>
+#include <xen_internal.h>
+#include <libxml/parser.h>
+#include <curl/curl.h>
+#include <xen/api/xen_common.h>
+#include <xen/api/xen_vm.h>
+#include <xen/api/xen_vm.h>
+#include <xen/api/xen_all.h>
+#include <xen/api/xen_vm_metrics.h>
+
+#include "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"
+
+/* returns 'file' or 'block' for the storage type */
+int
+getStorageVolumeType(char *type)
+{
+ if((STREQ(type,"lvmoiscsi")) ||
+ (STREQ(type,"lvmohba")) ||
+ (STREQ(type,"lvm")) ||
+ (STREQ(type,"file")) ||
+ (STREQ(type,"iso")) ||
+ (STREQ(type,"ext")) ||
+ (STREQ(type,"nfs")))
+ return (int)VIR_STORAGE_VOL_FILE;
+ else if((STREQ(type,"iscsi")) ||
+ (STREQ(type,"equal")) ||
+ (STREQ(type,"hba")) ||
+ (STREQ(type,"cslg")) ||
+ (STREQ(type,"udev")) ||
+ (STREQ(type,"netapp")))
+ return (int)VIR_STORAGE_VOL_BLOCK;
+ return -1;
+}
+
+/* returns error description if any received from the server */
+char *
+returnErrorFromSession(xen_session *session)
+{
+ int i;
+ char *buf = NULL;
+ for (i=0; i<session->error_description_count-1; i++) {
+ if (buf==NULL) {
+ buf = (char *)realloc(buf,strlen(session->error_description[i])+1);
+ strcpy(buf,session->error_description[i]);
+ } else {
+ buf = (char *)realloc(buf,strlen(buf)+strlen(session->error_description[i])+2);
+ strcat(buf,":");
+ strcat(buf,session->error_description[i]);
+ }
+ }
+ return buf;
+}
+
+/* XenAPI error handler - internally calls libvirt error handler after clearing error
+flag in session */
+void xenapiSessionErrorHandler(virConnectPtr conn, virErrorNumber errNum,
+ const char *buf, const char *filename, const char *func, size_t lineno)
+{
+ if (buf==NULL) {
+ char *ret=NULL;
+ ret = returnErrorFromSession(((struct _xenapiPrivate *)(conn->privateData))->session);
+ virReportErrorHelper (conn, VIR_FROM_XENAPI, errNum, filename, func, lineno, _("%s\n"), ret);
+ xen_session_clear_error(((struct _xenapiPrivate *)(conn->privateData))->session);
+ VIR_FREE(ret);
+ } else {
+ virReportErrorHelper (conn, VIR_FROM_XENAPI, errNum, filename, func, lineno, _("%s\n"), buf);
+ }
+}
+
+/* converts bitmap to string of the form '1,2...' */
+char *
+mapDomainPinVcpu(unsigned int vcpu, unsigned char *cpumap, int maplen)
+{
+ char buf[VIR_UUID_BUFLEN], mapstr[sizeof(cpumap_t) * 64];
+ char *ret=NULL;
+ int i, j;
+ mapstr[0] = 0;
+ for (i = 0; i < maplen; i++) {
+ for (j = 0; j < 8; j++) {
+ if (cpumap[i] & (1 << j)) {
+ snprintf(buf, sizeof(buf), "%d,", (8 * i) + j);
+ strcat(mapstr, buf);
+ }
+ }
+ }
+ mapstr[strlen(mapstr) - 1] = 0;
+ snprintf(buf, sizeof(buf), "%d", vcpu);
+ ret = strdup(mapstr);
+ return ret;
+}
+
+/* obtains the CPU bitmap from the string passed */
+void
+getCpuBitMapfromString(char *mask, unsigned char *cpumap, int maplen)
+{
+ int pos;
+ int max_bits = maplen * 8;
+ char *num = NULL;
+ bzero(cpumap, maplen);
+ num = strtok (mask, ",");
+ while (num != NULL) {
+ sscanf (num, "%d", &pos);
+ if (pos<0 || pos>max_bits-1)
+ printf ("number in str %d exceeds cpumap's max bits %d\n", pos, max_bits);
+ else
+ (cpumap)[pos/8] |= (1<<(pos%8));
+ num = strtok (NULL, ",");
+ }
+}
+
+
+/* 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;
+}
+
+/* Gets the value of the child for the current node passed */
+char *
+getXmlChildValue(xmlDocPtr doc, xmlNodePtr cur, const char *tag)
+{
+ char *key = NULL;
+ cur = cur->xmlChildrenNode;
+ while (cur != NULL) {
+ if ((!xmlStrcmp(cur->name, (const xmlChar *)tag))){
+ cur = cur->xmlChildrenNode;
+ key = (char *)xmlNodeListGetString(doc,cur,1);
+ }
+ cur = cur->next;
+ }
+ return key;
+}
+
+/* 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++;
+ *strings = realloc(*strings,sizeof(xen_string_string_map)+
+ sizeof(xen_string_string_map_contents)*sz);
+ (*strings)->size = sz;
+ (*strings)->contents[sz-1].key = strdup(key);
+ (*strings)->contents[sz-1].val = strdup(val);
+ return 0;
+}
+
+/* create boot order string as understood by libvirt */
+void
+createXmlBootOrderString(char **order, char *key)
+{
+ int sz = ((*order)==NULL)?0:(strlen(*order)+1);
+ const char *temp=NULL;
+ if (strcmp(key,"fd")==0)
+ temp="a";
+ else if (strcmp(key,"hd")==0)
+ temp="c";
+ else if (strcmp(key,"cdrom")==0)
+ temp="d";
+ else if (strcmp(key,"network")==0)
+ temp="n";
+ if (temp!=NULL) {
+ *order = (char *)realloc(*order,sz+strlen(temp)+1);
+ if(sz==0) strcpy(*order,temp);
+ else strcat(*order,temp);
+ }
+}
+
+enum xen_on_normal_exit
+actionShutdownStringtoEnum(char *str)
+{
+ enum xen_on_normal_exit code = XEN_ON_NORMAL_EXIT_UNDEFINED;
+ if (STREQ(str, "destroy"))
+ code = XEN_ON_NORMAL_EXIT_DESTROY;
+ else if (STREQ(str, "restart"))
+ code = XEN_ON_NORMAL_EXIT_RESTART;
+ return code;
+}
+
+enum xen_on_crash_behaviour
+actionCrashStringtoEnum(char *str)
+{
+ enum xen_on_crash_behaviour code = XEN_ON_CRASH_BEHAVIOUR_UNDEFINED;
+ if (STREQ(str, "destroy"))
+ code = XEN_ON_CRASH_BEHAVIOUR_DESTROY;
+ else if (STREQ(str, "restart"))
+ code = XEN_ON_CRASH_BEHAVIOUR_RESTART;
+ else if (STREQ(str, "preserve"))
+ code = XEN_ON_CRASH_BEHAVIOUR_PRESERVE;
+ else if (STREQ(str, "rename-restart"))
+ code = XEN_ON_CRASH_BEHAVIOUR_RENAME_RESTART;
+ return code;
+}
+
+/* convert boot order string libvirt format to XenServer format */
+const char *
+mapXmlBootOrder(char c) {
+ switch(c) {
+ case 'a':
+ return "fd";
+ case 'c':
+ return "hd";
+ case 'd':
+ return "cdrom";
+ case 'n':
+ return "network";
+ default:
+ return NULL;
+ }
+}
+
+/* creates network intereface for VM */
+int
+createVifNetwork (virConnectPtr conn, xen_vm vm, char *device,
+ char *bridge, char *mac)
+{
+ xen_vm xvm = NULL;
+ char *uuid = NULL;
+ xen_vm_get_uuid(((struct _xenapiPrivate *)(conn->privateData))->session, &uuid, vm);
+ if (uuid) {
+ if(!xen_vm_get_by_uuid(((struct _xenapiPrivate *)(conn->privateData))->session,
+ &xvm, uuid))
+ return -1;
+ VIR_FREE(uuid);
+ }
+ xen_vm_record_opt *vm_opt = xen_vm_record_opt_alloc();
+ vm_opt->is_record = 0;
+ vm_opt->u.handle = xvm;
+ xen_network_set *net_set = NULL;
+ xen_network_record *net_rec = NULL;
+ int cnt=0;
+ if (xen_network_get_all(((struct _xenapiPrivate *)(conn->privateData))->session, &net_set)) {
+ for(cnt=0;cnt<(net_set->size);cnt++) {
+ if (xen_network_get_record(((struct _xenapiPrivate *)(conn->privateData))->session,
+ &net_rec, net_set->contents[cnt])) {
+ if (STREQ(net_rec->bridge,bridge)) {
+ break;
+ } else {
+ xen_network_record_free(net_rec);
+ }
+ }
+ }
+ }
+ if ( (cnt<net_set->size) && net_rec) {
+ xen_network network = NULL;
+ xen_network_get_by_uuid(((struct _xenapiPrivate *)(conn->privateData))->session,
+ &network, net_rec->uuid);
+ xen_network_record_opt *network_opt = xen_network_record_opt_alloc();
+ network_opt->is_record = 0;
+ network_opt->u.handle = network;
+ xen_vif_record *vif_record = xen_vif_record_alloc();
+ vif_record->mac = mac;
+ vif_record->vm = vm_opt;
+ vif_record->network = network_opt;
+ xen_vif vif=NULL;
+
+ vif_record->other_config = xen_string_string_map_alloc(0);
+ vif_record->runtime_properties = xen_string_string_map_alloc(0);
+ vif_record->qos_algorithm_params = xen_string_string_map_alloc(0);
+ vif_record->device = strdup(device);
+ xen_vif_create(((struct _xenapiPrivate *)(conn->privateData))->session,
+ &vif, vif_record);
+ if (vif!=NULL) {
+ xen_vif_free(vif);
+ xen_vif_record_free(vif_record);
+ xen_network_record_free(net_rec);
+ xen_network_set_free(net_set);
+ return 0;
+ }
+ xen_vif_record_free(vif_record);
+ xen_network_record_free(net_rec);
+ }
+ if (net_set!=NULL) xen_network_set_free(net_set);
+ return -1;
+}
+
+/* Create a VM record from the XML description */
+int
+createVMRecordFromXml (virConnectPtr conn, const char *xmlDesc,
+ xen_vm_record **record, xen_vm *vm)
+{
+ xmlDocPtr doc;
+ xmlNodePtr cur,child,temp;
+ doc = xmlParseMemory(xmlDesc,strlen(xmlDesc));
+ if (doc == NULL) {
+ xenapiSessionErrorHandler(conn,VIR_ERR_XML_ERROR ,"", __FILE__, __FUNCTION__, __LINE__);
+ return -1;
+ }
+ cur = xmlDocGetRootElement(doc);
+ if (cur == NULL) {
+ xenapiSessionErrorHandler(conn,VIR_ERR_XML_ERROR ,"", __FILE__, __FUNCTION__, __LINE__);
+ xmlFreeDoc(doc);
+ return -1;
+ }
+ if (xmlStrcmp(cur->name, (const xmlChar *) "domain")) {
+ xenapiSessionErrorHandler(conn,VIR_ERR_XML_ERROR ,"root node not domain", __FILE__, __FUNCTION__, __LINE__);
+ xmlFreeDoc(doc);
+ return -1;
+ }
+ *record = xen_vm_record_alloc();
+ char *name = getXmlChildValue(doc,cur,"name");
+ (*record)->name_label = strdup(name);
+ child = cur->xmlChildrenNode;
+ while (child!=NULL) {
+ if ((!xmlStrcmp(child->name, (const xmlChar *)"os"))) {
+ char *ostype = getXmlChildValue(doc,child,"type");
+ if (ostype!=NULL) {
+ if (STREQ(ostype,"hvm")) {
+ (*record)->hvm_boot_policy = strdup("BIOS order");
+ temp = child;
+ child = child->xmlChildrenNode;
+ char *boot_order = NULL;
+ while (child != NULL) {
+ if ((!xmlStrcmp(child->name, (const xmlChar *)"boot"))){
+ xmlChar *key;
+ key = xmlGetProp(child, (const xmlChar *)"dev");
+ if (key!=NULL) {
+ createXmlBootOrderString(&boot_order,(char *)key);
+ xmlFree(key);
+ }
+ }
+ child = child->next;
+ }
+ if (boot_order!=NULL) {
+ xen_string_string_map *hvm_boot_params=NULL;
+ allocStringMap(&hvm_boot_params, (char *)"order",boot_order);
+ //int size = sizeof(xen_string_string_map) +
+ // (hvm_boot_params->size * sizeof(xen_string_string_map_contents));
+ //(*record)->hvm_boot_params = (xen_string_string_map *) malloc(size);
+ //memcpy((char *)(*record)->hvm_boot_params, (char *)hvm_boot_params, size);
+ (*record)->hvm_boot_params = hvm_boot_params;
+ VIR_FREE(boot_order);
+ //freeStringMap(hvm_boot_params);
+ }
+ child = temp;
+ } else if (STREQ(ostype,"linux")) {
+ (*record)->pv_bootloader = strdup("pygrub");
+ char *kernel = getXmlChildValue(doc,child,"kernel");
+ if (kernel != NULL){
+ (*record)->pv_kernel = kernel;
+ //strcpy((*record)->pv_kernel,kernel);
+ //free(kernel);
+ }
+ char *initrd = getXmlChildValue(doc,child,"initrd");
+ if (initrd != NULL) {
+ (*record)->pv_ramdisk = initrd;//(char *)malloc(strlen(initrd)+1);
+ //strcpy((*record)->pv_ramdisk,initrd);
+ //free(initrd);
+ }
+ char *cmdline = getXmlChildValue(doc,child,"cmdline");
+ if (cmdline != NULL) {
+ (*record)->pv_args = cmdline; //(char *)malloc(strlen(cmdline)+1);
+ //strcpy((*record)->pv_args,cmdline);
+ //free(cmdline);
+ }
+ (*record)->hvm_boot_params = xen_string_string_map_alloc(0);
+ }
+ VIR_FREE(ostype);
+ }
+ }
+ child = child->next;
+ }
+ char *bootload_args = getXmlChildValue(doc,cur,"bootloader_args");
+ if (bootload_args!=NULL) {
+ (*record)->pv_bootloader_args =bootload_args; //(char *)malloc(strlen(bootload_args)+1);
+ //strcpy((*record)->pv_bootloader_args,bootload_args);
+ //free(bootload_args);
+ }
+ char *memory = getXmlChildValue(doc,cur,"memory");
+ if (memory!=NULL) {
+ int64_t static_max=0;
+ static_max = atoll(memory);
+ (*record)->memory_static_max = static_max * 1024;
+ VIR_FREE(memory);
+ }
+ char *curmemory = getXmlChildValue(doc,cur,"currentmemory");
+ if (curmemory!=NULL) {
+ int64_t dy_max=0;
+ dy_max = atoll(curmemory);
+ (*record)->memory_dynamic_max = dy_max * 1024;
+ VIR_FREE(curmemory);
+ } else {
+ (*record)->memory_dynamic_max = (*record)->memory_static_max;
+ }
+ char *vcpu = getXmlChildValue(doc, cur, "vcpu");
+ if (vcpu!=NULL) {
+ (*record)->vcpus_max = atoll(vcpu);
+ (*record)->vcpus_at_startup = atoll(vcpu);
+ VIR_FREE(vcpu);
+ }
+ char *on_poweroff = getXmlChildValue(doc,cur,"on_poweroff");
+ if (on_poweroff!=NULL) {
+ (*record)->actions_after_shutdown = actionShutdownStringtoEnum(on_poweroff);
+ VIR_FREE(on_poweroff);
+ }
+ char *on_reboot = getXmlChildValue(doc,cur,"on_reboot");
+ if (on_reboot!=NULL) {
+ (*record)->actions_after_reboot = actionShutdownStringtoEnum(on_reboot);
+ VIR_FREE(on_reboot);
+ }
+ char *on_crash = getXmlChildValue(doc,cur,"on_crash");
+ if (on_crash!=NULL) {
+ (*record)->actions_after_crash = actionCrashStringtoEnum(on_crash);
+ VIR_FREE(on_crash);
+ }
+ temp = cur;
+ cur = cur->xmlChildrenNode;
+ xen_string_string_map *strings=NULL;
+ while (cur != NULL) {
+ if ((!xmlStrcmp(cur->name, (const xmlChar *)"features"))){
+ for (child=cur->children;child!=NULL;child=child->next) {
+ allocStringMap(&strings,(char *)child->name,(char *)"true");
+ }
+ }
+ cur = cur->next;
+ }
+ cur = temp;
+ if (strings!=NULL) {
+ //int size = sizeof(xen_string_string_map)+ sizeof(xen_string_string_map_contents)*strings->size;
+ (*record)->platform = strings; //(xen_string_string_map *)malloc(size);
+ //memcpy((void *)(*record)->platform,(void *)strings,size);
+ }
+ (*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)) {
+ xmlFreeDoc(doc);
+ xenapiSessionErrorHandler(conn,VIR_ERR_INTERNAL_ERROR ,NULL, __FILE__, __FUNCTION__, __LINE__);
+ return -1;
+ }
+ cur = cur->xmlChildrenNode;
+ int device_number=0;
+ xmlChar *bridge=NULL,*mac=NULL;
+ while (cur != NULL) {
+ if ((!xmlStrcmp(cur->name, (const xmlChar *)"interface"))){
+ for (child=cur->children;child!=NULL;child=child->next) {
+ if ((!xmlStrcmp(child->name, (const xmlChar *)"source"))) {
+ bridge = xmlGetProp(child, (const xmlChar *)"bridge");
+ }
+ if ((!xmlStrcmp(child->name, (const xmlChar *)"mac"))) {
+ mac = xmlGetProp(child, (const xmlChar *)"address");
+ }
+ }
+ if (mac!=NULL && bridge!=NULL) {
+ char device[NETWORK_DEVID_SIZE]="\0";
+ sprintf(device,"%d",device_number);
+ createVifNetwork(conn, *vm, device, (char *)bridge, (char *)mac);
+ xmlFree(bridge);
+ device_number++;
+ }
+ }
+ cur = cur->next;
+ }
+ xmlFreeDoc(doc);
+ return 0;
+}
+
diff -Nur ./libvirt_org/src/xenapi/xenapi_utils.h ./libvirt/src/xenapi/xenapi_utils.h
--- ./libvirt_org/src/xenapi/xenapi_utils.h 1970-01-01 01:00:00.000000000 +0100
+++ ./libvirt/src/xenapi/xenapi_utils.h 2010-02-18 16:28:10.000000000 +0000
@@ -0,0 +1,94 @@
+/*
+ * xenapi_utils.h: Xen API driver -- utils header
+ * Copyright (C) 2009 Citrix Ltd.
+ * Sharadha Prabhakar <sharadha.prabhakar(a)citrix.com>
+ */
+
+#ifndef _VIR_XENAPI_UTILS_
+#define _VIR_XENAPI_UTILS_
+
+#include <stdio.h>
+#include <string.h>
+#include <config.h>
+
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <libxml/uri.h>
+#include <xen_internal.h>
+#include <libxml/parser.h>
+#include <curl/curl.h>
+#include <xen/api/xen_common.h>
+#include <xen/api/xen_vm.h>
+#include <xen/api/xen_vm.h>
+#include <xen/api/xen_all.h>
+#include <xen/api/xen_vm_metrics.h>
+//#include <xen/dom0_ops.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"
+
+#define NETWORK_DEVID_SIZE (10)
+
+typedef uint64_t cpumap_t;
+
+void getCpuBitMapfromString(char *mask, unsigned char *cpumap, int maplen);
+
+int getStorageVolumeType(char *type);
+
+char *returnErrorFromSession(xen_session *session);
+
+void xenapiSessionErrorHandler(virConnectPtr conn, virErrorNumber errNum,
+ const char *buf, const char *filename, const char *func, size_t lineno);
+
+
+virDomainState
+mapPowerState(enum xen_vm_power_state state);
+
+char *
+mapDomainPinVcpu(unsigned int vcpu, unsigned char *cpumap, int maplen);
+
+char *
+getXmlChildValue(xmlDocPtr doc, xmlNodePtr cur, const char *tag);
+
+int
+createVMRecordFromXml (virConnectPtr conn, const char *xmlDesc,
+ xen_vm_record **record, xen_vm *vm);
+
+int
+allocStringMap (xen_string_string_map **strings, char *key, char *val);
+
+void
+createXmlBootOrderString(char **order, char *key);
+
+enum xen_on_normal_exit
+actionShutdownStringtoEnum(char *str);
+
+enum xen_on_crash_behaviour
+actionCrashStringtoEnum(char *str);
+
+int
+createVifNetwork(virConnectPtr conn, xen_vm vm, char *device,
+ char *bridge, char *mac);
+
+const char *
+mapXmlBootOrder(char c);
+
+
+
+
+
+
+
+#endif //_VIR_XENAPI_UTILS_
1
0
18 Feb '10
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(a)citrix.com>
+*/
+
+#include <config.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <libxml/uri.h>
+#include <xen_internal.h>
+#include <libxml/parser.h>
+#include <curl/curl.h>
+#include <xen/api/xen_common.h>
+#include <xen/api/xen_vm.h>
+#include <xen/api/xen_vm.h>
+#include <xen/api/xen_all.h>
+#include <xen/api/xen_vm_metrics.h>
+
+#include "libvirt_internal.h"
+#include "libvirt/libvirt.h"
+#include "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(a)citrix.com>
+ */
+
+
+#ifndef __VIR_XENAPI_H__
+#define __VIR_XENAPI_H__
+
+#include <xen/api/xen_common.h>
+#include <libxml/tree.h>
+
+//#define PRINT_XML
+#define 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__ */
1
0
18 Feb '10
diff -ur ./libvirt_org/src/libvirt.c ./libvirt/src/libvirt.c
--- ./libvirt_org/src/libvirt.c 2010-02-17 17:38:08.000000000 +0000
+++ ./libvirt/src/libvirt.c 2010-02-18 12:21:43.000000000 +0000
@@ -64,6 +64,9 @@
#ifdef WITH_ESX
#include "esx/esx_driver.h"
#endif
+#ifdef WITH_XENAPI
+#include "xenapi/xenapi_driver.h"
+#endif
#endif
#define VIR_FROM_THIS VIR_FROM_NONE
@@ -357,6 +360,7 @@
virDriverLoadModule("openvz");
virDriverLoadModule("vbox");
virDriverLoadModule("esx");
+ virDriverLoadModule("xenapi");
virDriverLoadModule("remote");
#else
#ifdef WITH_TEST
@@ -377,6 +381,9 @@
#ifdef WITH_ESX
if (esxRegister() == -1) return -1;
#endif
+#ifdef WITH_XENAPI
+ if (xenapiRegister () == -1) return -1;
+#endif
#ifdef WITH_REMOTE
if (remoteRegister () == -1) return -1;
#endif
@@ -1035,6 +1042,10 @@
if (STRCASEEQ(type, "Remote"))
*typeVer = remoteVersion();
#endif
+#if WITH_XENAPI
+ if (STRCASEEQ(type, "XenAPI"))
+ *typeVer = LIBVIR_VERSION_NUMBER;
+#endif
if (*typeVer == 0) {
virLibConnError(NULL, VIR_ERR_NO_SUPPORT, type);
goto error;
diff -ur ./libvirt_org/src/driver.h ./libvirt/src/driver.h
--- ./libvirt_org/src/driver.h 2010-02-17 17:38:08.000000000 +0000
+++ ./libvirt/src/driver.h 2010-02-18 10:45:54.000000000 +0000
@@ -27,6 +27,7 @@
VIR_DRV_ONE = 9,
VIR_DRV_ESX = 10,
VIR_DRV_PHYP = 11,
+ VIR_DRV_XENAPI = 12
} virDrvNo;
diff -ur ./libvirt_org/include/libvirt/virterror.h ./libvirt/include/libvirt/virterror.h
--- ./libvirt_org/include/libvirt/virterror.h 2010-02-17 17:37:51.000000000 +0000
+++ ./libvirt/include/libvirt/virterror.h 2010-02-18 12:17:54.000000000 +0000
@@ -69,6 +69,7 @@
VIR_FROM_PHYP, /* Error from IBM power hypervisor */
VIR_FROM_SECRET, /* Error from secret storage */
VIR_FROM_CPU, /* Error from CPU driver */
+ VIR_FROM_XENAPI /* Error from XenAPI */
} virErrorDomain;
diff -ur ./libvirt_org/src/util/virterror.c ./libvirt/src/util/virterror.c
--- ./libvirt_org/src/util/virterror.c 2010-02-17 17:38:14.000000000 +0000
+++ ./libvirt/src/util/virterror.c 2010-02-18 12:13:08.000000000 +0000
@@ -85,6 +85,9 @@
case VIR_FROM_XEN:
dom = "Xen ";
break;
+ case VIR_FROM_XENAPI:
+ dom = "XenAPI ";
+ break;
case VIR_FROM_XML:
dom = "XML ";
break;
Only in ./libvirt/src: xenapi
1
0
These patches rebase my previously posted virtio-serial patches, add support for
max_ports and vectors, and allow multiple virtio-serial devices to be used. I
wasn't going to bother with the latter, however it turns out this can be useful
if the user wants more than 31 virtserialports.
N.B. These apply on top of 2 previously posted patches. Specifically "Fix whitespace in domain.rng" and "Remove unused functions from domain_conf".
4
13
18 Feb '10
---
src/remote/remote_driver.c | 37 ++++++++++++++++++++++++++++++++++---
1 files changed, 34 insertions(+), 3 deletions(-)
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 13534ce..7f92fd0 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -154,6 +154,7 @@ struct private_data {
virMutex lock;
int sock; /* Socket. */
+ int errsock; /* Socket connected to remote stderr */
int watch; /* File handle watch */
pid_t pid; /* PID of tunnel process */
int uses_tls; /* TLS enabled on socket? */
@@ -783,6 +784,7 @@ doRemoteOpen (virConnectPtr conn,
case trans_ext: {
pid_t pid;
int sv[2];
+ int errsock[2];
/* Fork off the external process. Use socketpair to create a private
* (unnamed) Unix domain socket to the child process so we don't have
@@ -794,14 +796,21 @@ doRemoteOpen (virConnectPtr conn,
goto failed;
}
+ if (socketpair (PF_UNIX, SOCK_STREAM, 0, errsock) == -1) {
+ virReportSystemError(errno, "%s",
+ _("unable to create socket pair"));
+ goto failed;
+ }
+
if (virExec((const char**)cmd_argv, NULL, NULL,
- &pid, sv[1], &(sv[1]), NULL,
+ &pid, sv[1], &(sv[1]), &(errsock[1]),
VIR_EXEC_CLEAR_CAPS) < 0)
goto failed;
/* Parent continues here. */
close (sv[1]);
priv->sock = sv[0];
+ priv->errsock = errsock[0];
priv->pid = pid;
/* Do not set 'is_secure' flag since we can't guarentee
@@ -827,6 +836,12 @@ doRemoteOpen (virConnectPtr conn,
goto failed;
}
+ if ((priv->errsock != -1) && virSetNonBlock(priv->errsock) < 0) {
+ virReportSystemError(errno, "%s",
+ _("unable to make socket non-blocking"));
+ goto failed;
+ }
+
if (pipe(wakeupFD) < 0) {
virReportSystemError(errno, "%s",
_("unable to make pipe"));
@@ -939,6 +954,9 @@ doRemoteOpen (virConnectPtr conn,
failed:
/* Close the socket if we failed. */
+ if (priv->errsock >= 0)
+ close(priv->errsock);
+
if (priv->sock >= 0) {
if (priv->uses_tls && priv->session) {
gnutls_bye (priv->session, GNUTLS_SHUT_RDWR);
@@ -986,6 +1004,7 @@ remoteAllocPrivateData(virConnectPtr conn)
priv->localUses = 1;
priv->watch = -1;
priv->sock = -1;
+ priv->errsock = -1;
return priv;
}
@@ -1408,6 +1427,7 @@ doRemoteClose (virConnectPtr conn, struct private_data *priv)
sasl_dispose (&priv->saslconn);
#endif
close (priv->sock);
+ close (priv->errsock);
#ifndef WIN32
if (priv->pid > 0) {
@@ -7785,12 +7805,23 @@ remoteIOReadBuffer(virConnectPtr conn,
if (errno == EWOULDBLOCK)
return 0;
+ char errout[1024] = "\0";
+ if (priv->errsock) {
+ recv(priv->errsock, errout, sizeof(errout), 0);
+ }
+
virReportSystemError(errno,
- "%s", _("cannot recv data"));
+ _("cannot recv data: %s"), errout);
+
} else {
+ char errout[1024] = "\0";
+ if (priv->errsock) {
+ recv(priv->errsock, errout, sizeof(errout), 0);
+ }
+
errorf (in_open ? NULL : conn,
VIR_ERR_SYSTEM_ERROR,
- "%s", _("server closed connection"));
+ _("server closed connection: %s"), errout);
}
return -1;
}
--
1.6.5.2
2
2
Remove virDomainDevicePCIAddressEqual and virDomainDeviceDriveAddressEqual,
which are defined but not used anywhere.
* src/conf/domain_conf.[ch]: Remove virDomainDevicePCIAddressEqual and
virDomainDeviceDriveAddressEqual.
---
src/conf/domain_conf.c | 24 ------------------------
src/conf/domain_conf.h | 4 ----
2 files changed, 0 insertions(+), 28 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 7f3df78..df35209 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -972,30 +972,6 @@ static int virDomainDeviceInfoFormat(virBufferPtr buf,
#ifndef PROXY
-int virDomainDevicePCIAddressEqual(virDomainDevicePCIAddressPtr a,
- virDomainDevicePCIAddressPtr b)
-{
- if (a->domain == b->domain &&
- a->bus == b->bus &&
- a->slot == b->slot &&
- a->function == b->function)
- return 1;
-
- return 0;
-}
-
-
-int virDomainDeviceDriveAddressEqual(virDomainDeviceDriveAddressPtr a,
- virDomainDeviceDriveAddressPtr b)
-{
- if (a->controller == b->controller &&
- a->bus == b->bus &&
- a->unit == b->unit)
- return 1;
-
- return 0;
-}
-
static int
virDomainDevicePCIAddressParseXML(xmlNodePtr node,
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index d9b2f28..307d9b5 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -743,10 +743,6 @@ void virDomainWatchdogDefFree(virDomainWatchdogDefPtr def);
void virDomainVideoDefFree(virDomainVideoDefPtr def);
void virDomainHostdevDefFree(virDomainHostdevDefPtr def);
void virDomainDeviceDefFree(virDomainDeviceDefPtr def);
-int virDomainDevicePCIAddressEqual(virDomainDevicePCIAddressPtr a,
- virDomainDevicePCIAddressPtr b);
-int virDomainDeviceDriveAddressEqual(virDomainDeviceDriveAddressPtr a,
- virDomainDeviceDriveAddressPtr b);
int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info,
int type);
int virDomainDevicePCIAddressIsValid(virDomainDevicePCIAddressPtr addr);
--
1.6.6
2
3