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

Daniel P. Berrange berrange at redhat.com
Thu Mar 19 11:25:59 UTC 2009


On Fri, Mar 13, 2009 at 12:06:12PM +0100, Florian Vichot wrote:
> Hi everyone,
> 
> Here is the new patch, with the requested modifications:
> - The target tag is now set to '/', and not used to specify the pivot 
> root location.
> - Search and replace uses virBuffer and strstr()
> - Use of virAsprintf when possible, instead of stack arrays.
> - Default config file name is read from /etc/vz/vz.conf

I think this looks good now, so ACK to this patch unless Evgeniy has
further suggestions from an OpenVZ point of view. I'll commit this 
tomorrow if no one objects...

Daniel


> diff --git a/src/openvz_conf.c b/src/openvz_conf.c
> index ff3d607..c5f4a14 100644
> --- a/src/openvz_conf.c
> +++ b/src/openvz_conf.c
> @@ -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
> diff --git a/src/openvz_conf.h b/src/openvz_conf.h
> index 8e02056..00e18b4 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_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);
> diff --git a/src/openvz_driver.c b/src/openvz_driver.c
> index d6c4362..ac2c089 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,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;

> --
> Libvir-list mailing list
> Libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list


-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list