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

[libvirt] [PATCH] Adding filesystem mount support for openVZ



Hi everyone,

This patch is to allow using the "mount" type in the "filesystem" tag for OpenVZ domains.

Example:
...
    <filesystem type='mount'>
      <source dir='/path/to/filesystem/directory/' />
      <target dir='/path/to/pivot/root/' />
    </filesystem>
...

This is my first patch to an external project, so don't spare me if I got things wrong :)

Also, I'm curious for suggestions as to how I could allow for the target not to be specified in the XML. Because in this case OpenVZ just makes a temporary pivot root in "/var/lib/vz/root/" and that is probably sufficient for most people, who might not want to have to explicitly create a pivot root somewhere, just for mounting the filesystem while it's running.

I was thinking either allow for the target tag not to be specified, or add an "auto" attribute to target. Which one sounds better ?

Thanks,
Florian
diff --git a/src/openvz_conf.c b/src/openvz_conf.c
index ff3d607..33fb259 100644
--- a/src/openvz_conf.c
+++ b/src/openvz_conf.c
@@ -314,6 +314,41 @@ error:
 }
 
 
+/* utility function to replace 'from' by 'to' in 'str' */
+static char*
+openvz_replace(const char* str,
+               const char* from,
+               int to) {
+    char tmp[4096];
+    char* offset = tmp;
+    int len = strlen(str);
+    int fromLen = strlen(from);
+    int r,i,maxcmp,left = sizeof(tmp);
+
+    if(!from)
+        return NULL;
+
+    for(i = 0; i < len && left; ++i) {
+      /* compare first caracters to limit useless full comparisons */
+        if(*from == str[i]) {
+            maxcmp = (fromLen > len-i) ? len-i : fromLen;
+            if(strncmp(from, str+i, maxcmp) == 0) {
+                r = snprintf(offset, left, "%d", to);
+                offset += r;
+                i += fromLen - 1;
+                continue;
+            }
+        }
+        *offset++ = str[i];
+        left = sizeof(tmp) - (offset-tmp);
+    }
+
+    tmp[sizeof(tmp)-left] = '\0';
+
+    return strdup(tmp);
+}
+
+
 static int
 openvzReadFSConf(virConnectPtr conn,
                  virDomainDefPtr def,
@@ -343,7 +378,42 @@ openvzReadFSConf(virConnectPtr conn,
             goto no_memory;
         def->fss[def->nfss++] = fs;
         fs = NULL;
+    } else {
+        /* OSTEMPLATE was not found, VE was booted from a private dir directly */
+        ret = openvzReadConfigParam(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 (VIR_ALLOC(fs) < 0)
+            goto no_memory;
+
+        fs->type = VIR_DOMAIN_FS_TYPE_MOUNT;
+        fs->src = openvz_replace(temp, "$VEID", veid);
+
+        if (fs->src == NULL)
+            goto no_memory;
+
+        ret = openvzReadConfigParam(veid, "VE_ROOT", temp, sizeof(temp));
+        if (ret <= 0) {
+            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+                        _("Cound not read 'VE_ROOT' from config for container %d"),
+                        veid);
+            goto error;
+        }
+
+        fs->dst = openvz_replace(temp, "$VEID", veid);
 
+        if (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;
@@ -597,6 +667,81 @@ openvzReadConfigParam(int vpsid ,const char * param, char *value, int maxlen)
     return ret ;
 }
 
+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;
+    char default_conf_file[PATH_MAX], conf_file[PATH_MAX];
+
+    confdir = openvzLocateConfDir();
+    if (confdir == NULL)
+        return -1;
+
+    if (snprintf(default_conf_file, PATH_MAX, "%s/%s",
+                 confdir, VZ_DEFAULT_CONF_FILE) >= PATH_MAX)
+    {
+        VIR_FREE(confdir);
+        return -1;
+    }
+
+    VIR_FREE(confdir);
+
+    if (openvzLocateConfFile(vpsid, conf_file, PATH_MAX, "conf")<0)
+        return -1;
+
+    if (openvz_copyfile(default_conf_file, conf_file)<0)
+        return -1;
+
+    return 0;
+}
+
 /* Locate config file of container
 * return -1 - error
 *         0 - OK
diff --git a/src/openvz_conf.h b/src/openvz_conf.h
index 8e02056..da9bfb4 100644
--- a/src/openvz_conf.h
+++ b/src/openvz_conf.h
@@ -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_DEFAULT_CONF_FILE "ve-vps.basic.conf-sample"
 
 #define VZCTL_BRIDGE_MIN_VERSION ((3 * 1000 * 1000) + (0 * 1000) + 22 + 1)
 
@@ -58,6 +59,7 @@ 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 openvzCopyDefaultConfig(int vpsid);
 virCapsPtr openvzCapsInit(void);
 int openvzLoadDomains(struct openvz_driver *driver);
 void openvzFreeDriver(struct openvz_driver *driver);
diff --git a/src/openvz_driver.c b/src/openvz_driver.c
index d6c4362..57727b2 100644
--- a/src/openvz_driver.c
+++ b/src/openvz_driver.c
@@ -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,83 @@ 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 (openvzWriteConfigParam(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;
+        }
+
+        if (openvzWriteConfigParam(vpsid, "VE_ROOT", vmdef->fss[0]->dst) < 0) {
+            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+                        "%s", _("Could not set the target 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;
@@ -656,8 +723,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 +745,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 +776,6 @@ openvzDomainDefineXML(virConnectPtr conn, const char *xml)
 
 cleanup:
     virDomainDefFree(vmdef);
-    cmdExecFree(prog);
     if (vm)
         virDomainObjUnlock(vm);
     openvzDriverUnlock(driver);
@@ -733,8 +791,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 +812,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 +853,6 @@ openvzDomainCreateXML(virConnectPtr conn, const char *xml,
 
 cleanup:
     virDomainDefFree(vmdef);
-    cmdExecFree(progcreate);
     if (vm)
         virDomainObjUnlock(vm);
     openvzDriverUnlock(driver);

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