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

[Libvir] OpenVZ driver enhancements



Hi,

I'm glad to make available patches for the OpenVZ driver that provide
the following features:

* virDomainDefineXML - Defines an OpenVZ domain and does not start it.
Takes XML description of the domain as input.
* virDomainCreateLinux - Starts a domain based on the provided XML
description. There is no way to start a domain in OpenVZ without
defining it. So, it is defined anyway, as of now. :-( There may be a way
to get around this. We are looking into it. As of now, treat this as
define + start.
* virDomainUndefine - removes domain from OpenVZ management. Since
OpenVZ manages the domain's root file system, it is also lost. This
behaviour is different from Xen.

The XML Format for OpenVZ:
--------------------------

<domain type='openvz'>
	<name>108</name>
	<uuid>8dea22b31d52d8f32516782e98ab8fa0</uuid>
	<container>
		<filesystem>
			<template>fedora-core-3-i386-minimal</template>
			<quota level = 'first'>123</quota>
			<quota level = 'second' uid = '500'>534</quota>
		</filesystem>
		<network>
			<ipaddress>192.168.1.108</ipaddress>
			<hostname>fedora-minimal</hostname>
			<gateway>192.168.1.1</gateway>
			<nameserver>192.168.1.1</nameserver>
			<netmask>255.255.255.0</netmask>
		</network>
		<profile>vps.basic</profile>
	</container>
</domain>

The name is the VPS "ID". The VPS ID is not temporary in OpenVZ as in
Xen. The "<template>" tag in the "<filesystem>" section tells libvirt
which OS template cache to use to create the VPS file system. Quota is
not implemented as yet. First and second level quotas are intended to be
supported. The "<profile>" tag must be a valid profile name from which
VPS parameter are inherited. Other things, I guess are self explanatory.

Other issues:
-------------
* Moved some static declarations from the header to the .c files.
* Fixed a small bug that cause libvirtd to crash on remote client exit.

Patches are against CVS head.

Regards,

-- 
Shuveb Hussain

Unix is very user friendly. It is just a 
little choosy about who its friends are
http://www.binarykarma.com
Index: src/openvz_conf.c
===================================================================
RCS file: /data/cvs/libvirt/src/openvz_conf.c,v
retrieving revision 1.4
diff -u -r1.4 openvz_conf.c
--- src/openvz_conf.c	9 Aug 2007 20:19:12 -0000	1.4
+++ src/openvz_conf.c	23 Aug 2007 08:39:27 -0000
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2006, 2007 Binary Karma
  * Copyright (C) 2006 Shuveb Hussain
+ * Copyright (C) 2007 Anoop Joe Cyriac
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -18,7 +19,10 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
  *
- * Author: Shuveb Hussain <shuveb binarykarma com>
+ * Authors: 
+ * Shuveb Hussain <shuveb binarykarma com>
+ * Anoop Joe Cyriac <anoop binarykarma com>
+ *
  */
 
 #ifdef WITH_OPENVZ
@@ -31,6 +35,10 @@
 #include <dirent.h>
 #include <strings.h>
 #include <time.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
 
 #include <libxml/parser.h>
 #include <libxml/tree.h>
@@ -39,11 +47,21 @@
 
 #include <libvirt/virterror.h>
 
-#include "openvz_conf.h"
 #include "openvz_driver.h"
+#include "openvz_conf.h"
 #include "uuid.h"
 #include "buf.h"
 
+#include <string.h>
+
+static char *openvzLocateConfDir(void);
+static void error (virConnectPtr conn, virErrorNumber code, const char *info);
+static struct openvz_vm_def *openvzParseXML(virConnectPtr conn, xmlDocPtr xml);
+static int openvzGetVPSUUID(int vpsid, char *uuidbuf);
+static int openvzSetUUID(int vpsid);
+static struct openvz_vm *openvzLoadConfig(struct openvz_driver *driver,
+                                          const char *path,
+                                          const char *xmlStr);
 
 /* For errors internal to this library. */
 static void
@@ -72,11 +90,11 @@
 
 struct openvz_vm 
 *openvzFindVMByUUID(const struct openvz_driver *driver,
-                                   const unsigned char *uuid) {
+                   		   const unsigned char *uuid) {
     struct openvz_vm *vm = driver->vms;
 
     while (vm) {
-        if (!memcmp(vm->vmdef->uuid, uuid, VIR_UUID_BUFLEN))
+        if (!memcmp(vm->vmdef->uuid, uuid, OPENVZ_UUID_MAX))
             return vm;
         vm = vm->next;
     }
@@ -98,30 +116,179 @@
     return NULL;
 }
 
-/* Free all memory associated with a struct openvz_vm object */
-void 
-openvzFreeVMDef(struct openvz_vm_def *def) {
-    struct ovz_quota *quota = def->fs.quota;
-    struct ovz_ip *ip = def->net.ips;
-    struct ovz_ns *ns = def->net.ns;
-
-    while (quota) {
-        struct ovz_quota *prev = quota;
-        quota = quota->next;
-        free(prev);
-    }
-    while (ip) {
-        struct ovz_ip *prev = ip;
-        ip = ip->next;
-        free(prev);
-    }
-    while (ns) {
-        struct ovz_ns *prev = ns;
-        ns = ns->next;
-        free(prev);
+int
+strtoI(char *str)
+{
+    int base = 10;
+    char *endptr;
+    int val;
+
+    val = (int) strtol(str, &endptr, base);
+
+    /* Check for various possible errors */
+    if ((endptr == str)         /* "No digits were found" */
+        ||((*endptr != '\0')
+           && (*endptr !=
+               ' ')) /*"Name contain characters other than integers" */ )
+        return 0;
+    return val;
+}
+
+void
+openvzRemoveInactiveVM(struct openvz_driver *driver, struct openvz_vm *vm)
+{
+    driver->num_inactive--;
+    openvzFreeVM(driver, vm, 1);
+}
+
+/* Free all memory associated with a openvz_vm_def structure */
+void
+openvzFreeVMDef(struct openvz_vm_def *def)
+{
+    if (def) {
+        struct ovz_quota *quota = def->fs.quota;
+        struct ovz_ip *ip = def->net.ips;
+        struct ovz_ns *ns = def->net.ns;
+
+        while (quota) {
+            struct ovz_quota *prev = quota;
+
+            quota = quota->next;
+            free(prev);
+        }
+        while (ip) {
+            struct ovz_ip *prev = ip;
+
+            ip = ip->next;
+            free(prev);
+        }
+        while (ns) {
+            struct ovz_ns *prev = ns;
+
+            ns = ns->next;
+            free(prev);
+        }
+
+        free(def);
+        def = NULL;
     }
+}
+
+/* Free all memory associated with a openvz_vm structure 
+ * @checkCallee == 0 then openvzFreeDriver() is callee else some other function
+ */
+void
+openvzFreeVM(struct openvz_driver *driver, struct openvz_vm *vm,
+             int checkCallee)
+{
+    struct openvz_vm *vms;
+
+    if (!vm && !driver)
+        return;
+    vms = driver->vms;
+    if (checkCallee) {
+        if (vms == vm)
+            driver->vms = vm->next;
+        else {
+            while (vms) {
+                struct openvz_vm *prev = vms;
 
-    free(def);
+                vms = vms->next;
+                if (vms == vm) {
+                    prev->next = vms->next;
+                    break;
+                }
+            }
+        }
+    }
+    if (vms) {
+        openvzFreeVMDef(vm->vmdef);
+        free(vm);
+        vm = NULL;
+    }
+}
+
+/* Free all memory associated with a openvz_driver structure */
+void
+openvzFreeDriver(struct openvz_driver *driver)
+{
+    struct openvz_vm *next;
+
+    if (!driver)
+        return;
+    if (driver->vms)
+        for(next = driver->vms->next; driver->vms; driver->vms = next)
+            openvzFreeVM(driver, driver->vms, 0);
+    free(driver);
+    driver = NULL;
+}
+
+struct openvz_vm *
+openvzAssignVMDef(virConnectPtr conn,
+                  struct openvz_driver *driver, struct openvz_vm_def *def)
+{
+    struct openvz_vm *vm = NULL;
+
+    if (!driver || !def)
+        return NULL;
+
+    if ((vm = openvzFindVMByName(driver, def->name))) {
+        if (!openvzIsActiveVM(vm)) {
+            openvzFreeVMDef(vm->vmdef);
+            vm->vmdef = def;
+        }
+
+        return vm;
+    }
+
+    if (!(vm = calloc(1, sizeof(struct openvz_vm)))) {
+        openvzFreeVMDef(def);    
+        error(conn, VIR_ERR_NO_MEMORY, "vm");
+        return NULL;
+    }
+
+    vm->vpsid = -1;             // -1 needed for to represent inactiveness of domain before 'start'
+    vm->status = VIR_DOMAIN_SHUTOFF;
+    vm->vmdef = def;
+    vm->next = driver->vms;
+
+    driver->vms = vm;
+    driver->num_inactive++;
+
+    return vm;
+}
+
+struct openvz_vm_def 
+*openvzParseVMDef(virConnectPtr conn,
+                 const char *xmlStr, const char *displayName)
+{
+    xmlDocPtr xml;
+    struct openvz_vm_def *def = NULL;
+
+    if (!
+        (xml =
+         xmlReadDoc(BAD_CAST xmlStr,
+                    displayName ? displayName : "domain.xml", NULL,
+                    XML_PARSE_NOENT | XML_PARSE_NONET | XML_PARSE_NOERROR |
+                    XML_PARSE_NOWARNING))) {
+        error(conn, VIR_ERR_XML_ERROR, NULL);
+        return NULL;
+    }
+    if (!(xml->name = calloc(1, PATH_MAX))) {
+        openvzLog(OPENVZ_ERR,
+                  "Error in allocating memory to store xml URI");
+        xmlFreeDoc(xml);
+        return NULL;
+    }
+    if (displayName)
+        strncpy(xml->name, displayName, PATH_MAX - 1);
+    else
+        strncpy(xml->name, "domain.xml", PATH_MAX - 1);
+
+    def = openvzParseXML(conn, xml);
+    xmlFreeDoc(xml);
+
+    return def;
 }
 
 /*
@@ -136,6 +303,8 @@
     xmlXPathContextPtr ctxt = NULL;
     xmlXPathObjectPtr obj = NULL;
     struct openvz_vm_def *def;
+    struct ovz_ip *ovzIp;
+    struct ovz_ns *ovzNs;
 
     if (!(def = calloc(1, sizeof(struct openvz_vm_def)))) {
         error(conn, VIR_ERR_NO_MEMORY, "xmlXPathContext");
@@ -155,8 +324,7 @@
         goto bail_out;
     }
 
-
-    /* Find out what type of QEMU virtualization to use */
+    /* Find out what type of OPENVZ virtualization to use */
     if (!(prop = xmlGetProp(root, BAD_CAST "type"))) {
         error(conn, VIR_ERR_INTERNAL_ERROR, "missing domain type attribute");
         goto bail_out;
@@ -171,16 +339,17 @@
 
     /* Extract domain name */
     obj = xmlXPathEval(BAD_CAST "string(/domain/name[1])", ctxt);
-    if ((obj == NULL) || (obj->type != XPATH_NUMBER) ||
+    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
         (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
         error(conn, VIR_ERR_INTERNAL_ERROR,"invalid domain name");
         goto bail_out;
     }
-    if (0/* check if VPS ID is < 101 */) {
-        error(conn, VIR_ERR_INTERNAL_ERROR, "VPS ID is less than 101");
+    if (strtoI(BAD_CAST obj->stringval) < 101) {        /* rejecting VPS ID < 101 for they are reserved */
+        error(conn, VIR_ERR_INTERNAL_ERROR,
+              "VPS ID Error (must be an integer greater than 101");
         goto bail_out;
     }
-    strcpy(def->name, (const char *)obj->stringval);
+    strncpy(def->name, (const char *) obj->stringval, OPENVZ_NAME_MAX);
     xmlXPathFreeObject(obj);
 
     /* Extract domain uuid */
@@ -188,9 +357,10 @@
     if ((obj == NULL) || (obj->type != XPATH_STRING) ||
         (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
         int err;
+
         if ((err = virUUIDGenerate(def->uuid))) {
             error(conn, VIR_ERR_INTERNAL_ERROR,
-                             "Failed to generate UUID");
+		    	     "Failed to generate UUID");
             goto bail_out;
         }
     } else if (virUUIDParse((const char *)obj->stringval, def->uuid) < 0) {
@@ -200,19 +370,165 @@
     xmlXPathFreeObject(obj);
 
     /* Extract filesystem info */
-    obj = xmlXPathEval(BAD_CAST "string(/domain/filesystem/template[1])", ctxt);
+    obj =
+        xmlXPathEval(BAD_CAST
+                     "string(/domain/container/filesystem/template[1])",
+                     ctxt);
     if ((obj == NULL) || (obj->type != XPATH_STRING) ||
-        (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
+	(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
         error(conn, VIR_ERR_OS_TYPE, NULL);
         goto bail_out;
     }
-    strcpy(def->fs.tmpl, (const char *)obj->stringval);
+    strncpy(def->fs.tmpl, (const char *) obj->stringval, OPENVZ_TMPL_MAX);
     xmlXPathFreeObject(obj);
 
     /* TODO Add quota processing here */
 
     /* TODO analysis of the network devices */
 
+
+    /*          Extract network                 */
+    /*              Extract ipaddress               */
+    obj =
+        xmlXPathEval(BAD_CAST
+                     "string(/domain/container/network/ipaddress[1])",
+                     ctxt);
+    if ((obj == NULL) || (obj->type != XPATH_STRING)
+        || (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
+
+        openvzLog(OPENVZ_WARN,
+                  "No IP address in the given xml config file '%s'",
+                  xml->name);
+    }
+    if (xmlStrlen(obj->stringval) >= (OPENVZ_IP_MAX)) {
+        char errorMessage[OPENVZ_MAX_ERROR_LEN];
+
+        snprintf(errorMessage, OPENVZ_MAX_ERROR_LEN - 1, "%s",
+                 "ipaddress length too long");
+        error(conn, VIR_ERR_INTERNAL_ERROR, errorMessage);
+        goto bail_out;
+    }
+    if (!(ovzIp = calloc(1, sizeof(struct ovz_ip)))) {
+        openvzLog(OPENVZ_ERR,
+                  "Failed to Create Memory for 'ovz_ip' structure");
+        goto bail_out;
+    }
+    strncpy(ovzIp->ip, (const char *) obj->stringval, OPENVZ_IP_MAX);
+    def->net.ips = ovzIp;
+    xmlXPathFreeObject(obj);
+
+    /*              Extract netmask                 */
+    obj =
+        xmlXPathEval(BAD_CAST
+                     "string(/domain/container/network/netmask[1])", ctxt);
+    if ((obj == NULL) || (obj->type != XPATH_STRING)
+        || (obj->stringval == NULL) || (obj->stringval[0] == 0))
+        openvzLog(OPENVZ_WARN,
+                  "No Netmask address in the given xml config file '%s'",
+                  xml->name);
+    if (strlen((const char *) obj->stringval) >= (OPENVZ_IP_MAX)) {
+        char errorMessage[OPENVZ_MAX_ERROR_LEN];
+
+        snprintf(errorMessage, OPENVZ_MAX_ERROR_LEN - 1, "%s",
+                 "netmask length too long");
+        error(conn, VIR_ERR_INTERNAL_ERROR, errorMessage);
+        goto bail_out;
+    }
+    strncpy(def->net.ips->netmask, (const char *) obj->stringval,
+            OPENVZ_IP_MAX);
+    xmlXPathFreeObject(obj);
+
+    /*              Extract hostname                */
+    obj =
+        xmlXPathEval(BAD_CAST
+                     "string(/domain/container/network/hostname[1])",
+                     ctxt);
+    if ((obj == NULL) || (obj->type != XPATH_STRING)
+        || (obj->stringval == NULL) || (obj->stringval[0] == 0))
+        openvzLog(OPENVZ_WARN,
+                  "No hostname in the given xml config file '%s'",
+                  xml->name);
+    if (strlen((const char *) obj->stringval) >= (OPENVZ_HOSTNAME_MAX - 1)) {
+        char errorMessage[OPENVZ_MAX_ERROR_LEN];
+
+        snprintf(errorMessage, OPENVZ_MAX_ERROR_LEN - 1, "%s",
+                 "hostname length too long");
+        error(conn, VIR_ERR_INTERNAL_ERROR, errorMessage);
+        goto bail_out;
+    }
+    strncpy(def->net.hostname, (const char *) obj->stringval,
+            OPENVZ_HOSTNAME_MAX - 1);
+    xmlXPathFreeObject(obj);
+
+    /*              Extract gateway         */
+    obj =
+        xmlXPathEval(BAD_CAST
+                     "string(/domain/container/network/gateway[1])", ctxt);
+    if ((obj == NULL) || (obj->type != XPATH_STRING)
+        || (obj->stringval == NULL) || (obj->stringval[0] == 0))
+        openvzLog(OPENVZ_WARN,
+                  "No Gateway address in the given xml config file '%s'",
+                  xml->name);
+    if (strlen((const char *) obj->stringval) >= (OPENVZ_IP_MAX)) {
+        char errorMessage[OPENVZ_MAX_ERROR_LEN];
+
+        snprintf(errorMessage, OPENVZ_MAX_ERROR_LEN - 1, "%s",
+                 "gateway length too long");
+        error(conn, VIR_ERR_INTERNAL_ERROR, errorMessage);
+        goto bail_out;
+    }
+    strncpy(def->net.def_gw, (const char *) obj->stringval, OPENVZ_IP_MAX);
+    xmlXPathFreeObject(obj);
+
+    /*              Extract nameserver      */
+    obj =
+        xmlXPathEval(BAD_CAST
+                     "string(/domain/container/network/nameserver[1])",
+                     ctxt);
+    if ((obj == NULL) || (obj->type != XPATH_STRING)
+        || (obj->stringval == NULL) || (obj->stringval[0] == 0))
+        openvzLog(OPENVZ_WARN,
+                  "No Nameserver address inthe given xml config file '%s'",
+                  xml->name);
+    if (strlen((const char *) obj->stringval) >= (OPENVZ_IP_MAX)) {
+        char errorMessage[OPENVZ_MAX_ERROR_LEN];
+
+        snprintf(errorMessage, OPENVZ_MAX_ERROR_LEN - 1, "%s",
+                 "nameserver length too long");
+        error(conn, VIR_ERR_INTERNAL_ERROR, errorMessage);
+        goto bail_out;
+    }
+    if (!(ovzNs = calloc(1, sizeof(struct ovz_ns)))) {
+        openvzLog(OPENVZ_ERR,
+                  "Failed to Create Memory for 'ovz_ns' structure");
+        goto bail_out;
+    }
+    strncpy(ovzNs->ip, (const char *) obj->stringval, OPENVZ_IP_MAX);
+    def->net.ns = ovzNs;
+    xmlXPathFreeObject(obj);
+
+    /*          Extract profile         */
+    obj =
+        xmlXPathEval(BAD_CAST "string(/domain/container/profile[1])",
+                     ctxt);
+    if ((obj == NULL) || (obj->type != XPATH_STRING)
+        || (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
+        error(conn, VIR_ERR_INTERNAL_ERROR, NULL);
+        goto bail_out;
+    }
+    if (strlen((const char *) obj->stringval) >= (OPENVZ_PROFILE_MAX - 1)) {
+        char errorMessage[OPENVZ_MAX_ERROR_LEN];
+
+        snprintf(errorMessage, OPENVZ_MAX_ERROR_LEN - 1, "%s",
+                 "profile length too long");
+        error(conn, VIR_ERR_INTERNAL_ERROR, errorMessage);
+        goto bail_out;
+    }
+    strncpy(def->profile, (const char *) obj->stringval,
+            OPENVZ_PROFILE_MAX - 1);
+    xmlXPathFreeObject(obj);
+
+
     xmlXPathFreeContext(ctxt);
 
     return def;
@@ -225,28 +541,8 @@
     if (ctxt)
         xmlXPathFreeContext(ctxt);
     openvzFreeVMDef(def);
-    return NULL;
-}
 
-struct openvz_vm_def *
-openvzParseVMDef(virConnectPtr conn,
-                const char *xmlStr,
-                const char *displayName) {
-    xmlDocPtr xml;
-    struct openvz_vm_def *def = NULL;
-
-    if (!(xml = xmlReadDoc(BAD_CAST xmlStr, displayName ? displayName : "domain.xml", NULL,
-                           XML_PARSE_NOENT | XML_PARSE_NONET |
-                           XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
-        error(conn, VIR_ERR_XML_ERROR, NULL);
-        return NULL;
-    }
-
-    def = openvzParseXML(conn, xml);
-
-    xmlFreeDoc(xml);
-
-    return def;
+    return NULL;
 }
 
 struct openvz_vm *
@@ -264,19 +560,19 @@
     driver = conn->privateData;
     driver->num_active = 0;
     driver->num_inactive = 0;
-    
+
     if((fp = popen(VZLIST " -a -ovpsid,status -H 2>/dev/null", "r")) == NULL) {
         error(conn, VIR_ERR_INTERNAL_ERROR, "popen failed");
         return NULL;
     }
-    pnext = &vm; 
-    while(!feof(fp)) { 
-        *pnext = malloc(sizeof(struct openvz_vm));
-        if(!*pnext) {
+    pnext = &vm;
+    while(!feof(fp)) {
+        *pnext = calloc(1, sizeof(struct openvz_vm));
+        if (!*pnext) {
             error(conn, VIR_ERR_INTERNAL_ERROR, "malloc failed");
             return NULL;
         }
-        
+
         if(!vm)
             vm = *pnext;
 
@@ -286,19 +582,19 @@
             driver->num_active ++;
             (*pnext)->vpsid = veid;
         }
-        else {
+       	else {
             (*pnext)->status = VIR_DOMAIN_SHUTOFF;
             driver->num_inactive ++;
             (*pnext)->vpsid = -1;    /* inactive domains don't have their ID set in libvirt,
                                         thought this doesn't make sense for OpenVZ */
         }
 
-        vmdef = malloc(sizeof(struct openvz_vm_def));
+        vmdef = calloc(1, sizeof(struct openvz_vm_def));
         if(!vmdef) {
             error(conn, VIR_ERR_INTERNAL_ERROR, "malloc failed");
             return NULL;
         }
-        
+
         snprintf(vmdef->name, OPENVZ_NAME_MAX,  "%i", veid);
         openvzGetVPSUUID(veid, uuidstr);
         ret = virUUIDParse(uuidstr, vmdef->uuid);
@@ -400,8 +696,8 @@
 openvzSetUUID(int vpsid)
 {
     char conf_file[PATH_MAX];
-    char uuidstr[VIR_UUID_STRING_BUFLEN];
-    unsigned char uuid[VIR_UUID_BUFLEN];
+    char uuid[VIR_UUID_STRING_BUFLEN];
+    unsigned char new_uuid[VIR_UUID_BUFLEN];
     char *conf_dir;
     int fd, ret, i;
 
@@ -418,8 +714,10 @@
         return -1;
 
     if(uuid[0] == (int)NULL) {
-        virUUIDGenerate(uuid);
-        virUUIDFormat(uuid, uuidstr);
+        virUUIDGenerate(new_uuid);
+        bzero(uuid, VIR_UUID_STRING_BUFLEN);
+        for(i = 0; i < VIR_UUID_BUFLEN; i++)
+            sprintf(uuid + (i * 2), "%02x", (unsigned char) new_uuid[i]);
 
         lseek(fd, 0, SEEK_END);
         write(fd, "\n#UUID: ", 8);
@@ -467,4 +765,3 @@
 }
 
 #endif
-
Index: src/openvz_conf.h
===================================================================
RCS file: /data/cvs/libvirt/src/openvz_conf.h,v
retrieving revision 1.3
diff -u -r1.3 openvz_conf.h
--- src/openvz_conf.h	9 Aug 2007 20:19:12 -0000	1.3
+++ src/openvz_conf.h	23 Aug 2007 08:39:18 -0000
@@ -1,8 +1,10 @@
+
 /*
- * openvz_config.h: config information for OpenVZ VPSs
+ * openvz_conf.c: config functions for managing OpenVZ VEs
  *
  * Copyright (C) 2006, 2007 Binary Karma.
  * Copyright (C) 2006 Shuveb Hussain
+ * Copyright (C) 2007 Anoop Joe Cyriac
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -18,7 +20,10 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
  *
- * Author: Shuveb Hussain <shuveb binarykarma com>
+ * Authors: 
+ * Shuveb Hussain <shuveb binarykarma com>
+ * Anoop Joe Cyriac <anoop binarykarma com>
+ *
  */
 
 #ifndef OPENVZ_CONF_H
@@ -26,12 +31,19 @@
 
 #include "openvz_driver.h"
 
+enum { OPENVZ_WARN, OPENVZ_ERR };
+
 #define OPENVZ_NAME_MAX 8
 #define OPENVZ_TMPL_MAX 256
 #define OPENVZ_UNAME_MAX    32
 #define OPENVZ_IP_MAX   16
 #define OPENVZ_HOSTNAME_MAX 256
 #define OPENVZ_PROFILE_MAX  256
+#define OPENVZ_UUID_MAX		 16
+#define OPENVZ_MAX_ERROR_LEN	 1024
+#define OPENVZ_MAX_XML_LEN	 4096
+#define OPENVZ_MAX_QUOTA	 8
+#define OPENVZ_MAX_XPathEval_LEN 256
 
 enum openvz_quota{
     VM_LEVEL = 0,
@@ -73,7 +85,7 @@
 
 struct openvz_vm_def {
     char name[OPENVZ_NAME_MAX];
-    unsigned char uuid[VIR_UUID_BUFLEN];
+    unsigned char uuid[OPENVZ_UUID_MAX];
     char profile[OPENVZ_PROFILE_MAX];
     struct openvz_fs_def fs;
     struct openvz_net_def net;
@@ -93,21 +105,31 @@
     struct openvz_vm *next;
 };
 
-static char *openvzLocateConfDir(void);
+static inline int
+openvzIsActiveVM(struct openvz_vm *vm)
+{
+    return vm->vpsid != -1;
+}
+
 int openvz_readline(int fd, char *ptr, int maxlen);
-static void error (virConnectPtr conn, virErrorNumber code, const char *info);
 struct openvz_vm *openvzFindVMByID(const struct openvz_driver *driver, int id); 
 struct openvz_vm *openvzFindVMByUUID(const struct openvz_driver *driver, 
                                             const unsigned char *uuid);
 struct openvz_vm *openvzFindVMByName(const struct openvz_driver *driver,
                                    const char *name);
-void openvzFreeVMDef(struct openvz_vm_def *def);
-static struct openvz_vm_def *openvzParseXML(virConnectPtr conn, xmlDocPtr xml);
 struct openvz_vm_def *openvzParseVMDef(virConnectPtr conn, const char *xmlStr,
                                             const char *displayName);
+struct openvz_vm *openvzAssignVMDef(virConnectPtr conn,
+                                    struct openvz_driver *driver,
+                                    struct openvz_vm_def *def);
 struct openvz_vm *openvzGetVPSInfo(virConnectPtr conn);
 void openvzGenerateUUID(unsigned char *uuid);
-static int openvzGetVPSUUID(int vpsid, char *uuidbuf);
-static int openvzSetUUID(int vpsid);
 int openvzAssignUUIDs(void);
+void openvzRemoveInactiveVM(struct openvz_driver *driver,
+                            struct openvz_vm *vm);
+void openvzFreeDriver(struct openvz_driver *driver);
+void openvzFreeVM(struct openvz_driver *driver, struct openvz_vm *vm,
+                  int checkCallee);
+void openvzFreeVMDef(struct openvz_vm_def *def);
+int strtoI(char *str);
 #endif /* OPENVZ_CONF_H */
Index: src/openvz_driver.c
===================================================================
RCS file: /data/cvs/libvirt/src/openvz_driver.c,v
retrieving revision 1.4
diff -u -r1.4 openvz_driver.c
--- src/openvz_driver.c	14 Aug 2007 01:23:59 -0000	1.4
+++ src/openvz_driver.c	23 Aug 2007 08:39:56 -0000
@@ -1,8 +1,10 @@
+
 /*
- * openvz_driver.c: core driver methods for managing OpenVZ VEs
+ * openvz_conf.c: config functions for managing OpenVZ VEs
  *
  * Copyright (C) 2006, 2007 Binary Karma
  * Copyright (C) 2006 Shuveb Hussain
+ * Copyright (C) 2007 Anoop Joe Cyriac
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -18,7 +20,10 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
  *
- * Author: Shuveb Hussain <shuveb binarykarma com>
+ * Authors: 
+ * Shuveb Hussain <shuveb binarykarma com>
+ * Anoop Joe Cyriac <anoop binarykarma com>
+ *
  */
 
 #ifdef WITH_OPENVZ
@@ -50,16 +55,13 @@
 
 #include <libvirt/virterror.h>
 
+#include "openvz_driver.h"
 #include "event.h"
 #include "buf.h"
 #include "util.h"
-#include "openvz_driver.h"
 #include "openvz_conf.h"
 #include "nodeinfo.h"
 
-
-#define openvzLog(level, msg...) fprintf(stderr, msg)
-
 static virDomainPtr openvzDomainLookupByID(virConnectPtr conn, int id);
 static char *openvzGetOSType(virDomainPtr dom);
 static int openvzGetNodeInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo);
@@ -84,6 +86,14 @@
 static int openvzCloseNetwork(virConnectPtr conn);
 static virDrvOpenStatus openvzOpenNetwork(virConnectPtr conn, const char *name ATTRIBUTE_UNUSED,
                                          int flags ATTRIBUTE_UNUSED);
+static virDomainPtr openvzDomainDefineXML(virConnectPtr conn,
+                                          const char *xml);
+static virDomainPtr openvzDomainCreateLinux(virConnectPtr conn,
+                                            const char *xml,
+                                            unsigned int flags
+                                            ATTRIBUTE_UNUSED);
+static int openvzDomainUndefine(virDomainPtr dom);
+
 struct openvz_driver ovz_driver;
 
 /* For errors internal to this library. */
@@ -122,7 +132,7 @@
 static char *openvzGetOSType(virDomainPtr dom)
 {
     /* OpenVZ runs on Linux and runs only Linux */
-    return strdup("Linux");
+    return strdup("linux");
 }
 
 
@@ -133,7 +143,7 @@
     virDomainPtr dom;
 
     if (!vm) {
-        error(conn, VIR_ERR_INTERNAL_ERROR, "no domain with matching uuid");
+        error(dom->conn, VIR_ERR_INVALID_DOMAIN, "no domain with matching uuid");
         return NULL;
     }
 
@@ -172,8 +182,9 @@
                        virDomainInfoPtr info) {
     struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData;
     struct openvz_vm *vm = openvzFindVMByUUID(driver, dom->uuid);
+
     if (!vm) {
-        error(dom->conn, VIR_ERR_INVALID_DOMAIN, "no domain with matching uuid");
+       error(dom->conn, VIR_ERR_INVALID_DOMAIN, "no domain with matching uuid");
         return -1;
     }
 
@@ -197,7 +208,7 @@
         error(dom->conn, VIR_ERR_INVALID_DOMAIN, "no domain with matching id");
         return -1;
     }
-    
+
     if (vm->status != VIR_DOMAIN_RUNNING) {
         error(dom->conn, VIR_ERR_OPERATION_DENIED, "domain is not in running state");
         return -1;
@@ -213,7 +224,7 @@
     vm->status = VIR_DOMAIN_SHUTOFF;
     ovz_driver.num_inactive ++;
     ovz_driver.num_active --;
-    
+
     return ret;
 }
 
@@ -227,7 +238,7 @@
         error(dom->conn, VIR_ERR_INVALID_DOMAIN, "no domain with matching id");
         return -1;
     }
-    
+
     if (vm->status != VIR_DOMAIN_RUNNING) {
         error(dom->conn, VIR_ERR_OPERATION_DENIED, "domain is not in running state");
         return -1;
@@ -239,22 +250,156 @@
         error(dom->conn, VIR_ERR_OPERATION_FAILED, "could not reboot domain");
         return -1;
     }
-    
+
     return ret;
 }
 
-static int openvzDomainCreate(virDomainPtr dom) {
+static virDomainPtr
+openvzDomainDefineXML(virConnectPtr conn, const char *xml)
+{
+    struct openvz_driver *driver =
+        (struct openvz_driver *) conn->privateData;
+    struct openvz_vm_def *vmdef = NULL;
+    struct openvz_vm *vm = NULL;
+    virDomainPtr dom;
+    char cmdbuf[1060], cmdOption[1024];
+    int ret;
+
+    if (!(vmdef = openvzParseVMDef(conn, xml, NULL)))
+        return NULL;
+
+    vm = openvzFindVMByID(driver, strtoI(vmdef->name));
+    if (vm) {
+        openvzLog(OPENVZ_ERR,
+                  "Already an OPENVZ VM defined with the id '%d'",
+                  strtoI(vmdef->name));
+        return NULL;
+    }
+    if (!(vm = openvzAssignVMDef(conn, driver, vmdef))) {
+        openvzFreeVMDef(vmdef);
+        openvzLog(OPENVZ_ERR, "Error creating OPENVZ VM");
+        return NULL;
+    }
+
+    snprintf(cmdbuf, 1060, VZCTL " create %s", vmdef->name);
+    if ((vmdef->fs.tmpl && *(vmdef->fs.tmpl))) {
+        snprintf(cmdOption, 1024, " --ostemplate %s", vmdef->fs.tmpl);
+        strcat(cmdbuf, cmdOption);
+    }
+    if ((vmdef->profile && *(vmdef->profile))) {
+        snprintf(cmdOption, 1024, " --config %s", vmdef->profile);
+        strcat(cmdbuf, cmdOption);
+    }
+    if ((vmdef->net.ips->ip && *(vmdef->net.ips->ip))) {
+        snprintf(cmdOption, 1024, " --ipadd %s", vmdef->net.ips->ip);
+        strcat(cmdbuf, cmdOption);
+    }
+    if ((vmdef->net.hostname && *(vmdef->net.hostname))) {
+        snprintf(cmdOption, 1024, " --hostname %s", vmdef->net.hostname);
+        strcat(cmdbuf, cmdOption);
+    }
+
+    strcat(cmdbuf, " >/dev/null 2>&1");
+    ret = system(cmdbuf);
+
+    if (WEXITSTATUS(ret)) {
+        error(conn, VIR_ERR_OPERATION_FAILED, "could not start domain");
+        return -1;
+    }
+
+    dom = virGetDomain(conn, vm->vmdef->name, vm->vmdef->uuid);
+    if (dom)
+        dom->id = vm->vpsid;
+    return dom;
+}
+
+static virDomainPtr
+openvzDomainCreateLinux(virConnectPtr conn, const char *xml,
+                        unsigned int flags ATTRIBUTE_UNUSED)
+{
+    struct openvz_vm_def *vmdef = NULL;
+    struct openvz_vm *vm = NULL;
+    virDomainPtr dom;
+    struct openvz_driver *driver =
+        (struct openvz_driver *) conn->privateData;
+    char cmdbuf[1060], cmdOption[1024];
+    int ret;
+
+    if (!(vmdef = openvzParseVMDef(conn, xml, NULL)))
+        return NULL;
+
+    vm = openvzFindVMByID(driver, strtoI(vmdef->name));
+    if (vm) {
+        openvzLog(OPENVZ_ERR,
+                  "Already an OPENVZ VM defined with the id '%d'",
+                  strtoI(vmdef->name));
+        return NULL;
+    }
+    if (!(vm = openvzAssignVMDef(conn, driver, vmdef))) {
+        openvzFreeVMDef(vmdef);
+        openvzLog(OPENVZ_ERR, "Error creating OPENVZ VM");
+        return NULL;
+    }
+
+    snprintf(cmdbuf, 1060, VZCTL " create %s", vmdef->name);
+    if ((vmdef->fs.tmpl && *(vmdef->fs.tmpl))) {
+        snprintf(cmdOption, 1024, " --ostemplate %s", vmdef->fs.tmpl);
+        strcat(cmdbuf, cmdOption);
+    }
+    if ((vmdef->profile && *(vmdef->profile))) {
+        snprintf(cmdOption, 1024, " --config %s", vmdef->profile);
+        strcat(cmdbuf, cmdOption);
+    }
+    if ((vmdef->net.ips->ip && *(vmdef->net.ips->ip))) {
+        snprintf(cmdOption, 1024, " --ipadd %s", vmdef->net.ips->ip);
+        strcat(cmdbuf, cmdOption);
+    }
+    if ((vmdef->net.hostname && *(vmdef->net.hostname))) {
+        snprintf(cmdOption, 1024, " --hostname %s", vmdef->net.hostname);
+        strcat(cmdbuf, cmdOption);
+    }
+
+    strcat(cmdbuf, " >/dev/null 2>&1");
+    ret = system(cmdbuf);
+
+    if (WEXITSTATUS(ret)) {
+        error(conn, VIR_ERR_OPERATION_FAILED, "could not define domain");
+        return NULL;
+    }
+
+    snprintf(cmdbuf, 1024, VZCTL " start %s >/dev/null 2>&1", vmdef->name);
+    ret = system(cmdbuf);
+    if (WEXITSTATUS(ret)) {
+        error(dom->conn, VIR_ERR_OPERATION_FAILED,
+              "could not start domain");
+        return NULL;
+    }
+    sscanf(vmdef->name, "%d", &vm->vpsid);
+    vm->status = VIR_DOMAIN_RUNNING;
+    ovz_driver.num_inactive--;
+    ovz_driver.num_active++;
+
+    dom = virGetDomain(conn, vm->vmdef->name, vm->vmdef->uuid);
+    if (dom)
+        dom->id = vm->vpsid;
+    return dom;
+
+}
+
+static int
+openvzDomainCreate(virDomainPtr dom)
+{
     char cmdbuf[1024];
     int ret;
     struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData;
-    struct openvz_vm *vm = openvzFindVMByID(driver, dom->id);
+    struct openvz_vm *vm = openvzFindVMByName(driver, dom->name);
     struct openvz_vm_def *vmdef;
 
     if (!vm) {
         error(dom->conn, VIR_ERR_INVALID_DOMAIN, "no domain with matching id");
         return -1;
     }
-    
+
     if (vm->status != VIR_DOMAIN_SHUTOFF) {
         error(dom->conn, VIR_ERR_OPERATION_DENIED, "domain is not in shutoff state");
         return -1;
@@ -275,6 +420,38 @@
     return ret;
 }
 
+static int
+openvzDomainUndefine(virDomainPtr dom)
+{
+    char cmdbuf[1024];
+    int ret;
+    struct openvz_driver *driver =
+        (struct openvz_driver *) dom->conn->privateData;
+    struct openvz_vm *vm = openvzFindVMByUUID(driver, dom->uuid);
+
+    if (!vm) {
+        error(dom->conn, VIR_ERR_INVALID_DOMAIN,
+              "no domain with matching uuid");
+        return -1;
+    }
+
+    if (openvzIsActiveVM(vm)) {
+        error(dom->conn, VIR_ERR_INTERNAL_ERROR,
+              "cannot delete active domain");
+        return -1;
+    }
+    snprintf(cmdbuf, 1024, VZCTL " destroy %s >/dev/null 2>&1",
+             vm->vmdef->name);
+    ret = system(cmdbuf);
+    if (WEXITSTATUS(ret)) {
+        error(dom->conn, VIR_ERR_OPERATION_FAILED,
+              "could not undefine domain");
+        return -1;
+    }
+    openvzRemoveInactiveVM(driver, vm);
+    return ret;
+}
+
 static virDrvOpenStatus openvzOpen(virConnectPtr conn,
                            const char *name,
                            int flags ATTRIBUTE_UNUSED) {
@@ -306,7 +483,6 @@
     
     struct openvz_driver *driver = (struct openvz_driver *)conn->privateData;
     struct openvz_vm *vm = driver->vms;
-    
 
     while(vm) {
         openvzFreeVMDef(vm->vmdef);
@@ -315,10 +491,11 @@
     vm = driver->vms;
     while (vm) {
         struct openvz_vm *prev = vm;
+
         vm = vm->next;
         free(prev);
     }
-    
+
     conn->privateData = NULL;
 
     return 0;
@@ -328,13 +505,11 @@
     return strdup("OpenVZ");
 }
 
-
 static int openvzGetNodeInfo(virConnectPtr conn,
                              virNodeInfoPtr nodeinfo) {
     return virNodeInfoPopulate(conn, nodeinfo);
 }
 
-
 static int openvzListDomains(virConnectPtr conn, int *ids, int nids) {
     int got = 0;
     int veid, pid, outfd, errfd;
@@ -370,7 +545,7 @@
     int veid, pid, outfd, errfd, ret;
     char vpsname[OPENVZ_NAME_MAX];
     char buf[32];
-    const char *cmd[] = {VZLIST, "-ovpsid", "-H", NULL};
+    const char *cmd[] = {VZLIST, "-ovpsid", "-H", "-S", NULL};
 
     /* the -S options lists only stopped domains */
     ret = virExec(conn, (char **)cmd, &pid, -1, &outfd, &errfd);
@@ -391,14 +566,13 @@
     return got;
 }
 
-
 static int openvzNumDefinedDomains(virConnectPtr conn) {
     return ovz_driver.num_inactive; 
 }
 
 static int openvzStartup(void) {
     openvzAssignUUIDs();
-    
+
     return 0;
 }
 
@@ -427,13 +601,13 @@
     return VIR_DRV_OPEN_SUCCESS;
 }
 
-
 static virDriver openvzDriver = {
     VIR_DRV_OPENVZ,
     "OPENVZ",
     LIBVIR_VERSION_NUMBER,
     openvzOpen, /* open */
     openvzClose, /* close */
+    NULL, /* supports_feature */
     openvzGetType, /* type */
     NULL, /* version */
     NULL, /* hostname */
@@ -443,7 +617,7 @@
     NULL, /* getCapabilities */
     openvzListDomains, /* listDomains */
     openvzNumDomains, /* numOfDomains */
-    NULL, /* domainCreateLinux */
+    openvzDomainCreateLinux, /* domainCreateLinux */
     openvzDomainLookupByID, /* domainLookupByID */
     openvzDomainLookupByUUID, /* domainLookupByUUID */
     openvzDomainLookupByName, /* domainLookupByName */
@@ -468,8 +642,8 @@
     openvzListDefinedDomains, /* listDomains */
     openvzNumDefinedDomains, /* numOfDomains */
     openvzDomainCreate, /* domainCreate */
-    NULL, /* domainDefineXML */
-    NULL, /* domainUndefine */
+    openvzDomainDefineXML, /* domainDefineXML */
+    openvzDomainUndefine, /* domainUndefine */
     NULL, /* domainAttachDevice */
     NULL, /* domainDetachDevice */
     NULL, /* domainGetAutostart */
@@ -480,6 +654,7 @@
 };
 
 static virNetworkDriver openvzNetworkDriver = {
+    NULL, /* name */	
     openvzOpenNetwork, /* open */
     openvzCloseNetwork, /* close */
     NULL, /* numOfNetworks */
Index: src/openvz_driver.h
===================================================================
RCS file: /data/cvs/libvirt/src/openvz_driver.h,v
retrieving revision 1.1
diff -u -r1.1 openvz_driver.h
--- src/openvz_driver.h	17 Jul 2007 13:27:26 -0000	1.1
+++ src/openvz_driver.h	23 Aug 2007 08:39:47 -0000
@@ -1,8 +1,10 @@
+
 /*
- * openvz_driver.h: core driver methods for managing OpenVZ VPSs
+ * openvz_conf.c: config functions for managing OpenVZ VEs
  *
- * Copyright (C) 2006, 2007 Binary Karma.
+ * Copyright (C) 2006, 2007 Binary Karma
  * Copyright (C) 2006 Shuveb Hussain
+ * Copyright (C) 2007 Anoop Joe Cyriac
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -18,7 +20,10 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
  *
- * Author: Shuveb Hussain <shuveb binarykarma com>
+ * Authors: 
+ * Shuveb Hussain <shuveb binarykarma com>
+ * Anoop Joe Cyriac <anoop binarykarma com>
+ *
  */
 
 
@@ -39,6 +44,14 @@
 
 int openvzRegister(void);
 
+#define openvzLog(level, msg...) { if(level == OPENVZ_WARN) \
+					fprintf(stderr, "\nWARNING: ");\
+				else \
+					fprintf(stderr, "\nERROR: ");\
+				fprintf(stderr, "\n\t");\
+				fprintf(stderr, msg);\
+				fprintf(stderr, "\n"); }
+
 #endif
 
 

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