From 25630a37350336262d0ad10c2a401eacfe366f14 Mon Sep 17 00:00:00 2001
From: =?utf8?q?C=C3=A9dric=20Bosdonnat?=
Date: Tue, 30 May 2017 17:03:58 +0200
Subject: [PATCH] lxc: allow defining environment variables
When running an application container, setting environment variables
could be important.
The newly introduced tag in domain configuration will allow
setting environment variables to the init program.
Reviewed-by: Daniel P. Berrange
---
docs/formatdomain.html.in | 5 ++++
docs/schemas/domaincommon.rng | 10 ++++++++
src/conf/domain_conf.c | 38 ++++++++++++++++++++++++++++
src/conf/domain_conf.h | 8 ++++++
src/lxc/lxc_container.c | 5 ++++
tests/lxcxml2xmldata/lxc-initenv.xml | 30 ++++++++++++++++++++++
tests/lxcxml2xmltest.c | 1 +
7 files changed, 97 insertions(+)
create mode 100644 tests/lxcxml2xmldata/lxc-initenv.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 36bea67c38..f4132b4c41 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -326,6 +326,10 @@
element, if set will be used to provide an equivalent to /proc/cmdline
but will not affect init argv.
+
+ To set environment variables, use the initenv
element, one
+ for each variable.
+
<os>
@@ -333,6 +337,7 @@
<init>/bin/systemd</init>
<initarg>--unit</initarg>
<initarg>emergency.service</initarg>
+ <initenv name='MYENV'>some value</initenv>
</os>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index bdf7103d76..930e31c42b 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -385,6 +385,16 @@
+
+
+
+
+ [a-zA-Z_]+[a-zA-Z0-9_]*
+
+
+
+
+
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index c3149f9769..71b43ca236 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2874,6 +2874,9 @@ void virDomainDefFree(virDomainDefPtr def)
for (i = 0; def->os.initargv && def->os.initargv[i]; i++)
VIR_FREE(def->os.initargv[i]);
VIR_FREE(def->os.initargv);
+ for (i = 0; def->os.initenv && def->os.initenv[i]; i++)
+ VIR_FREE(def->os.initenv[i]);
+ VIR_FREE(def->os.initenv);
VIR_FREE(def->os.kernel);
VIR_FREE(def->os.initrd);
VIR_FREE(def->os.cmdline);
@@ -17048,6 +17051,7 @@ virDomainDefParseBootOptions(virDomainDefPtr def,
xmlNodePtr *nodes = NULL;
xmlNodePtr oldnode;
char *tmp = NULL;
+ char *name = NULL;
int ret = -1;
size_t i;
int n;
@@ -17083,6 +17087,37 @@ virDomainDefParseBootOptions(virDomainDefPtr def,
}
def->os.initargv[n] = NULL;
VIR_FREE(nodes);
+
+ if ((n = virXPathNodeSet("./os/initenv", ctxt, &nodes)) < 0)
+ goto error;
+
+ if (VIR_ALLOC_N(def->os.initenv, n+1) < 0)
+ goto error;
+ for (i = 0; i < n; i++) {
+ if (!(name = virXMLPropString(nodes[i], "name"))) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("No name supplied for element"));
+ goto error;
+ }
+
+ if (!nodes[i]->children ||
+ !nodes[i]->children->content) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("No value supplied for element"),
+ name);
+ goto error;
+ }
+
+ if (VIR_ALLOC(def->os.initenv[i]) < 0)
+ goto error;
+
+ def->os.initenv[i]->name = name;
+ if (VIR_STRDUP(def->os.initenv[i]->value,
+ (const char*) nodes[i]->children->content) < 0)
+ goto error;
+ }
+ def->os.initenv[n] = NULL;
+ VIR_FREE(nodes);
}
if (def->os.type == VIR_DOMAIN_OSTYPE_XEN ||
@@ -24915,6 +24950,9 @@ virDomainDefFormatInternal(virDomainDefPtr def,
for (i = 0; def->os.initargv && def->os.initargv[i]; i++)
virBufferEscapeString(buf, "%s \n",
def->os.initargv[i]);
+ for (i = 0; def->os.initenv && def->os.initenv[i]; i++)
+ virBufferAsprintf(buf, "%s \n",
+ def->os.initenv[i]->name, def->os.initenv[i]->value);
if (def->os.loader)
virDomainLoaderDefFormat(buf, def->os.loader);
virBufferEscapeString(buf, "%s \n",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 964bc02f9f..3f34601016 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1848,6 +1848,13 @@ typedef enum {
VIR_ENUM_DECL(virDomainIOAPIC);
/* Operating system configuration data & machine / arch */
+typedef struct _virDomainOSEnv virDomainOSEnv;
+typedef virDomainOSEnv *virDomainOSEnvPtr;
+struct _virDomainOSEnv {
+ char *name;
+ char *value;
+};
+
typedef struct _virDomainOSDef virDomainOSDef;
typedef virDomainOSDef *virDomainOSDefPtr;
struct _virDomainOSDef {
@@ -1861,6 +1868,7 @@ struct _virDomainOSDef {
bool bm_timeout_set;
char *init;
char **initargv;
+ virDomainOSEnvPtr *initenv;
char *kernel;
char *initrd;
char *cmdline;
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index af02b54605..ffafc39d79 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -246,6 +246,11 @@ static virCommandPtr lxcContainerBuildInitCmd(virDomainDefPtr vmDef,
if (vmDef->os.cmdline)
virCommandAddEnvPair(cmd, "LIBVIRT_LXC_CMDLINE", vmDef->os.cmdline);
+ for (i = 0; vmDef->os.initenv[i]; i++) {
+ virCommandAddEnvPair(cmd, vmDef->os.initenv[i]->name,
+ vmDef->os.initenv[i]->value);
+ }
+
virBufferFreeAndReset(&buf);
return cmd;
}
diff --git a/tests/lxcxml2xmldata/lxc-initenv.xml b/tests/lxcxml2xmldata/lxc-initenv.xml
new file mode 100644
index 0000000000..933d836a25
--- /dev/null
+++ b/tests/lxcxml2xmldata/lxc-initenv.xml
@@ -0,0 +1,30 @@
+
+ jessie
+ e21987a5-e98e-9c99-0e35-803e4d9ad1fe
+ 1048576
+ 1048576
+ 1
+
+ /machine
+
+
+ exe
+ /sbin/sh
+ bar
+
+
+ destroy
+ restart
+ restart
+
+ /usr/libexec/libvirt_lxc
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/lxcxml2xmltest.c b/tests/lxcxml2xmltest.c
index 226a73d274..2a24b60b3b 100644
--- a/tests/lxcxml2xmltest.c
+++ b/tests/lxcxml2xmltest.c
@@ -98,6 +98,7 @@ mymain(void)
DO_TEST("ethernet-hostip");
DO_TEST_FULL("filesystem-root", 0, false,
VIR_DOMAIN_DEF_PARSE_SKIP_OSTYPE_CHECKS);
+ DO_TEST("initenv");
virObjectUnref(caps);
virObjectUnref(xmlopt);
--
2.39.5