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