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@xxxxxxxxxx> + */ + +#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@xxxxxxxxxx> + */ + +#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_ -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list