Tmpfs default usage is computed based on the host physical memory. To test this more easily, the value is computed outside the parse method. --- src/lxc/lxc_container.c | 2 +- src/lxc/lxc_container.h | 2 + src/lxc/lxc_native.c | 295 ++++++++++++++++++++++++++- tests/lxcconf2xmldata/lxcconf2xml-simple.xml | 9 + 4 files changed, 302 insertions(+), 6 deletions(-) diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index c6bdc8c..f08dbc2 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -744,7 +744,7 @@ static const virLXCBasicMountInfo lxcBasicMounts[] = { }; -static bool lxcIsBasicMountLocation(const char *path) +bool lxcIsBasicMountLocation(const char *path) { size_t i; diff --git a/src/lxc/lxc_container.h b/src/lxc/lxc_container.h index e74a7d7..67292ab 100644 --- a/src/lxc/lxc_container.h +++ b/src/lxc/lxc_container.h @@ -71,4 +71,6 @@ virArch lxcContainerGetAlt32bitArch(virArch arch); int lxcContainerChown(virDomainDefPtr def, const char *path); +bool lxcIsBasicMountLocation(const char *path); + #endif /* LXC_CONTAINER_H */ diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c index 2cd9143..9e2e870 100644 --- a/src/lxc/lxc_native.c +++ b/src/lxc/lxc_native.c @@ -21,11 +21,14 @@ */ #include <config.h> +#include <stdio.h> #include <sys/stat.h> #include "internal.h" +#include "lxc_container.h" #include "lxc_native.h" #include "util/viralloc.h" +#include "util/virfile.h" #include "util/virlog.h" #include "util/virstring.h" @@ -206,7 +209,11 @@ lxcParseProperties(const char *properties) } static virDomainFSDefPtr -lxcCreateFSDef(int type, char *src, char* dst) +lxcCreateFSDef(int type, + char *src, + char* dst, + bool readonly, + unsigned long long usage) { virDomainFSDefPtr def; @@ -217,16 +224,181 @@ lxcCreateFSDef(int type, char *src, char* dst) def->accessmode = VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH; def->src = src; def->dst = dst; + def->readonly = readonly; + def->usage = usage; return def; } +typedef struct _lxcFstab lxcFstab; +typedef lxcFstab *lxcFstabPtr; +struct _lxcFstab { + lxcFstabPtr next; + char *src; + char *dst; + char *type; + char *options; +}; + +static void +lxcFstabFree(lxcFstabPtr fstab) +{ + while (fstab) { + lxcFstabPtr next = NULL; + next = fstab->next; + + VIR_FREE(fstab->src); + VIR_FREE(fstab->dst); + VIR_FREE(fstab->type); + VIR_FREE(fstab->options); + VIR_FREE(fstab); + + fstab = next; + } +} + +static char ** lxcStringSplit(const char *string) +{ + char *tmp; + size_t i; + size_t ntokens = 0; + char **parts; + char **result = NULL; + + if (VIR_STRDUP(tmp, string) < 0) + return NULL; + + /* Replace potential \t by a space */ + for (i = 0; tmp[i]; i++) { + if (tmp[i] == '\t') + tmp[i] = ' '; + } + + parts = virStringSplit(tmp, " ", 0); + for (i = 0; parts[i]; i++) { + if (STREQ(parts[i], "")) + continue; + + if (VIR_EXPAND_N(result, ntokens, 1) < 0) + goto error; + + if (VIR_STRDUP(result[ntokens-1], parts[i]) < 0) + goto error; + } + + /* Append NULL element */ + if (VIR_EXPAND_N(result, ntokens, 1) < 0) + goto error; + + VIR_FREE(tmp); + virStringFreeList(parts); + return result; + +error: + VIR_FREE(tmp); + virStringFreeList(parts); + virStringFreeList(result); + return NULL; +} + +static lxcFstabPtr +lxcParseFstabLine(char *fstabLine) +{ + lxcFstabPtr fstab = NULL; + char **parts; + + if (VIR_ALLOC(fstab) < 0) + return NULL; + + parts = lxcStringSplit(fstabLine); + + if (!parts[0] || !parts[1] || !parts[2] || !parts[3]) + goto error; + + if (VIR_STRDUP(fstab->src, parts[0]) < 0 || + VIR_STRDUP(fstab->dst, parts[1]) < 0 || + VIR_STRDUP(fstab->type, parts[2]) < 0 || + VIR_STRDUP(fstab->options, parts[3]) < 0) + goto error; + + virStringFreeList(parts); + + return fstab; + +error: + lxcFstabFree(fstab); + virStringFreeList(parts); + return NULL; +} + +static lxcFstabPtr +lxcParseFstabString(const char *fstabString) +{ + lxcFstabPtr fstab = NULL; + char **lines; + size_t i; + lxcFstabPtr line = NULL; + + lines = virStringSplit(fstabString, "\n", 0); + + for (i = 0; lines[i]; i++) { + if (!(line = lxcParseFstabLine(lines[i]))) + continue; + line->next = fstab; + fstab = line; + } + + virStringFreeList(lines); + + return fstab; +} + +static lxcFstabPtr +lxcParseFstabFile(const char *path) +{ + lxcFstabPtr fstab = NULL; + FILE *fp = fopen(path, "r"); + char *tmp; + int tmplen = 0; + lxcFstabPtr line = NULL; + + if (!fp) { + char errbuf[1024]; + VIR_ERROR(_("Failed to open file %s: %s"), path, + virStrerror(errno, errbuf, sizeof(errbuf))); + goto cleanup; + } + + while (fgets(tmp, tmplen, fp) != NULL) { + if (tmplen == 0 || !(line = lxcParseFstabLine(tmp))) + continue; + line->next = fstab; + fstab = line; + } + + if (ferror(fp)) { + char errbuf[1024]; + VIR_ERROR(_("Failed to read file %s: %s"), path, + virStrerror(errno, errbuf, sizeof(errbuf))); + } + +cleanup: + VIR_FORCE_FCLOSE(fp); + + return fstab; +} + static int -lxcAddFSDef(virDomainDefPtr def, int type, char *src, char *dst) +lxcAddFSDef(virDomainDefPtr def, + int type, + char *src, + char *dst, + bool readonly, + unsigned long long usage) { virDomainFSDefPtr fsDef = NULL; - if (!(fsDef = lxcCreateFSDef(type, src, dst))) + if (!(fsDef = lxcCreateFSDef(type, src, dst, readonly, usage))) goto error; if (VIR_EXPAND_N(def->fss, def->nfss, 1) < 0) @@ -260,7 +432,7 @@ lxcSetRootfs(virDomainDefPtr def, type = VIR_DOMAIN_FS_TYPE_BLOCK; - if (lxcAddFSDef(def, type, fssrc, fsdst) < 0) + if (lxcAddFSDef(def, type, fssrc, fsdst, false, 0) < 0) goto error; return 0; @@ -271,13 +443,90 @@ error: return -1; } +static unsigned long long +lxcConvertSize(const char *size, unsigned long memory) +{ + unsigned long long value = 0; + char *unit = NULL; + + /* Split the string into value and unit */ + if (virStrToLong_ull(size, &unit, 10, &value) < 0) + return 0; + + if (STREQ(unit, "%")) { + value = value * memory * 1024 / 100; + + } else if (virScaleInteger(&value, unit, 1, ULLONG_MAX) < 0) + return 0; + + return value; +} + +static int +lxcAddFstabLine(virDomainDefPtr def, lxcFstabPtr fstab, unsigned long memory) +{ + char *src = NULL; + char *dst = NULL; + char **options = virStringSplit(fstab->options, ",", 0); + bool readonly; + int type = VIR_DOMAIN_FS_TYPE_MOUNT; + unsigned long long usage = 0; + + if (fstab->dst[0] != '/') { + if (virAsprintf(&dst, "/%s", fstab->dst) < 0) + goto error; + } else if (VIR_STRDUP(dst, fstab->dst) < 0) + goto error; + + /* Check that we don't add basic mounts */ + if (lxcIsBasicMountLocation(dst)) { + VIR_FREE(dst); + return 0; + } + + if (STREQ(fstab->type, "tmpfs")) { + char *sizeStr = NULL; + size_t i; + type = VIR_DOMAIN_FS_TYPE_RAM; + + for (i = 0; options[i]; i++) { + if ((sizeStr = STRSKIP(options[i], "size="))) { + usage = lxcConvertSize(sizeStr, memory); + break; + } + } + /* Default tmpfs size is 50%, cf kernel doc */ + if (!sizeStr) + usage = lxcConvertSize("50%", memory); + } else if (VIR_STRDUP(src, fstab->src) < 0) + goto error; + + /* Do we have ro in options? */ + readonly = virStringArrayHasString(options, "ro"); + + if (lxcAddFSDef(def, type, src, dst, readonly, usage) < 0) + goto error; + + + return 1; + +error: + VIR_FREE(dst); + VIR_FREE(src); + virStringFreeList(options); + return -1; +} + virDomainDefPtr lxcParseConfigString(const char *config, - const char *fstab ATTRIBUTE_UNUSED, + const char *fstab, unsigned long memory) { virDomainDefPtr vmdef = NULL; virPropertiesPtr properties = NULL; + lxcFstabPtr fstabEntries = NULL; + char *mountLine = NULL; + lxcFstabPtr fstabIter = NULL; if (!(properties = lxcParseProperties(config))) return NULL; @@ -290,6 +539,7 @@ lxcParseConfigString(const char *config, _("failed to generate uuid")); goto error; } + vmdef->id = -1; vmdef->mem.max_balloon = memory; @@ -302,6 +552,8 @@ lxcParseConfigString(const char *config, * minimum required to make XML parsing pass */ vmdef->maxvcpus = 1; + vmdef->nfss = 0; + if (VIR_STRDUP(vmdef->os.type, "exe") < 0) goto error; @@ -316,6 +568,38 @@ lxcParseConfigString(const char *config, if (lxcSetRootfs(vmdef, properties) < 0) goto error; + /* Look for fstab */ + if (!fstab) { + char *fstabPath = NULL; + if (VIR_STRDUP(fstabPath, virPropertiesLookup(properties, "lxc.mount")) < 0) + goto error; + + fstabEntries = lxcParseFstabFile(fstabPath); + VIR_FREE(fstabPath); + } else { + fstabEntries = lxcParseFstabString(fstab); + } + + /* Loop over lxc.mount.entry to add them to fstab */ + mountLine = virPropertiesLookup(properties, "lxc.mount.entry"); + while (mountLine) { + lxcFstabPtr fstabLine = lxcParseFstabLine(mountLine); + if (fstabLine) { + fstabLine->next = fstabEntries; + fstabEntries = fstabLine; + } + mountLine = virPropertiesLookup(properties, NULL); + } + + /* Loop over fstab entries to add filesystem devices for them */ + fstabIter = fstabEntries; + while (fstabIter) { + if (lxcAddFstabLine(vmdef, fstabIter, memory) < 0) + goto error; + + fstabIter = fstabIter->next; + } + goto cleanup; error: @@ -323,6 +607,7 @@ error: vmdef = NULL; cleanup: + lxcFstabFree(fstabEntries); virPropertiesFree(properties); return vmdef; diff --git a/tests/lxcconf2xmldata/lxcconf2xml-simple.xml b/tests/lxcconf2xmldata/lxcconf2xml-simple.xml index 621e699..8f2d442 100644 --- a/tests/lxcconf2xmldata/lxcconf2xml-simple.xml +++ b/tests/lxcconf2xmldata/lxcconf2xml-simple.xml @@ -17,5 +17,14 @@ <source dir='/var/lib/lxc/migrate_test/rootfs'/> <target dir='/'/> </filesystem> + <filesystem type='mount' accessmode='passthrough'> + <source dir='/etc/resolv.conf'/> + <target dir='/etc/resolv.conf'/> + <readonly/> + </filesystem> + <filesystem type='ram' accessmode='passthrough'> + <source usage='2017885' units='KiB'/> + <target dir='/run'/> + </filesystem> </devices> </domain> -- 1.8.5.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list