]> xenbits.xensource.com Git - libvirt.git/commitdiff
Add support for a non-template filesystem root. (Florian Vichot)
authorDaniel P. Berrange <berrange@redhat.com>
Tue, 24 Mar 2009 10:59:13 +0000 (10:59 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Tue, 24 Mar 2009 10:59:13 +0000 (10:59 +0000)
AUTHORS
ChangeLog
src/openvz_conf.c
src/openvz_conf.h
src/openvz_driver.c

diff --git a/AUTHORS b/AUTHORS
index 1c4f3b86683323bd00be51e45ec5bb2f2ab5b3a2..16463d88f541feaaa9eb77cfe630edada0c31318 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -66,6 +66,7 @@ Patches have also been contributed by:
   Ryota Ozaki          <ozaki.ryota@gmail.com>
   Pritesh Kothari      <Pritesh.Kothari@Sun.COM>
   Amit Shah            <amit.shah@redhat.com>
+  Florian Vichot      <florian.vichot@diateam.net>
 
   [....send patches to get your name here....]
 
index 1ee016d8039786f75a76033de3951bd80fcf6816..6f57180d065b358865df4b0dfaaba4d6006698ed 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Tue Mar 24 10:51:22 GMT 2009 Daniel P. Berrange <berrange@redhat.com>
+
+       * src/openvz_conf.c, src/openvz_conf.h, src/openvz_driver.c: Add
+       support for a non-template filesystem root. (Florian Vichot)
+
 Mon Mar 23 17:33:17 CET 2009 Daniel Veillard <veillard@redhat.com>
 
        * src/virsh.c: fix missing authentication when command are issued
index ff3d607fbd56d4384e176402c87026033a691bb0..c5f4a14587a838c1badbd59cb3741e0425361077 100644 (file)
@@ -192,7 +192,7 @@ openvzReadNetworkConf(virConnectPtr conn,
      *   IP_ADDRESS="1.1.1.1 1.1.1.2"
      *   splited IPs by space
      */
-    ret = openvzReadConfigParam(veid, "IP_ADDRESS", temp, sizeof(temp));
+    ret = openvzReadVPSConfigParam(veid, "IP_ADDRESS", temp, sizeof(temp));
     if (ret < 0) {
         openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                  _("Cound not read 'IP_ADDRESS' from config for container %d"),
@@ -224,7 +224,7 @@ openvzReadNetworkConf(virConnectPtr conn,
      *NETIF="ifname=eth10,mac=00:18:51:C1:05:EE,host_ifname=veth105.10,host_mac=00:18:51:8F:D9:F3"
      *devices splited by ';'
      */
-    ret = openvzReadConfigParam(veid, "NETIF", temp, sizeof(temp));
+    ret = openvzReadVPSConfigParam(veid, "NETIF", temp, sizeof(temp));
     if (ret < 0) {
         openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                      _("Cound not read 'NETIF' from config for container %d"),
@@ -314,15 +314,46 @@ error:
 }
 
 
+/* utility function to replace 'from' by 'to' in 'str' */
+static char*
+openvz_replace(const char* str,
+               const char* from,
+               const char* to) {
+    const char* offset = NULL;
+    const char* str_start = str;
+    int to_len = strlen(to);
+    int from_len = strlen(from);
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+    if(!from)
+        return NULL;
+
+    while((offset = strstr(str_start, from)))
+    {
+        virBufferAdd(&buf, str_start, offset-str_start);
+        virBufferAdd(&buf, to, to_len);
+        str_start = offset + from_len;
+    }
+
+     virBufferAdd(&buf, str_start, strlen(str_start));
+
+    if(virBufferError(&buf))
+      return NULL;
+
+    return virBufferContentAndReset(&buf);
+}
+
+
 static int
 openvzReadFSConf(virConnectPtr conn,
                  virDomainDefPtr def,
                  int veid) {
     int ret;
     virDomainFSDefPtr fs = NULL;
-    char temp[4096];
+    char* veid_str = NULL;
+    char temp[100];
 
-    ret = openvzReadConfigParam(veid, "OSTEMPLATE", temp, sizeof(temp));
+    ret = openvzReadVPSConfigParam(veid, "OSTEMPLATE", temp, sizeof(temp));
     if (ret < 0) {
         openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                     _("Cound not read 'OSTEMPLATE' from config for container %d"),
@@ -334,18 +365,38 @@ openvzReadFSConf(virConnectPtr conn,
 
         fs->type = VIR_DOMAIN_FS_TYPE_TEMPLATE;
         fs->src = strdup(temp);
-        fs->dst = strdup("/");
+    } else {
+        /* OSTEMPLATE was not found, VE was booted from a private dir directly */
+        ret = openvzReadVPSConfigParam(veid, "VE_PRIVATE", temp, sizeof(temp));
+        if (ret <= 0) {
+            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+                        _("Cound not read 'VE_PRIVATE' from config for container %d"),
+                        veid);
+            goto error;
+        }
 
-        if (fs->src == NULL || fs->dst == NULL)
+        if (VIR_ALLOC(fs) < 0)
             goto no_memory;
 
-        if (VIR_REALLOC_N(def->fss, def->nfss + 1) < 0)
-            goto no_memory;
-        def->fss[def->nfss++] = fs;
-        fs = NULL;
+        if(virAsprintf(&veid_str, "%d", veid) < 0)
+          goto error;
+
+        fs->type = VIR_DOMAIN_FS_TYPE_MOUNT;
+        fs->src = openvz_replace(temp, "$VEID", veid_str);
 
+        VIR_FREE(veid_str);
     }
 
+    fs->dst = strdup("/");
+
+    if (fs->src == NULL || fs->dst == NULL)
+        goto no_memory;
+
+    if (VIR_REALLOC_N(def->fss, def->nfss + 1) < 0)
+        goto no_memory;
+    def->fss[def->nfss++] = fs;
+    fs = NULL;
+
     return 0;
 no_memory:
     virReportOOMError(conn);
@@ -432,7 +483,7 @@ int openvzLoadDomains(struct openvz_driver *driver) {
         if (!(dom->def->os.init = strdup("/sbin/init")))
             goto no_memory;
 
-        ret = openvzReadConfigParam(veid, "CPUS", temp, sizeof(temp));
+        ret = openvzReadVPSConfigParam(veid, "CPUS", temp, sizeof(temp));
         if (ret < 0) {
             openvzError(NULL, VIR_ERR_INTERNAL_ERROR,
                         _("Cound not read config for container %d"),
@@ -485,26 +536,23 @@ openvzGetNodeCPUs(void)
     return nodeinfo.cpus;
 }
 
-int
-openvzWriteConfigParam(int vpsid, const char *param, const char *value)
+static int
+openvzWriteConfigParam(const char * conf_file, const char *param, const char *value)
 {
-    char conf_file[PATH_MAX];
-    char temp_file[PATH_MAX];
+    char * temp_file = NULL;
+    int fd = -1, temp_fd = -1;
     char line[PATH_MAX] ;
-    int fd, temp_fd;
 
-    if (openvzLocateConfFile(vpsid, conf_file, PATH_MAX, "conf")<0)
-        return -1;
-    if (openvzLocateConfFile(vpsid, temp_file, PATH_MAX, "tmp")<0)
+    if (virAsprintf(&temp_file, "%s.tmp", conf_file)<0)
         return -1;
 
     fd = open(conf_file, O_RDONLY);
     if (fd == -1)
-        return -1;
+        goto error;
     temp_fd = open(temp_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
     if (temp_fd == -1) {
         close(fd);
-        return -1;
+        goto error;
     }
 
     while(1) {
@@ -541,30 +589,32 @@ error:
         close(fd);
     if (temp_fd != -1)
         close(temp_fd);
-    unlink(temp_file);
+    if(temp_file)
+        unlink(temp_file);
+    VIR_FREE(temp_file);
     return -1;
 }
 
-/*
-* Read parameter from container config
-* sample: 133, "OSTEMPLATE", value, 1024
-* return: -1 - error
-*         0 - don't found
-*          1 - OK
-*/
 int
-openvzReadConfigParam(int vpsid ,const char * param, char *value, int maxlen)
+openvzWriteVPSConfigParam(int vpsid, const char *param, const char *value)
+{
+    char conf_file[PATH_MAX];
+
+    if (openvzLocateConfFile(vpsid, conf_file, PATH_MAX, "conf")<0)
+        return -1;
+
+    return openvzWriteConfigParam(conf_file, param, value);
+}
+
+static int
+openvzReadConfigParam(const char * conf_file ,const char * param, char *value, int maxlen)
 {
-    char conf_file[PATH_MAX] ;
     char line[PATH_MAX] ;
     int ret, found = 0;
     int fd ;
     char * sf, * token;
     char *saveptr = NULL;
 
-    if (openvzLocateConfFile(vpsid, conf_file, PATH_MAX, "conf")<0)
-        return -1;
-
     value[0] = 0;
 
     fd = open(conf_file, O_RDONLY);
@@ -597,6 +647,103 @@ openvzReadConfigParam(int vpsid ,const char * param, char *value, int maxlen)
     return ret ;
 }
 
+/*
+* Read parameter from container config
+* sample: 133, "OSTEMPLATE", value, 1024
+* return: -1 - error
+*         0 - don't found
+*          1 - OK
+*/
+int
+openvzReadVPSConfigParam(int vpsid ,const char * param, char *value, int maxlen)
+{
+    char conf_file[PATH_MAX] ;
+
+    if (openvzLocateConfFile(vpsid, conf_file, PATH_MAX, "conf")<0)
+        return -1;
+
+    return openvzReadConfigParam(conf_file, param, value, maxlen);
+}
+
+static int
+openvz_copyfile(char* from_path, char* to_path)
+{
+    char line[PATH_MAX];
+    int fd, copy_fd;
+    int bytes_read;
+
+    fd = open(from_path, O_RDONLY);
+    if (fd == -1)
+        return -1;
+    copy_fd = open(to_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+    if (copy_fd == -1) {
+        close(fd);
+        return -1;
+    }
+
+    while(1) {
+        if (openvz_readline(fd, line, sizeof(line)) <= 0)
+            break;
+
+        bytes_read = strlen(line);
+        if (safewrite(copy_fd, line, bytes_read) != bytes_read)
+            goto error;
+    }
+
+    if (close(fd) < 0)
+        goto error;
+    fd = -1;
+    if (close(copy_fd) < 0)
+        goto error;
+    copy_fd = -1;
+
+    return 0;
+
+error:
+    if (fd != -1)
+        close(fd);
+    if (copy_fd != -1)
+        close(copy_fd);
+    return -1;
+}
+
+/*
+* Copy the default config to the VE conf file
+* return: -1 - error
+*          0 - OK
+*/
+int
+openvzCopyDefaultConfig(int vpsid)
+{
+    char * confdir = NULL;
+    char * default_conf_file = NULL;
+    char configfile_value[PATH_MAX];
+    char conf_file[PATH_MAX];
+    int ret = -1;
+
+    if(openvzReadConfigParam(VZ_CONF_FILE, "CONFIGFILE", configfile_value, PATH_MAX) < 0)
+        goto cleanup;
+
+    confdir = openvzLocateConfDir();
+    if (confdir == NULL)
+        goto cleanup;
+
+    if (virAsprintf(&default_conf_file, "%s/ve-%s.conf-sample", confdir, configfile_value) < 0)
+        goto cleanup;
+
+    if (openvzLocateConfFile(vpsid, conf_file, PATH_MAX, "conf")<0)
+        goto cleanup;
+
+    if (openvz_copyfile(default_conf_file, conf_file)<0)
+        goto cleanup;
+
+    ret = 0;
+cleanup:
+    VIR_FREE(confdir);
+    VIR_FREE(default_conf_file);
+    return ret;
+}
+
 /* Locate config file of container
 * return -1 - error
 *         0 - OK
index 8e02056fd87fe59ffb3d08e0f8cf55dbac44a07b..00e18b4325225cf95c3f106d3756fa58b2ce749a 100644 (file)
@@ -42,6 +42,7 @@ enum { OPENVZ_WARN, OPENVZ_ERR };
 /* OpenVZ commands - Replace with wrapper scripts later? */
 #define VZLIST  "/usr/sbin/vzlist"
 #define VZCTL   "/usr/sbin/vzctl"
+#define VZ_CONF_FILE "/etc/vz/vz.conf"
 
 #define VZCTL_BRIDGE_MIN_VERSION ((3 * 1000 * 1000) + (0 * 1000) + 22 + 1)
 
@@ -56,8 +57,9 @@ struct openvz_driver {
 int openvz_readline(int fd, char *ptr, int maxlen);
 int openvzExtractVersion(virConnectPtr conn,
                          struct openvz_driver *driver);
-int openvzReadConfigParam(int vpsid ,const char * param, char *value, int maxlen);
-int openvzWriteConfigParam(int vpsid, const char *param, const char *value);
+int openvzReadVPSConfigParam(int vpsid ,const char * param, char *value, int maxlen);
+int openvzWriteVPSConfigParam(int vpsid, const char *param, const char *value);
+int openvzCopyDefaultConfig(int vpsid);
 virCapsPtr openvzCapsInit(void);
 int openvzLoadDomains(struct openvz_driver *driver);
 void openvzFreeDriver(struct openvz_driver *driver);
index d6c4362dc0fec77ec7616f2d16efc9c3b7c54994..ac2c089813a71e4afb0ae96152cff0fd8f45318d 100644 (file)
@@ -132,19 +132,9 @@ static int openvzDomainDefineCmd(virConnectPtr conn,
     ADD_ARG_LIT("create");
     ADD_ARG_LIT(vmdef->name);
 
-    if (vmdef->nfss) {
-        if (vmdef->fss[0]->type != VIR_DOMAIN_FS_TYPE_TEMPLATE) {
-            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
-                        "%s", _("only filesystem templates are supported"));
-            return -1;
-        }
-
-        if (vmdef->nfss > 1) {
-            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
-                        "%s", _("only one filesystem supported"));
-            return -1;
-        }
-
+    if (vmdef->nfss == 1 &&
+        vmdef->fss[0]->type == VIR_DOMAIN_FS_TYPE_TEMPLATE)
+    {
         ADD_ARG_LIT("--ostemplate");
         ADD_ARG_LIT(vmdef->fss[0]->src);
     }
@@ -166,6 +156,77 @@ static int openvzDomainDefineCmd(virConnectPtr conn,
 }
 
 
+static int openvzSetInitialConfig(virConnectPtr conn,
+                                  virDomainDefPtr vmdef)
+{
+    int ret = -1;
+    int vpsid;
+    char * confdir = NULL;
+    const char *prog[OPENVZ_MAX_ARG];
+    prog[0] = NULL;
+
+    if (vmdef->nfss > 1) {
+        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+                    "%s", _("only one filesystem supported"));
+        goto cleanup;
+    }
+
+    if (vmdef->nfss == 1 &&
+        vmdef->fss[0]->type != VIR_DOMAIN_FS_TYPE_TEMPLATE &&
+        vmdef->fss[0]->type != VIR_DOMAIN_FS_TYPE_MOUNT)
+    {
+        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+                    "%s", _("filesystem is not of type 'template' or 'mount'"));
+        goto cleanup;
+    }
+
+
+    if (vmdef->nfss == 1 &&
+        vmdef->fss[0]->type == VIR_DOMAIN_FS_TYPE_MOUNT)
+    {
+
+        if(virStrToLong_i(vmdef->name, NULL, 10, &vpsid) < 0) {
+            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+                        "%s", _("Could not convert domain name to VEID"));
+            goto cleanup;
+        }
+
+        if (openvzCopyDefaultConfig(vpsid) < 0) {
+            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+                        "%s", _("Could not copy default config"));
+            goto cleanup;
+        }
+
+        if (openvzWriteVPSConfigParam(vpsid, "VE_PRIVATE", vmdef->fss[0]->src) < 0) {
+            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+                        "%s", _("Could not set the source dir for the filesystem"));
+            goto cleanup;
+        }
+    }
+    else
+    {
+        if (openvzDomainDefineCmd(conn, prog, OPENVZ_MAX_ARG, vmdef) < 0) {
+            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+                        "%s", _("Error creating command for container"));
+            goto cleanup;
+        }
+
+        if (virRun(conn, prog, NULL) < 0) {
+            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+                   _("Could not exec %s"), VZCTL);
+            goto cleanup;
+        }
+    }
+
+    ret = 0;
+
+cleanup:
+  VIR_FREE(confdir);
+  cmdExecFree(prog);
+  return ret;
+}
+
+
 static virDomainPtr openvzDomainLookupByID(virConnectPtr conn,
                                            int id) {
     struct openvz_driver *driver = conn->privateData;
@@ -447,7 +508,7 @@ openvzGenerateContainerVethName(int veid)
     char    temp[1024];
 
     /* try to get line "^NETIF=..." from config */
-    if ( (ret = openvzReadConfigParam(veid, "NETIF", temp, sizeof(temp))) <= 0) {
+    if ( (ret = openvzReadVPSConfigParam(veid, "NETIF", temp, sizeof(temp))) <= 0) {
         snprintf(temp, sizeof(temp), "eth0");
     } else {
         char *saveptr;
@@ -630,7 +691,7 @@ openvzDomainSetNetworkConfig(virConnectPtr conn,
     if (driver->version < VZCTL_BRIDGE_MIN_VERSION && def->nnets) {
         param = virBufferContentAndReset(&buf);
         if (param) {
-            if (openvzWriteConfigParam(strtoI(def->name), "NETIF", param) < 0) {
+            if (openvzWriteVPSConfigParam(strtoI(def->name), "NETIF", param) < 0) {
                 VIR_FREE(param);
                 openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                             "%s", _("cannot replace NETIF config"));
@@ -656,8 +717,6 @@ openvzDomainDefineXML(virConnectPtr conn, const char *xml)
     virDomainDefPtr vmdef = NULL;
     virDomainObjPtr vm = NULL;
     virDomainPtr dom = NULL;
-    const char *prog[OPENVZ_MAX_ARG];
-    prog[0] = NULL;
 
     openvzDriverLock(driver);
     if ((vmdef = virDomainDefParseString(conn, driver->caps, xml,
@@ -680,20 +739,14 @@ openvzDomainDefineXML(virConnectPtr conn, const char *xml)
         goto cleanup;
     vmdef = NULL;
 
-    if (openvzDomainDefineCmd(conn, prog, OPENVZ_MAX_ARG, vm->def) < 0) {
+    if (openvzSetInitialConfig(conn, vm->def) < 0) {
         openvzError(conn, VIR_ERR_INTERNAL_ERROR,
-                "%s", _("Error creating command for container"));
+                "%s", _("Error creating intial configuration"));
         goto cleanup;
     }
 
     //TODO: set quota
 
-    if (virRun(conn, prog, NULL) < 0) {
-        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
-               _("Could not exec %s"), VZCTL);
-        goto cleanup;
-    }
-
     if (openvzSetDefinedUUID(strtoI(vm->def->name), vm->def->uuid) < 0) {
         openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                "%s", _("Could not set UUID"));
@@ -717,7 +770,6 @@ openvzDomainDefineXML(virConnectPtr conn, const char *xml)
 
 cleanup:
     virDomainDefFree(vmdef);
-    cmdExecFree(prog);
     if (vm)
         virDomainObjUnlock(vm);
     openvzDriverUnlock(driver);
@@ -733,8 +785,6 @@ openvzDomainCreateXML(virConnectPtr conn, const char *xml,
     virDomainObjPtr vm = NULL;
     virDomainPtr dom = NULL;
     const char *progstart[] = {VZCTL, "--quiet", "start", PROGRAM_SENTINAL, NULL};
-    const char *progcreate[OPENVZ_MAX_ARG];
-    progcreate[0] = NULL;
 
     openvzDriverLock(driver);
     if ((vmdef = virDomainDefParseString(conn, driver->caps, xml,
@@ -756,15 +806,9 @@ openvzDomainCreateXML(virConnectPtr conn, const char *xml,
         goto cleanup;
     vmdef = NULL;
 
-    if (openvzDomainDefineCmd(conn, progcreate, OPENVZ_MAX_ARG, vm->def) < 0) {
-        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
-                    "%s", _("Error creating command for container"));
-        goto cleanup;
-    }
-
-    if (virRun(conn, progcreate, NULL) < 0) {
+    if (openvzSetInitialConfig(conn, vm->def) < 0) {
         openvzError(conn, VIR_ERR_INTERNAL_ERROR,
-               _("Could not exec %s"), VZCTL);
+                "%s", _("Error creating intial configuration"));
         goto cleanup;
     }
 
@@ -803,7 +847,6 @@ openvzDomainCreateXML(virConnectPtr conn, const char *xml,
 
 cleanup:
     virDomainDefFree(vmdef);
-    cmdExecFree(progcreate);
     if (vm)
         virDomainObjUnlock(vm);
     openvzDriverUnlock(driver);
@@ -940,7 +983,7 @@ openvzDomainGetAutostart(virDomainPtr dom, int *autostart)
         goto cleanup;
     }
 
-    if (openvzReadConfigParam(strtoI(vm->def->name), "ONBOOT", value, sizeof(value)) < 0) {
+    if (openvzReadVPSConfigParam(strtoI(vm->def->name), "ONBOOT", value, sizeof(value)) < 0) {
         openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR,
                     "%s", _("Could not read container config"));
         goto cleanup;