[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 4/4] Addition of XenAPI support to libvirt



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 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 *>

+    if (on_poweroff!=NULL) {

+        (*record)->actions_after_shutdown = actionShutdownStringtoEnum(on_poweroff);

+        VIR_FREE(on_poweroff);

+    }

+    char *>

+    if (on_reboot!=NULL) {

+        (*record)->actions_after_reboot = actionShutdownStringtoEnum(on_reboot);

+        VIR_FREE(on_reboot);

+    }

+    char *>

+    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 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_

 

 

 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]