[libvirt] [PATCH] lxc: allow defining environment variables

Cédric Bosdonnat posted 1 patch 6 years, 10 months ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/libvirt tags/patchew/20170530193243.24257-1-cbosdonnat@suse.com
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
[libvirt] [PATCH] lxc: allow defining environment variables
Posted by Cédric Bosdonnat 6 years, 10 months ago
When running an application container, setting environment variables
could be important.

The newly introduced <initenv> tag in domain configuration will allow
setting environment variables to the init program.
---
 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 07208eef8..8da50875b 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 <code>/proc/cmdline</code>
       but will not affect init argv.
     </p>
+    <p>
+      To set environment variables, use the <code>initenv</code> element, one
+      for each variable.
+    </p>
 
     <pre>
 &lt;os&gt;
@@ -333,6 +337,7 @@
   &lt;init&gt;/bin/systemd&lt;/init&gt;
   &lt;initarg&gt;--unit&lt;/initarg&gt;
   &lt;initarg&gt;emergency.service&lt;/initarg&gt;
+  &lt;initenv name='MYENV'&gt;some value&lt;/initenv&gt;
 &lt;/os&gt;
     </pre>
 
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 4d9f8d1a2..695214816 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -385,6 +385,16 @@
             <text/>
           </element>
         </zeroOrMore>
+        <zeroOrMore>
+          <element name="initenv">
+            <attribute name="name">
+              <data type='string'>
+                <param name='pattern'>[a-zA-Z_]+[a-zA-Z0-9_]*</param>
+              </data>
+            </attribute>
+            <text/>
+          </element>
+        </zeroOrMore>
       </interleave>
     </element>
   </define>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index c7e20b8ba..89c803047 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2799,6 +2799,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);
@@ -16776,6 +16779,7 @@ virDomainDefParseBootOptions(virDomainDefPtr def,
     xmlNodePtr *nodes = NULL;
     xmlNodePtr oldnode;
     char *tmp = NULL;
+    char *name = NULL;
     int ret = -1;
     size_t i;
     int n;
@@ -16811,6 +16815,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 <initenv> element"));
+                goto error;
+            }
+
+            if (!nodes[i]->children ||
+                !nodes[i]->children->content) {
+                virReportError(VIR_ERR_XML_ERROR,
+                               _("No value supplied for <initenv name='%s'> 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 ||
@@ -24524,6 +24559,9 @@ virDomainDefFormatInternal(virDomainDefPtr def,
     for (i = 0; def->os.initargv && def->os.initargv[i]; i++)
         virBufferEscapeString(buf, "<initarg>%s</initarg>\n",
                               def->os.initargv[i]);
+    for (i = 0; def->os.initenv && def->os.initenv[i]; i++)
+        virBufferAsprintf(buf, "<initenv name='%s'>%s</initenv>\n",
+                          def->os.initenv[i]->name, def->os.initenv[i]->value);
     if (def->os.loader)
         virDomainLoaderDefFormat(buf, def->os.loader);
     virBufferEscapeString(buf, "<kernel>%s</kernel>\n",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 83e067269..03153b972 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1820,6 +1820,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 {
@@ -1833,6 +1840,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 af02b5460..ffafc39d7 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 000000000..933d836a2
--- /dev/null
+++ b/tests/lxcxml2xmldata/lxc-initenv.xml
@@ -0,0 +1,30 @@
+<domain type='lxc'>
+  <name>jessie</name>
+  <uuid>e21987a5-e98e-9c99-0e35-803e4d9ad1fe</uuid>
+  <memory unit='KiB'>1048576</memory>
+  <currentMemory unit='KiB'>1048576</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <resource>
+    <partition>/machine</partition>
+  </resource>
+  <os>
+    <type arch='x86_64'>exe</type>
+    <init>/sbin/sh</init>
+    <initenv name='FOO'>bar</initenv>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>restart</on_crash>
+  <devices>
+    <emulator>/usr/libexec/libvirt_lxc</emulator>
+    <filesystem type='mount' accessmode='passthrough'>
+      <source dir='/mach/jessie'/>
+      <target dir='/'/>
+    </filesystem>
+    <console type='pty'>
+      <target type='lxc' port='0'/>
+    </console>
+  </devices>
+  <seclabel type='none'/>
+</domain>
diff --git a/tests/lxcxml2xmltest.c b/tests/lxcxml2xmltest.c
index 226a73d27..2a24b60b3 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.12.2

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] lxc: allow defining environment variables
Posted by Daniel P. Berrange 6 years, 9 months ago
On Tue, May 30, 2017 at 09:32:43PM +0200, Cédric Bosdonnat wrote:
> When running an application container, setting environment variables
> could be important.
> 
> The newly introduced <initenv> tag in domain configuration will allow
> setting environment variables to the init program.
> ---
>  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

Generally looks fine, but do we need to wire this up for  native-to-xml
conversion too ?


Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] lxc: allow defining environment variables
Posted by Cedric Bosdonnat 6 years, 9 months ago
On Mon, 2017-06-05 at 15:23 +0100, Daniel P. Berrange wrote:
> On Tue, May 30, 2017 at 09:32:43PM +0200, Cédric Bosdonnat wrote:
> > When running an application container, setting environment variables
> > could be important.
> > 
> > The newly introduced <initenv> tag in domain configuration will allow
> > setting environment variables to the init program.
> > ---
> >  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
> 
> Generally looks fine, but do we need to wire this up for  native-to-xml
> conversion too ?

lxc config file doesn't have anything related to the command to run, it's env
variables and PWD. These will need to be added in docker's json native-to-xml though.

--
Cedric

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list