From b811851b8df557433b65ec021852464f023c2bc7 Mon Sep 17 00:00:00 2001 From: Daniel Veillard Date: Mon, 25 May 2009 11:56:00 +0000 Subject: [PATCH] Include the OpenNebula driver * src/opennebula/one_conf.[ch] src/opennebula/one_driver.[ch]: the OpenNebula driver * configure.in include/libvirt/virterror.h qemud/Makefile.am qemud/qemud.c src/Makefile.am src/domain_conf.[ch] src/driver.h src/libvirt.c src/virterror.c: integration of the OpenNebula driver in the libvirt infrastructure * AUTHORS: add Abel Miguez Rodriguez daniel --- AUTHORS | 1 + ChangeLog | 10 + configure.in | 17 + include/libvirt/virterror.h | 1 + qemud/Makefile.am | 4 + qemud/qemud.c | 7 + src/Makefile.am | 26 ++ src/domain_conf.c | 3 +- src/domain_conf.h | 1 + src/driver.h | 1 + src/libvirt.c | 4 + src/opennebula/one_conf.c | 259 ++++++++++++ src/opennebula/one_conf.h | 52 +++ src/opennebula/one_driver.c | 794 ++++++++++++++++++++++++++++++++++++ src/opennebula/one_driver.h | 30 ++ src/virterror.c | 3 + 16 files changed, 1212 insertions(+), 1 deletion(-) create mode 100644 src/opennebula/one_conf.c create mode 100644 src/opennebula/one_conf.h create mode 100644 src/opennebula/one_driver.c create mode 100644 src/opennebula/one_driver.h diff --git a/AUTHORS b/AUTHORS index e4c2a32745..dcb6ea58d7 100644 --- a/AUTHORS +++ b/AUTHORS @@ -70,6 +70,7 @@ Patches have also been contributed by: Serge E. Hallyn Soren Hansen Laine Stump + Abel Míguez Rodríguez [....send patches to get your name here....] diff --git a/ChangeLog b/ChangeLog index 2d844e252f..77af7d77ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Mon May 25 13:52:30 CEST 2009 Daniel Veillard + + * src/opennebula/one_conf.[ch] src/opennebula/one_driver.[ch]: + the OpenNebula driver + * configure.in include/libvirt/virterror.h qemud/Makefile.am + qemud/qemud.c src/Makefile.am src/domain_conf.[ch] src/driver.h + src/libvirt.c src/virterror.c: integration of the OpenNebula + driver in the libvirt infrastructure + * AUTHORS: add Abel Miguez Rodriguez + Mon May 25 11:42:15 CEST 2009 Daniel Veillard * examples/domain-events/events-c/event-test.c: fixed the example diff --git a/configure.in b/configure.in index 73a02d2b78..d2674adf27 100644 --- a/configure.in +++ b/configure.in @@ -190,6 +190,8 @@ AC_ARG_WITH([vbox], [ --with-vbox add VirtualBox support (on)],[],[with_vbox=yes]) AC_ARG_WITH([lxc], [ --with-lxc add Linux Container support (on)],[],[with_lxc=yes]) +AC_ARG_WITH([one], +[ --with-one add ONE support (on)],[],[with_one=no]) AC_ARG_WITH([test], [ --with-test add test driver support (on)],[],[with_test=yes]) AC_ARG_WITH([remote], @@ -309,6 +311,11 @@ if test "$with_uml" = "yes" ; then fi AM_CONDITIONAL([WITH_UML], [test "$with_uml" = "yes"]) +if test "$with_one" = "yes" ; then + AC_DEFINE_UNQUOTED([WITH_ONE],1,[whether ONE driver is enabled]) +fi +AM_CONDITIONAL([WITH_ONE],[test "$with_one" = "yes"]) + if test "$with_test" = "yes" ; then AC_DEFINE_UNQUOTED([WITH_TEST], 1, [whether Test driver is enabled]) fi @@ -410,6 +417,15 @@ dnl check for kvm headers dnl AC_CHECK_HEADERS([linux/kvm.h]) +dnl OpenNebula driver Compilation setting +dnl + +if test "$with_one" = "yes" ; then + CFLAGS="$CFLAGS -I$ONE_LOCATION/include" + ONE_LIBS="-L/usr/local/lib -lxmlrpc_client++ -lxmlrpc -lxmlrpc_util -lxmlrpc_xmlparse -lxmlrpc_xmltok -lxmlrpc++ -lxmlrpc_client -L$ONE_LOCATION/lib -loneapi" + AC_SUBST([ONE_LIBS]) +fi + dnl Need to test if pkg-config exists PKG_PROG_PKG_CONFIG @@ -1414,6 +1430,7 @@ AC_MSG_NOTICE([ UML: $with_uml]) AC_MSG_NOTICE([ OpenVZ: $with_openvz]) AC_MSG_NOTICE([ VBox: $with_vbox]) AC_MSG_NOTICE([ LXC: $with_lxc]) +AC_MSG_NOTICE([ ONE: $with_one]) AC_MSG_NOTICE([ Test: $with_test]) AC_MSG_NOTICE([ Remote: $with_remote]) AC_MSG_NOTICE([ Network: $with_network]) diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 3613ac2995..109289663d 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -64,6 +64,7 @@ typedef enum { VIR_FROM_SECURITY, /* Error from security framework */ VIR_FROM_VBOX, /* Error from VirtualBox driver */ VIR_FROM_INTERFACE, /* Error when operating on an interface */ + VIR_FROM_ONE, /* Error from OpenNebula driver */ } virErrorDomain; diff --git a/qemud/Makefile.am b/qemud/Makefile.am index 9b8e6bac93..d5b1064232 100644 --- a/qemud/Makefile.am +++ b/qemud/Makefile.am @@ -122,6 +122,10 @@ if WITH_UML libvirtd_LDADD += ../src/libvirt_driver_uml.la endif +if WITH_ONE + libvirtd_LDADD += ../src/libvirt_driver_one.la +endif + if WITH_STORAGE_DIR libvirtd_LDADD += ../src/libvirt_driver_storage.la endif diff --git a/qemud/qemud.c b/qemud/qemud.c index 0ac9462a7f..137556015f 100644 --- a/qemud/qemud.c +++ b/qemud/qemud.c @@ -75,6 +75,9 @@ #ifdef WITH_UML #include "uml_driver.h" #endif +#ifdef WITH_ONE +#include "opennebula/one_driver.h" +#endif #ifdef WITH_NETWORK #include "network_driver.h" #endif @@ -815,6 +818,7 @@ static struct qemud_server *qemudInitialize(int sigread) { virDriverLoadModule("qemu"); virDriverLoadModule("lxc"); virDriverLoadModule("uml"); + virDriverLoadModule("one"); #else #ifdef WITH_NETWORK networkRegister(); @@ -835,6 +839,9 @@ static struct qemud_server *qemudInitialize(int sigread) { #ifdef WITH_UML umlRegister(); #endif +#ifdef WITH_ONE + oneRegister(); +#endif #endif virEventRegisterImpl(virEventAddHandleImpl, diff --git a/src/Makefile.am b/src/Makefile.am index 81331686c9..76d178302d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -145,6 +145,12 @@ UML_DRIVER_SOURCES = \ uml_conf.c uml_conf.h \ uml_driver.c uml_driver.h +ONE_DRIVER_SOURCES = \ + ./opennebula/one_conf.c \ + ./opennebula/one_conf.h \ + ./opennebula/one_driver.c \ + ./opennebula/one_driver.h + NETWORK_DRIVER_SOURCES = \ network_driver.h network_driver.c @@ -338,6 +344,25 @@ endif libvirt_driver_uml_la_SOURCES = $(UML_DRIVER_SOURCES) endif +if WITH_ONE +if WITH_DRIVER_MODULES +mod_LTLIBRARIES += libvirt_driver_one.la +else +noinst_LTLIBRARIES += libvirt_driver_one.la +# Stateful, so linked to daemon instead +#libvirt_la_LIBADD += libvirt_driver_one.la +endif +libvirt_driver_one_la_LDFLAGS = $(ONE_LIBS) +#libvirt_driver_one_la_CFLAGS = "-DWITH_ONE" +if WITH_DRIVER_MODULES +libvirt_driver_one_la_LDFLAGS += -module -avoid-version +endif +libvirt_driver_one_la_SOURCES = $(ONE_DRIVER_SOURCES) +endif + + + + if WITH_NETWORK if WITH_DRIVER_MODULES mod_LTLIBRARIES += libvirt_driver_network.la @@ -435,6 +460,7 @@ EXTRA_DIST += \ $(QEMU_DRIVER_SOURCES) \ $(LXC_DRIVER_SOURCES) \ $(UML_DRIVER_SOURCES) \ + $(ONE_DRIVER_SOURCES) \ $(OPENVZ_DRIVER_SOURCES) \ $(VBOX_DRIVER_SOURCES) \ $(NETWORK_DRIVER_SOURCES) \ diff --git a/src/domain_conf.c b/src/domain_conf.c index d7c4166d4c..f9e576bf94 100644 --- a/src/domain_conf.c +++ b/src/domain_conf.c @@ -55,7 +55,8 @@ VIR_ENUM_IMPL(virDomainVirt, VIR_DOMAIN_VIRT_LAST, "test", "vmware", "hyperv", - "vbox") + "vbox", + "one") VIR_ENUM_IMPL(virDomainBoot, VIR_DOMAIN_BOOT_LAST, "fd", diff --git a/src/domain_conf.h b/src/domain_conf.h index bc1b49f20e..bba78609b8 100644 --- a/src/domain_conf.h +++ b/src/domain_conf.h @@ -49,6 +49,7 @@ enum virDomainVirtType { VIR_DOMAIN_VIRT_VMWARE, VIR_DOMAIN_VIRT_HYPERV, VIR_DOMAIN_VIRT_VBOX, + VIR_DOMAIN_VIRT_ONE, VIR_DOMAIN_VIRT_LAST, }; diff --git a/src/driver.h b/src/driver.h index 15709178e1..7957915d2d 100644 --- a/src/driver.h +++ b/src/driver.h @@ -21,6 +21,7 @@ typedef enum { VIR_DRV_LXC = 6, VIR_DRV_UML = 7, VIR_DRV_VBOX = 8, + VIR_DRV_ONE = 9, } virDrvNo; diff --git a/src/libvirt.c b/src/libvirt.c index c601b94698..d50e972e2f 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -904,6 +904,10 @@ virGetVersion(unsigned long *libVer, const char *type, if (STRCASEEQ(type, "UML")) *typeVer = LIBVIR_VERSION_NUMBER; #endif +#if WITH_ONE + if (STRCASEEQ(type, "ONE")) + *typeVer = LIBVIR_VERSION_NUMBER; +#endif #if WITH_REMOTE if (STRCASEEQ(type, "Remote")) *typeVer = remoteVersion(); diff --git a/src/opennebula/one_conf.c b/src/opennebula/one_conf.c new file mode 100644 index 0000000000..3d28197d28 --- /dev/null +++ b/src/opennebula/one_conf.c @@ -0,0 +1,259 @@ +/*----------------------------------------------------------------------------------*/ +/* Copyright 2002-2009, Distributed Systems Architecture Group, Universidad + * Complutense de Madrid (dsa-research.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/*-----------------------------------------------------------------------------------*/ + +#include +#include + +#include "virterror_internal.h" +#include "one_conf.h" +#include "buf.h" +#include "memory.h" +#include "util.h" + +#define VIR_FROM_THIS VIR_FROM_ONE +/* --------------------------------------------------------------------------------- */ + +/** + * oneCapsInit initialize the driver capabilities + * @return a pointer to the driver capabilities NULL in case of error + */ + +virCapsPtr oneCapsInit(void) +{ + struct utsname utsname; + virCapsPtr caps; + virCapsGuestPtr guest; + + uname(&utsname); + + if ((caps = virCapabilitiesNew(utsname.machine,0,0)) == NULL) + { + goto no_memory; + } + + virCapabilitiesSetMacPrefix(caps,(unsigned char[]){ 0x52, 0x54, 0x00 }); + + if ((guest = virCapabilitiesAddGuest(caps, + "hvm", + "i686", + 32, + NULL, + NULL, + 0, + NULL)) == NULL) + { + goto no_memory; + } + + if (virCapabilitiesAddGuestDomain(guest, + "one", + NULL, + NULL, + 0, + NULL) == NULL) + { + goto no_memory; + } + + + if ((guest = virCapabilitiesAddGuest(caps, + "hvm", + "x86_64", + 64, + NULL, + NULL, + 0, + NULL)) == NULL) + { + goto no_memory; + } + + if (virCapabilitiesAddGuestDomain(guest, + "one", + NULL, + NULL, + 0, + NULL) == NULL) + { + goto no_memory; + } + + return caps; + +no_memory: + + virCapabilitiesFree(caps); + return NULL; +} + +/* --------------------------------------------------------------------------------- */ +/* --------------------------------------------------------------------------------- */ +/* --------------------------------------------------------------------------------- */ + + +/** + * oneSubmitVM generates an OpenNebula description file and submits the new VM + * @param driver the OpenNebula driver + * @param vm the virtual machine pointer + * @return the OpenNebula ID for the new VM or -1 in case of error + */ + +int oneSubmitVM(virConnectPtr conn, + one_driver_t* driver ATTRIBUTE_UNUSED, + virDomainObjPtr vm) +{ + char* templ; + int oneid; + + if((templ=xmlOneTemplate(conn,vm->def))==NULL ) + return -1; + + if( (oneid=c_oneAllocateTemplate(templ))<0 ){ + oneError(conn, NULL, VIR_ERR_OPERATION_FAILED, + "Error submitting virtual machine to OpenNebula"); + VIR_FREE(templ); + return -1; + } + + VIR_FREE(templ); + return oneid; +} +/* --------------------------------------------------------------------------------- */ +/* --------------------------------------------------------------------------------- */ +/* --------------------------------------------------------------------------------- */ + +/** + * xmlOneTemplate Generate an OpenNebula template to deploy a VM from libvirt + * internal Domain definition. + * @param def Internal libvirt Domain definition + * @return OpenNebula VM template. + */ + +char* xmlOneTemplate(virConnectPtr conn,virDomainDefPtr def) +{ + int i; + virBuffer buf= VIR_BUFFER_INITIALIZER; + virBufferVSprintf(&buf,"#OpenNebula Template automatically generated by libvirt\nNAME = %s\nCPU = %ld\nMEMORY = %ld\n", + def->name, + def->vcpus, + (def->maxmem)/1024); + + /*Optional Booting OpenNebula Information:*/ + if( def->os.kernel ){ + virBufferVSprintf(&buf,"OS=[ kernel = \"%s\"",def->os.kernel); + if(def->os.initrd) + virBufferVSprintf(&buf,",\n initrd = \"%s\"",def->os.initrd); + if(def->os.cmdline) + virBufferVSprintf(&buf,",\n kernel_cmd = \"%s\"",def->os.cmdline); + if(def->os.root) + virBufferVSprintf(&buf,",\n root = \"%s\"",def->os.root); + + virBufferAddLit(&buf," ]\n"); + } + /* set Disks & NICS */ + for(i=0 ; indisks ; i++){ + // missing source is only allowed at cdrom and floppy + if(def->disks[i]->device==VIR_DOMAIN_DISK_DEVICE_DISK){ + virBufferVSprintf(&buf, "DISK=[ type = disk,\n" + " source = \"%s\",\n", + def->disks[i]->src); + } + else if(def->disks[i]->device==VIR_DOMAIN_DISK_DEVICE_CDROM){ + virBufferAddLit(&buf, "DISK=[ type = cdrom,\n"); + if(def->disks[i]->src) virBufferVSprintf(&buf, " source = \"%s\",\n",def->disks[i]->src); + } + else if(def->disks[i]->device==VIR_DOMAIN_DISK_DEVICE_FLOPPY){ + virBufferAddLit(&buf, "DISK=[ type = floppy,\n"); + if(def->disks[i]->src) virBufferVSprintf(&buf, " source = \"%s\",\n",def->disks[i]->src); + } + + virBufferVSprintf(&buf, " target = \"%s\",\n" + " readonly =", + def->disks[i]->dst); + + if(def->disks[i]->readonly) + virBufferAddLit(&buf,"\"yes\"]\n"); + else + virBufferAddLit(&buf,"\"no\"]\n"); + } + + for(i=0 ; i< def->nnets ; i++) + { + if ( !def->nets[i] ) { + continue; + } + + switch(def->nets[i]->type) + { + case VIR_DOMAIN_NET_TYPE_BRIDGE: + virBufferVSprintf(&buf,"NIC=[ bridge =\"%s\",\n",def->nets[i]->data.bridge.brname); + + if(def->nets[i]->ifname) + virBufferVSprintf(&buf," target =\"%s\",\n",def->nets[i]->ifname); + + virBufferVSprintf(&buf," mac =\"%02x:%02x:%02x:%02x:%02x:%02x\" ]\n", + def->nets[i]->mac[0],def->nets[i]->mac[1], + def->nets[i]->mac[2],def->nets[i]->mac[3], + def->nets[i]->mac[4],def->nets[i]->mac[5]); + break; + + case VIR_DOMAIN_NET_TYPE_NETWORK: + virBufferVSprintf(&buf,"NIC=[ network=\"%s\"",def->nets[i]->data.network.name); + if(def->nets[i]->ifname) + virBufferVSprintf(&buf,",\n target =\"%s\"",def->nets[i]->ifname); + virBufferAddLit(&buf," ]\n"); + break; + + default: break; + } + } + + if(def->graphics!=NULL){ + if(def->graphics->type==VIR_DOMAIN_GRAPHICS_TYPE_VNC){ + virBufferAddLit(&buf,"GRAPHICS = [\n type = \"vnc\""); + + if(def->graphics->data.vnc.listenAddr!=NULL) + virBufferVSprintf(&buf,",\n listen = \"%s\"",def->graphics->data.vnc.listenAddr); + + if(def->graphics->data.vnc.autoport==0) + virBufferVSprintf(&buf,",\n port = \"%d\"",def->graphics->data.vnc.port); + + if(def->graphics->data.vnc.passwd!=NULL) + virBufferVSprintf(&buf,",\n passwd = \"%s\"",def->graphics->data.vnc.passwd); + + virBufferAddLit(&buf," ]\n"); + + } + else //graphics.type==VIR_DOMAIN_GRAPHICS_TYPE_SDL + virBufferAddLit(&buf,"GRAPHICS = [\n type = \"sdl\" ]\n"); + + } + if (virBufferError(&buf)) + goto no_memory; + + return virBufferContentAndReset(&buf); + + no_memory: + virReportOOMError(conn); + char* tmp = virBufferContentAndReset(&buf); + VIR_FREE(tmp); + return NULL; +}; + diff --git a/src/opennebula/one_conf.h b/src/opennebula/one_conf.h new file mode 100644 index 0000000000..3355c25541 --- /dev/null +++ b/src/opennebula/one_conf.h @@ -0,0 +1,52 @@ +/*----------------------------------------------------------------------------------*/ +/* Copyright 2002-2009, Distributed Systems Architecture Group, Universidad + * Complutense de Madrid (dsa-research.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/*-----------------------------------------------------------------------------------*/ + +#ifndef ONE_CONF_H +#define ONE_CONF_H + +#include + +#include "internal.h" +#include "domain_conf.h" +#include "capabilities.h" +#include "threads.h" + +struct one_driver{ + virMutex lock; + + virCapsPtr caps; + virDomainObjList domains; + int nextid; +}; + +typedef struct one_driver one_driver_t; + +virCapsPtr oneCapsInit(void); + +int oneSubmitVM(virConnectPtr conn ,one_driver_t* driver, virDomainObjPtr vm); + +char* xmlOneTemplate(virConnectPtr conn,virDomainDefPtr def); + +#define oneError(conn, dom, code, fmt...) \ + virReportErrorHelper(conn, VIR_FROM_ONE, code, __FILE__, \ + __FUNCTION__, __LINE__, fmt) + +#endif /* ONE_CONF_H */ + diff --git a/src/opennebula/one_driver.c b/src/opennebula/one_driver.c new file mode 100644 index 0000000000..d279ec1554 --- /dev/null +++ b/src/opennebula/one_driver.c @@ -0,0 +1,794 @@ +/*---------------------------------------------------------------------------*/ +/* Copyright 2002-2009, Distributed Systems Architecture Group, Universidad + * Complutense de Madrid (dsa-research.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/*---------------------------------------------------------------------------*/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "virterror_internal.h" +#include "logging.h" +#include "datatypes.h" +#include "one_conf.h" +#include "one_driver.h" +#include "memory.h" +#include "util.h" +#include "bridge.h" +#include "veth.h" + +#define VIR_FROM_THIS VIR_FROM_ONE + +static int oneStartup(void); +static int oneShutdown(void); +static int oneActive(void); + +static void oneDriverLock(one_driver_t* driver) +{ + virMutexLock(&driver->lock); +} + +static void oneDriverUnlock(one_driver_t* driver) +{ + virMutexUnlock(&driver->lock); +} + +static one_driver_t *one_driver =NULL; + + +static virDrvOpenStatus oneOpen(virConnectPtr conn, + virConnectAuthPtr auth ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED) +{ + /* Verify uri was specified */ + if (conn->uri == NULL) { + conn->uri = xmlParseURI("one:///"); + if (!conn->uri) { + virReportOOMError(conn); + return VIR_DRV_OPEN_ERROR; + } + } else if (conn->uri->scheme == NULL || + STRNEQ(conn->uri->scheme, "one")) { + goto declineConnection; + } + conn->privateData = one_driver; + + return VIR_DRV_OPEN_SUCCESS; + +declineConnection: + return VIR_DRV_OPEN_DECLINED; +} + +static int oneClose(virConnectPtr conn) +{ + conn->privateData = NULL; + return 0; +} + +static virDomainPtr oneDomainLookupByID(virConnectPtr conn, + int id) +{ + one_driver_t *driver = (one_driver_t *)conn->privateData; + virDomainPtr dom = NULL; + virDomainObjPtr vm = NULL; + + oneDriverLock(driver); + vm = virDomainFindByID(&driver->domains, id); + oneDriverUnlock(driver); + + if (!vm) { + oneError(conn, NULL, VIR_ERR_NO_DOMAIN, NULL); + goto return_point; + } + + dom = virGetDomain(conn, vm->def->name, vm->def->uuid); + if (dom) { + dom->id = vm->def->id; + } + +return_point: + if(vm) { + virDomainObjUnlock(vm); + } + + return dom; +} + +static virDomainPtr oneDomainLookupByUUID(virConnectPtr conn, + const unsigned char *uuid) +{ + one_driver_t *driver = (one_driver_t *)conn->privateData; + virDomainPtr dom = NULL; + virDomainObjPtr vm = NULL; + + oneDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, uuid); + oneDriverUnlock(driver); + if (!vm) { + oneError(conn, NULL, VIR_ERR_NO_DOMAIN, NULL); + goto return_point; + } + + dom = virGetDomain(conn, vm->def->name, vm->def->uuid); + if (dom) { + dom->id = vm->def->id; + } + +return_point: + if(vm) { + virDomainObjUnlock(vm); + } + + return dom; +} + +static virDomainPtr oneDomainLookupByName(virConnectPtr conn, + const char *name) +{ + one_driver_t *driver = (one_driver_t *)conn->privateData; + virDomainObjPtr vm = NULL; + virDomainPtr dom=NULL; + + oneDriverLock(driver); + vm = virDomainFindByName(&driver->domains, name); + oneDriverUnlock(driver); + + if (!vm) { + oneError(conn, NULL, VIR_ERR_NO_DOMAIN, NULL); + goto return_point; + } + + dom = virGetDomain(conn, vm->def->name, vm->def->uuid); + if (dom) { + dom->id = vm->def->id; + } +return_point: + if(vm) { + virDomainObjUnlock(vm); + } + + return dom; +} + +static int oneListDomains(virConnectPtr conn, int *ids, int nids) +{ + one_driver_t *driver = (one_driver_t *)conn->privateData; + int got = 0, i; + + oneDriverLock(driver); + for (i = 0 ; i < driver->domains.count && got < nids ; i++){ + virDomainObjLock(driver->domains.objs[i]); + if (virDomainIsActive(driver->domains.objs[i])) + ids[got++] = driver->domains.objs[i]->def->id; + virDomainObjUnlock(driver->domains.objs[i]); + } + oneDriverUnlock(driver); + + return got; +} + +static int oneNumDomains(virConnectPtr conn) +{ + one_driver_t *driver = (one_driver_t *)conn->privateData; + int n = 0, i; + + oneDriverLock(driver); + for (i = 0 ; i < driver->domains.count ; i++){ + virDomainObjLock(driver->domains.objs[i]); + if (virDomainIsActive(driver->domains.objs[i])) + n++; + virDomainObjUnlock(driver->domains.objs[i]); + } + oneDriverUnlock(driver); + + return n; +} + +static int oneListDefinedDomains(virConnectPtr conn, + char **const names, int nnames) { + one_driver_t *driver = (one_driver_t *)conn->privateData; + int got = 0, i; + + oneDriverLock(driver); + for (i = 0 ; i < driver->domains.count && got < nnames ; i++) { + virDomainObjLock(driver->domains.objs[i]); + if (!virDomainIsActive(driver->domains.objs[i])) { + if (!(names[got++] = strdup(driver->domains.objs[i]->def->name))) { + virReportOOMError(conn); + virDomainObjUnlock(driver->domains.objs[i]); + goto cleanup; + } + } + virDomainObjUnlock(driver->domains.objs[i]); + } + oneDriverUnlock(driver); + + return got; + + cleanup: + for (i = 0 ; i < got ; i++) + VIR_FREE(names[i]); + oneDriverUnlock(driver); + + return -1; +} + +static int oneNumDefinedDomains(virConnectPtr conn) +{ + one_driver_t *driver = (one_driver_t *)conn->privateData; + int n = 0, i; + + oneDriverLock(driver); + for (i = 0 ; i < driver->domains.count ; i++){ + virDomainObjLock(driver->domains.objs[i]); + if (!virDomainIsActive(driver->domains.objs[i])) + n++; + virDomainObjUnlock(driver->domains.objs[i]); + } + oneDriverUnlock(driver); + + return n; +} + +static virDomainPtr oneDomainDefine(virConnectPtr conn, const char *xml) +{ + one_driver_t *driver = (one_driver_t *)conn->privateData; + virDomainDefPtr def; + virDomainObjPtr vm; + virDomainPtr dom=NULL; + + oneDriverLock(driver); + if (!(def = virDomainDefParseString(conn, driver->caps, xml, + VIR_DOMAIN_XML_INACTIVE))) + goto return_point; + + if (!(vm = virDomainAssignDef(conn, &driver->domains, def))) { + virDomainDefFree(def); + goto return_point; + } + + vm->def->id = -1; + vm->persistent = 1; + dom = virGetDomain(conn, vm->def->name, vm->def->uuid); + if (dom) { + dom->id = vm->def->id; + } + virDomainObjUnlock(vm); + +return_point: + oneDriverUnlock(driver); + return dom; +} + + +static int oneDomainUndefine(virDomainPtr dom) +{ + one_driver_t *driver = (one_driver_t *)dom->conn->privateData; + virDomainObjPtr vm = NULL; + int ret=-1; + + oneDriverLock(driver); + vm =virDomainFindByUUID(&driver->domains, dom->uuid); + if (!vm) { + oneError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN, + "no domain with matching uuid"); + goto return_point; + } + + if (!vm->persistent) { + oneError(dom->conn, dom, VIR_ERR_INTERNAL_ERROR, + "cannot undefine transient domain"); + goto return_point; + } + virDomainRemoveInactive(&driver->domains, vm); + ret=0; + +return_point: + oneDriverUnlock(driver); + return ret; +} + +static int oneDomainGetInfo(virDomainPtr dom, + virDomainInfoPtr info) +{ + one_driver_t *driver = (one_driver_t *)dom->conn->privateData; + struct timeval tv; + virDomainObjPtr vm; + oneDriverLock(driver); + vm= virDomainFindByUUID(&driver->domains, dom->uuid); + oneDriverUnlock(driver); + + if (!vm) { + oneError(dom->conn,dom, VIR_ERR_INVALID_DOMAIN, + "%s", _("no domain with matching uuid")); + return -1; + } + + if(gettimeofday(&tv,NULL)<0) { + oneError(dom->conn,dom, VIR_ERR_INTERNAL_ERROR, + "%s",_("getting time of day")); + virDomainObjUnlock(vm); + return -1; + } + + if (!virDomainIsActive(vm)) { + info->cpuTime = 0; + } else { + char vm_info[257]; + c_oneVmInfo(vm->pid,vm_info,256); + //State: + char* cptr = strstr(vm_info,"STATE"); + cptr = index(cptr, ':'); + cptr++; + int one_state=atoi(cptr); + + switch(one_state) { + case 3: /** running */ + if (vm->state!=VIR_DOMAIN_SHUTDOWN) + vm->state=VIR_DOMAIN_RUNNING; + break; + case 5: /** pause */ + vm->state=VIR_DOMAIN_PAUSED; + break; + case 6: /** done */ + vm->state=VIR_DOMAIN_SHUTOFF; + vm->def->id=-1; + break; + case 7: /** error */ + vm->state=VIR_DOMAIN_CRASHED; + break; + default: + break; + }; + //Memory: + cptr=strstr(vm_info,"MEMORY"); + cptr=index(cptr,':'); + cptr++; + vm->def->memory = atoi(cptr); + + //run time: + cptr=strstr(vm_info,"START TIME"); + cptr=index(cptr,':'); + cptr++; + long starttime = atol(cptr); + info->cpuTime = (tv.tv_sec - starttime) *1000ll *1000ll *1000ll; + + } + + info->state = vm->state; + info->maxMem = vm->def->maxmem; + info->memory = vm->def->memory; + info->nrVirtCpu = vm->def->vcpus; + + virDomainObjUnlock(vm); + return 0; +} + +static char *oneGetOSType(virDomainPtr dom) +{ + + one_driver_t *driver = (one_driver_t *)dom->conn->privateData; + virDomainObjPtr vm = NULL; + + oneDriverLock(driver); + vm =virDomainFindByUUID(&driver->domains, dom->uuid); + oneDriverUnlock(driver); + if (!vm) { + oneError(dom->conn,dom, VIR_ERR_INVALID_DOMAIN, + "%s", _("no domain with matching uuid")); + return NULL; + } + + virDomainObjUnlock(vm); + return strdup(vm->def->os.type); +} + +static int oneDomainStart(virDomainPtr dom) +{ + virConnectPtr conn = dom->conn; + one_driver_t *driver = (one_driver_t *)(conn->privateData); + virDomainObjPtr vm; + int ret = -1; + int oneid; + + oneDriverLock(driver); + vm = virDomainFindByName(&driver->domains, dom->name); + + if (!vm) { + oneError(conn, dom, VIR_ERR_INVALID_DOMAIN, + "no domain named %s", dom->name); + goto return_point; + } + if((oneid = oneSubmitVM(dom->conn,driver,vm)) < 0) { + goto return_point; + } + vm->pid=oneid; + vm->def->id=driver->nextid++; + vm->state=VIR_DOMAIN_BLOCKED; + ret=0; + +return_point: + if(vm) + virDomainObjUnlock(vm); + oneDriverUnlock(driver); + + return ret; +} + +static virDomainPtr +oneDomainCreateAndStart(virConnectPtr conn, + const char *xml, + unsigned int flags ATTRIBUTE_UNUSED) { + one_driver_t *driver = (one_driver_t *)conn->privateData; + virDomainObjPtr vm = NULL; + virDomainDefPtr def; + virDomainPtr dom = NULL; + int oneid; + + oneDriverLock(driver); + if (!(def = virDomainDefParseString(conn, driver->caps, xml, + VIR_DOMAIN_XML_INACTIVE))) + goto return_point; + + vm = virDomainFindByName(&driver->domains, def->name); + if (vm) { + oneError(conn,NULL, VIR_ERR_OPERATION_FAILED, + _("Already an OpenNebula VM active with the name: \"%s\" id: %d "), + def->name,def->id); + goto return_point; + } + + if (!(vm = virDomainAssignDef(conn, &driver->domains, def))) { + virDomainDefFree(def); + goto return_point; + } + if ((oneid = oneSubmitVM(conn, driver, vm)) < 0) { + virDomainRemoveInactive(&driver->domains, vm); + vm=NULL; + goto return_point; + } + + vm->def->id=driver->nextid++; + vm->persistent=0; + vm->pid=oneid; + vm->state=VIR_DOMAIN_BLOCKED; + + dom = virGetDomain(conn, vm->def->name, vm->def->uuid); + if (dom) { + dom->id = vm->def->id; + } + +return_point: + if(vm) + virDomainObjUnlock(vm); + oneDriverUnlock(driver); + + return dom; +} + +static int oneDomainShutdown(virDomainPtr dom) +{ + one_driver_t *driver = (one_driver_t*)dom->conn->privateData; + virDomainObjPtr vm; + int ret=-1; + + oneDriverLock(driver); + if((vm=virDomainFindByID(&driver->domains, dom->id))) { + if(!(c_oneShutdown(vm->pid) ) ) { + vm->state=VIR_DOMAIN_SHUTDOWN; + ret= 0; + goto return_point; + } + oneError(dom->conn, dom, VIR_ERR_OPERATION_FAILED, + "Wrong state to perform action"); + goto return_point; + } + oneError(dom->conn,dom, VIR_ERR_INVALID_DOMAIN, + _("no domain with id %d"), dom->id); + goto return_point; + + if (!vm->persistent) { + virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } +return_point: + if(vm) + virDomainObjUnlock(vm); + oneDriverUnlock(driver); + + return ret; +} + +static int oneDomainDestroy(virDomainPtr dom) +{ + one_driver_t *driver = (one_driver_t*)dom->conn->privateData; + virDomainObjPtr vm; + int ret=-1; + + oneDriverLock(driver); + vm= virDomainFindByID(&driver->domains, dom->id); + if (!vm) { + oneError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN, + "no domain with id %d", dom->id); + goto return_point; + } + if(c_oneCancel(vm->pid)) { + /* VM not running, delete the instance at ONE DB */ + if(c_oneFinalize(vm->pid)){ + oneError(dom->conn, dom, VIR_ERR_OPERATION_FAILED, + "Wrong state to perform action"); + goto return_point; + } + } + if(!vm->persistent) { + virDomainRemoveInactive(&driver->domains,vm); + vm=NULL; + } + ret=0; + +return_point: + if(vm) + virDomainObjUnlock(vm); + + oneDriverUnlock(driver); + + return ret; +} + +static int oneDomainSuspend(virDomainPtr dom) +{ + one_driver_t* driver=dom->conn->privateData; + virDomainObjPtr vm; + int ret=-1; + + oneDriverLock(driver); + if ((vm=virDomainFindByID(&driver->domains,dom->id))){ + + if (vm->state == VIR_DOMAIN_RUNNING) { + if( !(c_oneSuspend(vm->pid)) ) { + vm->state=VIR_DOMAIN_PAUSED; + ret=0; + goto return_point; + } + oneError(dom->conn, dom, VIR_ERR_OPERATION_FAILED, + "Wrong state to perform action"); + goto return_point; + } + oneError(dom->conn,dom,VIR_ERR_OPERATION_FAILED, + "domain is not running"); + } else { + oneError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN, + "no domain with matching id %d", dom->id); + } + +return_point: + if(vm) + virDomainObjUnlock(vm); + oneDriverUnlock(driver); + + return ret; +}; + +static int oneDomainResume(virDomainPtr dom) +{ + one_driver_t* driver=dom->conn->privateData; + virDomainObjPtr vm; + int ret=-1; + + oneDriverLock(driver); + if ((vm=virDomainFindByID(&driver->domains,dom->id))) { + if (vm->state == VIR_DOMAIN_PAUSED) { + if( !(c_oneResume(vm->pid)) ) { + vm->state=VIR_DOMAIN_RUNNING; + ret=0; + goto return_point; + } + oneError(dom->conn, dom, VIR_ERR_OPERATION_FAILED, + "Wrong state to perform action"); + goto return_point; + } + oneError(dom->conn,dom,VIR_ERR_OPERATION_FAILED, + "domain is not paused "); + } else { + oneError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN, + "no domain with matching id %d", dom->id); +} + +return_point: + if(vm) + virDomainObjUnlock(vm); + oneDriverUnlock(driver); + + return ret; +}; + +static int oneStartup(void){ + + if (VIR_ALLOC(one_driver) < 0) { + return -1; + } + + if(virMutexInit(&one_driver->lock)<0){ + VIR_FREE(one_driver); + return -1; + } + + c_oneStart(); + oneDriverLock(one_driver); + one_driver->nextid=1; + if ((one_driver->caps = oneCapsInit()) == NULL) { + oneDriverUnlock(one_driver); + VIR_FREE(one_driver); + return -1; + } + oneDriverUnlock(one_driver); + + return 0; +} + +static int oneShutdown(void){ + if (one_driver == NULL) + return(-1); + + oneDriverLock(one_driver); + virDomainObjListFree(&one_driver->domains); + + virCapabilitiesFree(one_driver->caps); + oneDriverUnlock(one_driver); + virMutexDestroy(&one_driver->lock); + VIR_FREE(one_driver); + one_driver = NULL; + c_oneFree(); + return 0; +} + +static int oneActive(void){ + unsigned int i; + int active = 0; + + if (one_driver == NULL) + return(0); + + oneDriverLock(one_driver); + for (i = 0 ; i < one_driver->domains.count ; i++) { + virDomainObjLock(one_driver->domains.objs[i]); + if (virDomainIsActive(one_driver->domains.objs[i])) + active = 1; + virDomainObjUnlock(one_driver->domains.objs[i]); + } + oneDriverUnlock(one_driver); + + return active; + +} + +static int oneVersion(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned long *hvVer) +{ + *hvVer = 1; + return 0; +} + + +static int oneGetAutostart(virDomainPtr domain ATTRIBUTE_UNUSED, int *autostart) +{ + autostart=0; + return 0; +} + +static char* oneGetCapabilities(virConnectPtr conn){ + one_driver_t* privconn=conn->privateData; + char *xml; + oneDriverLock(privconn); + if ((xml = virCapabilitiesFormatXML(privconn->caps)) == NULL) + virReportOOMError(conn); + oneDriverUnlock(privconn); + return xml; +} +/* Function Tables */ +static virDriver oneDriver = { + VIR_DRV_ONE, /* the number virDrvNo */ + "one", /* the name of the driver */ + oneOpen, /* open */ + oneClose, /* close */ + NULL, /* supports_feature */ + NULL, /* type */ + oneVersion, /* version */ + NULL, /* getHostname */ + NULL, /* getMaxVcpus */ + NULL, /* nodeGetInfo */ + oneGetCapabilities, /* getCapabilities */ + oneListDomains, /* listDomains */ + oneNumDomains, /* numOfDomains */ + oneDomainCreateAndStart, /* domainCreateXML */ + oneDomainLookupByID, /* domainLookupByID */ + oneDomainLookupByUUID, /* domainLookupByUUID */ + oneDomainLookupByName, /* domainLookupByName */ + oneDomainSuspend, /* domainSuspend */ + oneDomainResume, /* domainResume */ + oneDomainShutdown, /* domainShutdown */ + NULL, /* domainReboot */ + oneDomainDestroy, /* domainDestroy */ + oneGetOSType, /* domainGetOSType */ + NULL, /* domainGetMaxMemory */ + NULL, /* domainSetMaxMemory */ + NULL, /* domainSetMemory */ + oneDomainGetInfo, /* domainGetInfo */ + NULL, /* domainSave */ + NULL, /* domainRestore */ + NULL, /* domainCoreDump */ + NULL, /* domainSetVcpus */ + NULL, /* domainPinVcpu */ + NULL, /* domainGetVcpus */ + NULL, /* domainGetMaxVcpus */ + NULL, /* domainGetSecurityLabel */ + NULL, /* nodeGetSecurityModel */ + NULL, /* domainDumpXML */ + oneListDefinedDomains, /* listDefinedDomains */ + oneNumDefinedDomains, /* numOfDefinedDomains */ + oneDomainStart, /* domainCreate */ + oneDomainDefine, /* domainDefineXML */ + oneDomainUndefine, /* domainUndefine */ + NULL, /* domainAttachDevice */ + NULL, /* domainDetachDevice */ + oneGetAutostart, /* domainGetAutostart */ + NULL, /* domainSetAutostart */ + NULL, /* domainGetSchedulerType */ + NULL, /* domainGetSchedulerParameters */ + NULL, /* domainSetSchedulerParameters */ + NULL, /* domainMigratePrepare */ + NULL, /* domainMigratePerform */ + NULL, /* domainMigrateFinish */ + NULL, /* domainBlockStats */ + NULL, /* domainInterfaceStats */ + NULL, /* domainBlockPeek */ + NULL, /* domainMemoryPeek */ + NULL, /* nodeGetCellsFreeMemory */ + NULL, /* getFreeMemory */ + NULL, /* domainEventRegister */ + NULL, /* domainEventDeregister */ + NULL, /* domainMigratePrepare2 */ + NULL, /* domainMigrateFinish2 */ + NULL, /* nodeDeviceDettach; */ + NULL, /* nodeDeviceReAttach; */ + NULL, /* nodeDeviceReset; */ +}; + +static virStateDriver oneStateDriver = { + .initialize = oneStartup, + .cleanup = oneShutdown, + .active = oneActive, +}; + + +int oneRegister(void) +{ + virRegisterDriver(&oneDriver); + virRegisterStateDriver(&oneStateDriver); + return 0; +} diff --git a/src/opennebula/one_driver.h b/src/opennebula/one_driver.h new file mode 100644 index 0000000000..c00f146b88 --- /dev/null +++ b/src/opennebula/one_driver.h @@ -0,0 +1,30 @@ +/*---------------------------------------------------------------------------*/ +/* Copyright 2002-2009, Distributed Systems Architecture Group, Universidad + * Complutense de Madrid (dsa-research.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/*---------------------------------------------------------------------------*/ + + +#ifndef ONE_DRIVER_H +#define ONE_DRIVER_H + +#include +#include + +int oneRegister(void); + +#endif /* ONE_DRIVER_H */ diff --git a/src/virterror.c b/src/virterror.c index 3af65447f0..b2735e1e5a 100644 --- a/src/virterror.c +++ b/src/virterror.c @@ -160,6 +160,9 @@ static const char *virErrorDomainName(virErrorDomain domain) { case VIR_FROM_INTERFACE: dom = "Interface "; break; + case VIR_FROM_ONE: + dom = "ONE "; + break; } return(dom); }