Imported Upstream version 1.0.7 upstream/1.0.7
authorDariusz Michaluk <d.michaluk@samsung.com>
Tue, 23 Dec 2014 09:10:34 +0000 (10:10 +0100)
committerDariusz Michaluk <d.michaluk@samsung.com>
Tue, 23 Dec 2014 09:10:34 +0000 (10:10 +0100)
63 files changed:
config/apparmor/abstractions/container-base
config/apparmor/abstractions/container-base.in
config/bash/Makefile.in
config/templates/plamo.common.conf.in
configure
configure.ac
doc/api/Doxyfile
doc/ja/lxc.container.conf.sgml.in
doc/ja/lxc.sgml.in
doc/lxc-create.sgml.in
doc/lxc.container.conf.sgml.in
doc/lxc.sgml.in
lxc.spec
lxc.spec.in
src/lxc/attach.c
src/lxc/attach_options.h
src/lxc/bdev.c
src/lxc/cgfs.c
src/lxc/cgmanager.c
src/lxc/commands.c
src/lxc/conf.c
src/lxc/conf.h
src/lxc/confile.c
src/lxc/legacy/lxc-ls.in
src/lxc/log.c
src/lxc/lxc-btrfs.h
src/lxc/lxc-checkconfig.in
src/lxc/lxc.h
src/lxc/lxc_info.c
src/lxc/lxc_start.c
src/lxc/lxc_unshare.c
src/lxc/lxc_user_nic.c
src/lxc/lxccontainer.c
src/lxc/lxccontainer.h
src/lxc/lxclock.c
src/lxc/network.c
src/lxc/network.h
src/lxc/nl.c
src/lxc/nl.h
src/lxc/start.c
src/lxc/utils.c
src/lxc/version.h
src/tests/Makefile.am
src/tests/Makefile.in
src/tests/containertests.c
src/tests/destroytest.c
src/tests/get_item.c
src/tests/lxc-test-unpriv
src/tests/lxc-test-usernic [deleted file]
src/tests/lxc-test-usernic.in
src/tests/saveconfig.c
src/tests/startone.c
templates/lxc-alpine.in
templates/lxc-busybox.in
templates/lxc-centos.in
templates/lxc-cirros.in
templates/lxc-debian.in
templates/lxc-fedora.in
templates/lxc-gentoo.in
templates/lxc-openmandriva.in
templates/lxc-opensuse.in
templates/lxc-plamo.in
templates/lxc-ubuntu.in

index d783c95..2d5fd7a 100644 (file)
@@ -3,14 +3,49 @@
   file,
   umount,
 
-  # The following 3 entries are only supported by recent apparmor versions.
-  # Comment them if the apparmor parser doesn't recognize them.
+  # dbus, signal, ptrace and unix are only supported by recent apparmor
+  # versions. Comment them if the apparmor parser doesn't recognize them.
+
+  # This also needs additional rules to reach outside of the container via
+  # DBus, so just let all of DBus within the container.
   dbus,
-  signal,
-  ptrace,
+
+  # Allow us to receive signals from anywhere. Note: if per-container profiles
+  # are supported, for container isolation this should be changed to something
+  # like:
+  #   signal (receive) peer=unconfined,
+  #   signal (receive) peer=/usr/bin/lxc-start,
+  signal (receive),
+
+  # Allow us to send signals to ourselves
+  signal peer=@{profile_name},
+
+  # Allow other processes to read our /proc entries, futexes, perf tracing and
+  # kcmp for now (they will need 'read' in the first place). Administrators can
+  # override with:
+  #   deny ptrace (readby) ...
+  ptrace (readby),
+
+  # Allow other processes to trace us by default (they will need 'trace' in
+  # the first place). Administrators can override with:
+  #   deny ptrace (tracedby) ...
+  ptrace (tracedby),
+
+  # Allow us to ptrace ourselves
+  ptrace peer=@{profile_name},
+
+  # Allow receive via unix sockets from anywhere. Note: if per-container
+  # profiles are supported, for container isolation this should be changed to
+  # something like:
+  #   unix (receive) peer=(label=unconfined),
+  unix (receive),
+
+  # Allow all unix in the container
+  unix peer=(label=@{profile_name}),
 
   # ignore DENIED message on / remount
   deny mount options=(ro, remount) -> /,
+  deny mount options=(ro, remount, silent) -> /,
 
   # allow tmpfs mounts everywhere
   mount fstype=tmpfs,
index c82f900..2065735 100644 (file)
@@ -3,14 +3,49 @@
   file,
   umount,
 
-  # The following 3 entries are only supported by recent apparmor versions.
-  # Comment them if the apparmor parser doesn't recognize them.
+  # dbus, signal, ptrace and unix are only supported by recent apparmor
+  # versions. Comment them if the apparmor parser doesn't recognize them.
+
+  # This also needs additional rules to reach outside of the container via
+  # DBus, so just let all of DBus within the container.
   dbus,
-  signal,
-  ptrace,
+
+  # Allow us to receive signals from anywhere. Note: if per-container profiles
+  # are supported, for container isolation this should be changed to something
+  # like:
+  #   signal (receive) peer=unconfined,
+  #   signal (receive) peer=/usr/bin/lxc-start,
+  signal (receive),
+
+  # Allow us to send signals to ourselves
+  signal peer=@{profile_name},
+
+  # Allow other processes to read our /proc entries, futexes, perf tracing and
+  # kcmp for now (they will need 'read' in the first place). Administrators can
+  # override with:
+  #   deny ptrace (readby) ...
+  ptrace (readby),
+
+  # Allow other processes to trace us by default (they will need 'trace' in
+  # the first place). Administrators can override with:
+  #   deny ptrace (tracedby) ...
+  ptrace (tracedby),
+
+  # Allow us to ptrace ourselves
+  ptrace peer=@{profile_name},
+
+  # Allow receive via unix sockets from anywhere. Note: if per-container
+  # profiles are supported, for container isolation this should be changed to
+  # something like:
+  #   unix (receive) peer=(label=unconfined),
+  unix (receive),
+
+  # Allow all unix in the container
+  unix peer=(label=@{profile_name}),
 
   # ignore DENIED message on / remount
   deny mount options=(ro, remount) -> /,
+  deny mount options=(ro, remount, silent) -> /,
 
   # allow tmpfs mounts everywhere
   mount fstype=tmpfs,
index b6decb1..a6ea48a 100644 (file)
@@ -378,8 +378,8 @@ distclean-generic:
 maintainer-clean-generic:
        @echo "This command is intended for maintainers to use"
        @echo "it deletes files that may require special tools to rebuild."
-@ENABLE_BASH_FALSE@install-data-local:
 @ENABLE_BASH_FALSE@uninstall-local:
+@ENABLE_BASH_FALSE@install-data-local:
 clean: clean-am
 
 clean-am: clean-generic mostlyclean-am
index 4f044c0..3115581 100644 (file)
@@ -4,6 +4,7 @@ lxc.pts = 1024
 
 # Default mount
 lxc.mount.auto = proc sys cgroup
+lxc.mount.entry = none dev/shm tmpfs nosuid,nodev,noexec,mode=1777 0 0
 
 # Default capabilities
 lxc.cap.drop = sys_module mac_admin mac_override sys_time
index 463edc0..0667f52 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for lxc 1.0.6.
+# Generated by GNU Autoconf 2.69 for lxc 1.0.7.
 #
 #
 # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -577,8 +577,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='lxc'
 PACKAGE_TARNAME='lxc'
-PACKAGE_VERSION='1.0.6'
-PACKAGE_STRING='lxc 1.0.6'
+PACKAGE_VERSION='1.0.7'
+PACKAGE_STRING='lxc 1.0.7'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
@@ -1430,7 +1430,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures lxc 1.0.6 to adapt to many kinds of systems.
+\`configure' configures lxc 1.0.7 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1500,7 +1500,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of lxc 1.0.6:";;
+     short | recursive ) echo "Configuration of lxc 1.0.7:";;
    esac
   cat <<\_ACEOF
 
@@ -1658,7 +1658,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-lxc configure 1.0.6
+lxc configure 1.0.7
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2123,7 +2123,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by lxc $as_me 1.0.6, which was
+It was created by lxc $as_me 1.0.7, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2594,7 +2594,7 @@ $as_echo "no" >&6; }
        fi
 fi
 
-LXC_VERSION_BASE=1.0.6
+LXC_VERSION_BASE=1.0.7
 
 
 
@@ -2602,9 +2602,9 @@ LXC_VERSION_MAJOR=1
 
 LXC_VERSION_MINOR=0
 
-LXC_VERSION_MICRO=6
+LXC_VERSION_MICRO=7
 
-LXC_VERSION=1.0.6
+LXC_VERSION=1.0.7
 
 
 
@@ -3125,7 +3125,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='lxc'
- VERSION='1.0.6'
+ VERSION='1.0.7'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -9745,7 +9745,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by lxc $as_me 1.0.6, which was
+This file was extended by lxc $as_me 1.0.7, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -9815,7 +9815,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-lxc config.status 1.0.6
+lxc config.status 1.0.7
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
index 6ec5740..6f41f8a 100644 (file)
@@ -3,7 +3,7 @@
 
 m4_define([lxc_version_major], 1)
 m4_define([lxc_version_minor], 0)
-m4_define([lxc_version_micro], 6)
+m4_define([lxc_version_micro], 7)
 m4_define([lxc_version_beta], [])
 
 m4_define([lxc_version_base], [lxc_version_major.lxc_version_minor.lxc_version_micro])
index 9432669..e6ada00 100644 (file)
@@ -1940,7 +1940,7 @@ PREDEFINED             =
 EXPAND_AS_DEFINED      =
 
 # If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
-# remove all refrences to function-like macros that are alone on a line, have an
+# remove all references to function-like macros that are alone on a line, have an
 # all uppercase name, and do not end with a semicolon. Such function macros are
 # typically used for boiler-plate code, and will confuse the parser if not
 # removed.
index 03a16b3..9bb81d5 100644 (file)
@@ -723,7 +723,7 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
               the maximum number of pseudo ttys allowed for a pts
               instance (this limitation is not implemented yet).
               -->
-              もし設定された場合、コンテナは新しい psuedo tty インスタンスを持ち、それを自身のプライベートとします。
+              もし設定された場合、コンテナは新しい pseudo tty インスタンスを持ち、それを自身のプライベートとします。
               この値は pts インスタンスに許可される pseudo tty の最大数を指定します (この制限はまだ実装されていません)。
            </para>
          </listitem>
index e5f5e33..6bfd04e 100644 (file)
@@ -166,52 +166,30 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
 
       <para>
        <!--
-       The kernel version >= 2.6.27 shipped with the distros, will
+       The kernel version >= 2.6.32 shipped with the distros, will
        work with <command>lxc</command>, this one will have less
        functionalities but enough to be interesting.
 
-       With the kernel 2.6.29, <command>lxc</command> is fully
-       functional.
-
        The helper script <command>lxc-checkconfig</command> will give
        you information about your kernel configuration.
        -->
-       2.6.27 以上のバージョンが採用されているディストリビューションならば、<command>lxc</command> は動作するでしょう。
+       2.6.32 以上のバージョンが採用されているディストリビューションならば、<command>lxc</command> は動作するでしょう。
         機能的には若干少ない形ですが、充分に楽しめるはずです。
-        2.6.29 カーネルであれば、<command>lxc</command> は完全に機能します。
         ヘルパースクリプトの <command>lxc-checkconfig</command> を使って、あなたのカーネルの設定に関する情報を取得できるでしょう。
       </para>
 
       <para>
        <!--
-       Before using the <command>lxc</command>, your system should be
-       configured with the file capabilities, otherwise you will need
-       to run the <command>lxc</command> commands as root.
-       -->
-       <command>lxc</command> を使う前に、システムがファイルに対するケーパビリティーをえられるように設定するか、もしくは <command>lxc</command> コマンドを root で実行する必要があるでしょう。
-      </para>
-
-      <para>
-       <!--
          The control group can be mounted anywhere, eg:
          <command>mount -t cgroup cgroup /cgroup</command>.
 
-         If you want to dedicate a specific cgroup mount point
-         for <command>lxc</command>, that is to have different cgroups
-         mounted at different places with different options but
-         let <command>lxc</command> to use one location, you can bind
-         the mount point with the <option>lxc</option> name, eg:
-         <command>mount -t cgroup lxc /cgroup4lxc</command> or
-         <command>mount -t cgroup -ons,cpuset,freezer,devices
-         lxc /cgroup4lxc</command>
+         It is however recommended to use cgmanager, cgroup-lite or systemd
+         to mount the cgroup hierarchy under /sys/fs/cgroup.
         -->
        control group は、どこにでもマウント可能です。
         例えば、<command>mount -t cgroup cgroup /cgroup</command> のようにです。
 
-       もし、異なる場所で、異なるオプションでマウントされた別々の cgroup を持ち、一つの場所の <command>lxc</command> コマンドを使うための、特定の <command>lxc</command> のための専用の cgroup のマウントポイントを提供したければ、lxc という名前でマウントポイントにバインドすることが出来ます。例えば以下のようにです。
-         <command>mount -t cgroup lxc /cgroup4lxc</command> or
-         <command>mount -t cgroup -ons,cpuset,freezer,devices
-         lxc /cgroup4lxc</command>
+       しかし、cgroup の階層構造を /sys/fs/cgroup 以下にマウントするために cgmanager や cgroup-lite や systemd の使用が推奨されています。
       </para>
 
   </refsect1>
index 4c8b108..0012d0a 100644 (file)
@@ -51,7 +51,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
       <command>lxc-create</command>
       <arg choice="req">-n <replaceable>name</replaceable></arg>
       <arg choice="opt">-f <replaceable>config_file</replaceable></arg>
-      <arg choice="opt">-t <replaceable>template</replaceable></arg>
+      <arg choice="reg">-t <replaceable>template</replaceable></arg>
       <arg choice="opt">-B <replaceable>backingstore</replaceable></arg>
       <arg choice="opt">-- <replaceable>template-options</replaceable></arg>
     </cmdsynopsis>
index 88a5f05..9cd0c57 100644 (file)
@@ -78,57 +78,57 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     <refsect2>
       <title>Configuration</title>
       <para>
-       In order to ease administration of multiple related containers, it
-       is possible to have a container configuration file cause another
-       file to be loaded.  For instance, network configuration
-       can be defined in one common file which is included by multiple
-       containers.  Then, if the containers are moved to another host,
-       only one file may need to be updated.
+        In order to ease administration of multiple related containers, it
+        is possible to have a container configuration file cause another
+        file to be loaded.  For instance, network configuration
+        can be defined in one common file which is included by multiple
+        containers.  Then, if the containers are moved to another host,
+        only one file may need to be updated.
       </para>
 
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.include</option>
-         </term>
-         <listitem>
-           <para>
-             Specify the file to be included.  The included file must be
-             in the same valid lxc configuration file format.
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.include</option>
+          </term>
+          <listitem>
+            <para>
+              Specify the file to be included.  The included file must be
+              in the same valid lxc configuration file format.
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
     </refsect2>
 
     <refsect2>
       <title>Architecture</title>
       <para>
-       Allows one to set the architecture for the container. For example,
-       set a 32bits architecture for a container running 32bits
-       binaries on a 64bits host. This fixes the container scripts
-       which rely on the architecture to do some work like
-       downloading the packages.
+        Allows one to set the architecture for the container. For example,
+        set a 32bits architecture for a container running 32bits
+        binaries on a 64bits host. This fixes the container scripts
+        which rely on the architecture to do some work like
+        downloading the packages.
       </para>
 
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.arch</option>
-         </term>
-         <listitem>
-           <para>
-             Specify the architecture for the container.
-           </para>
-           <para>
-             Valid options are
-             <option>x86</option>,
-             <option>i686</option>,
-             <option>x86_64</option>,
-             <option>amd64</option>
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.arch</option>
+          </term>
+          <listitem>
+            <para>
+              Specify the architecture for the container.
+            </para>
+            <para>
+              Valid options are
+              <option>x86</option>,
+              <option>i686</option>,
+              <option>x86_64</option>,
+              <option>amd64</option>
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
 
     </refsect2>
@@ -136,22 +136,22 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     <refsect2>
       <title>Hostname</title>
       <para>
-       The utsname section defines the hostname to be set for the
-       container. That means the container can set its own hostname
-       without changing the one from the system. That makes the
-       hostname private for the container.
+        The utsname section defines the hostname to be set for the
+        container. That means the container can set its own hostname
+        without changing the one from the system. That makes the
+        hostname private for the container.
       </para>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.utsname</option>
-         </term>
-         <listitem>
-           <para>
-             specify the hostname for the container
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.utsname</option>
+          </term>
+          <listitem>
+            <para>
+              specify the hostname for the container
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
     </refsect2>
 
@@ -204,388 +204,388 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     <refsect2>
       <title>Network</title>
       <para>
-       The network section defines how the network is virtualized in
-       the container. The network virtualization acts at layer
-       two. In order to use the network virtualization, parameters
-       must be specified to define the network interfaces of the
-       container. Several virtual interfaces can be assigned and used
-       in a container even if the system has only one physical
-       network interface.
+        The network section defines how the network is virtualized in
+        the container. The network virtualization acts at layer
+        two. In order to use the network virtualization, parameters
+        must be specified to define the network interfaces of the
+        container. Several virtual interfaces can be assigned and used
+        in a container even if the system has only one physical
+        network interface.
       </para>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.network.type</option>
-         </term>
-         <listitem>
-           <para>
-             specify what kind of network virtualization to be used
-             for the container. Each time
-             a <option>lxc.network.type</option> field is found a new
-             round of network configuration begins. In this way,
-             several network virtualization types can be specified
-             for the same container, as well as assigning several
-             network interfaces for one container. The different
-             virtualization types can be:
-           </para>
-
-           <para>
-             <option>none:</option> will cause the container to share
-             the host's network namespace.  This means the host
-             network devices are usable in the container.  It also
-             means that if both the container and host have upstart as
-             init, 'halt' in a container (for instance) will shut down the
-             host.
-           </para>
-
-           <para>
-             <option>empty:</option> will create only the loopback
-             interface.
-           </para>
-
-           <para>
-             <option>veth:</option> a peer network device is created
-             with one side assigned to the container and the other
-             side is attached to a bridge specified by
-             the <option>lxc.network.link</option>. If the bridge is
-             not specified, then the veth pair device will be created
-             but not attached to any bridge. Otherwise, the bridge
-             has to be setup before on the
-             system, <command>lxc</command> won't handle any
-             configuration outside of the container.  By
-             default <command>lxc</command> choose a name for the
-             network device belonging to the outside of the
-             container, this name is handled
-             by <command>lxc</command>, but if you wish to handle
-             this name yourself, you can tell <command>lxc</command>
-             to set a specific name with
-             the <option>lxc.network.veth.pair</option> option (except for
-             unprivileged containers where this option is ignored for security
-             reasons).
-           </para>
-
-           <para>
-             <option>vlan:</option> a vlan interface is linked with
-             the interface specified by
-             the <option>lxc.network.link</option> and assigned to
-             the container. The vlan identifier is specified with the
-             option <option>lxc.network.vlan.id</option>.
-           </para>
-
-           <para>
-             <option>macvlan:</option> a macvlan interface is linked
-             with the interface specified by
-             the <option>lxc.network.link</option> and assigned to
-             the container.
-             <option>lxc.network.macvlan.mode</option> specifies the
-             mode the macvlan will use to communicate between
-             different macvlan on the same upper device. The accepted
-             modes are <option>private</option>, the device never
-             communicates with any other device on the same upper_dev (default),
-             <option>vepa</option>, the new Virtual Ethernet Port
-             Aggregator (VEPA) mode, it assumes that the adjacent
-             bridge returns all frames where both source and
-             destination are local to the macvlan port, i.e. the
-             bridge is set up as a reflective relay.  Broadcast
-             frames coming in from the upper_dev get flooded to all
-             macvlan interfaces in VEPA mode, local frames are not
-             delivered locally, or <option>bridge</option>, it
-             provides the behavior of a simple bridge between
-             different macvlan interfaces on the same port. Frames
-             from one interface to another one get delivered directly
-             and are not sent out externally. Broadcast frames get
-             flooded to all other bridge ports and to the external
-             interface, but when they come back from a reflective
-             relay, we don't deliver them again.  Since we know all
-             the MAC addresses, the macvlan bridge mode does not
-             require learning or STP like the bridge module does.
-           </para>
-
-           <para>
-             <option>phys:</option> an already existing interface
-             specified by the <option>lxc.network.link</option> is
-             assigned to the container.
-           </para>
-         </listitem>
-         </varlistentry>
-
-       <varlistentry>
-         <term>
-           <option>lxc.network.flags</option>
-         </term>
-         <listitem>
-           <para>
-             specify an action to do for the
-             network.
-           </para>
-
-           <para><option>up:</option> activates the interface.
-           </para>
-         </listitem>
-       </varlistentry>
-
-       <varlistentry>
-         <term>
-           <option>lxc.network.link</option>
-         </term>
-         <listitem>
-           <para>
-             specify the interface to be used for real network
-             traffic.
-           </para>
-         </listitem>
-       </varlistentry>
-
-       <varlistentry>
-         <term>
-           <option>lxc.network.mtu</option>
-         </term>
-         <listitem>
-           <para>
-             specify the maximum transfer unit for this interface.
-           </para>
-         </listitem>
-       </varlistentry>
-
-       <varlistentry>
-         <term>
-           <option>lxc.network.name</option>
-         </term>
-         <listitem>
-           <para>
-             the interface name is dynamically allocated, but if
-             another name is needed because the configuration files
-             being used by the container use a generic name,
-             eg. eth0, this option will rename the interface in the
-             container.
-           </para>
-         </listitem>
-       </varlistentry>
-
-       <varlistentry>
-         <term>
-           <option>lxc.network.hwaddr</option>
-         </term>
-         <listitem>
-           <para>
-             the interface mac address is dynamically allocated by
-             default to the virtual interface, but in some cases,
-             this is needed to resolve a mac address conflict or to
-             always have the same link-local ipv6 address.
-             Any "x" in address will be replaced by random value,
-             this allows setting hwaddr templates.
-           </para>
-         </listitem>
-       </varlistentry>
-
-       <varlistentry>
-         <term>
-           <option>lxc.network.ipv4</option>
-         </term>
-         <listitem>
-           <para>
-             specify the ipv4 address to assign to the virtualized
-             interface. Several lines specify several ipv4 addresses.
-             The address is in format x.y.z.t/m,
-             eg. 192.168.1.123/24. The broadcast address should be
-             specified on the same line, right after the ipv4
-             address.
-           </para>
-         </listitem>
-       </varlistentry>
-
-       <varlistentry>
-         <term>
-           <option>lxc.network.ipv4.gateway</option>
-         </term>
-         <listitem>
-           <para>
-             specify the ipv4 address to use as the gateway inside the
-             container. The address is in format x.y.z.t, eg.
-             192.168.1.123.
-
-             Can also have the special value <option>auto</option>,
-             which means to take the primary address from the bridge
-             interface (as specified by the
-             <option>lxc.network.link</option> option) and use that as
-             the gateway. <option>auto</option> is only available when
-             using the <option>veth</option> and
-             <option>macvlan</option> network types.
-           </para>
-         </listitem>
-       </varlistentry>
-
-
-       <varlistentry>
-         <term>
-           <option>lxc.network.ipv6</option>
-         </term>
-         <listitem>
-           <para>
-             specify the ipv6 address to assign to the virtualized
-             interface. Several lines specify several ipv6 addresses.
-             The address is in format x::y/m,
-             eg. 2003:db8:1:0:214:1234:fe0b:3596/64
-           </para>
-         </listitem>
-       </varlistentry>
-
-       <varlistentry>
-         <term>
-           <option>lxc.network.ipv6.gateway</option>
-         </term>
-         <listitem>
-           <para>
-             specify the ipv6 address to use as the gateway inside the
-             container. The address is in format x::y,
-             eg. 2003:db8:1:0::1
-
-             Can also have the special value <option>auto</option>,
-             which means to take the primary address from the bridge
-             interface (as specified by the
-             <option>lxc.network.link</option> option) and use that as
-             the gateway. <option>auto</option> is only available when
-             using the <option>veth</option> and
-             <option>macvlan</option> network types.
-           </para>
-         </listitem>
-       </varlistentry>
-
-       <varlistentry>
-         <term>
-           <option>lxc.network.script.up</option>
-         </term>
-         <listitem>
-           <para>
-             add a configuration option to specify a script to be
-             executed after creating and configuring the network used
-             from the host side. The following arguments are passed
-             to the script: container name and config section name
-             (net) Additional arguments depend on the config section
-             employing a script hook; the following are used by the
-             network system: execution context (up), network type
-             (empty/veth/macvlan/phys), Depending on the network
-             type, other arguments may be passed:
-             veth/macvlan/phys. And finally (host-sided) device name.
-           </para>
-           <para>
-             Standard output from the script is logged at debug level.
-             Standard error is not logged, but can be captured by the
-             hook redirecting its standard error to standard output.
-           </para>
-         </listitem>
-       </varlistentry>
-
-       <varlistentry>
-         <term>
-           <option>lxc.network.script.down</option>
-         </term>
-         <listitem>
-           <para>
-             add a configuration option to specify a script to be
-             executed before destroying the network used from the
-             host side. The following arguments are passed to the
-             script: container name and config section name (net)
-             Additional arguments depend on the config section
-             employing a script hook; the following are used by the
-             network system: execution context (down), network type
-             (empty/veth/macvlan/phys), Depending on the network
-             type, other arguments may be passed:
-             veth/macvlan/phys. And finally (host-sided) device name.
-           </para>
-           <para>
-             Standard output from the script is logged at debug level.
-             Standard error is not logged, but can be captured by the
-             hook redirecting its standard error to standard output.
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.network.type</option>
+          </term>
+          <listitem>
+            <para>
+              specify what kind of network virtualization to be used
+              for the container. Each time
+              a <option>lxc.network.type</option> field is found a new
+              round of network configuration begins. In this way,
+              several network virtualization types can be specified
+              for the same container, as well as assigning several
+              network interfaces for one container. The different
+              virtualization types can be:
+            </para>
+
+            <para>
+              <option>none:</option> will cause the container to share
+              the host's network namespace.  This means the host
+              network devices are usable in the container.  It also
+              means that if both the container and host have upstart as
+              init, 'halt' in a container (for instance) will shut down the
+              host.
+            </para>
+
+            <para>
+              <option>empty:</option> will create only the loopback
+              interface.
+            </para>
+
+            <para>
+              <option>veth:</option> a peer network device is created
+              with one side assigned to the container and the other
+              side is attached to a bridge specified by
+              the <option>lxc.network.link</option>. If the bridge is
+              not specified, then the veth pair device will be created
+              but not attached to any bridge. Otherwise, the bridge
+              has to be setup before on the
+              system, <command>lxc</command> won't handle any
+              configuration outside of the container.  By
+              default <command>lxc</command> choose a name for the
+              network device belonging to the outside of the
+              container, this name is handled
+              by <command>lxc</command>, but if you wish to handle
+              this name yourself, you can tell <command>lxc</command>
+              to set a specific name with
+              the <option>lxc.network.veth.pair</option> option (except for
+              unprivileged containers where this option is ignored for security
+              reasons).
+            </para>
+
+            <para>
+              <option>vlan:</option> a vlan interface is linked with
+              the interface specified by
+              the <option>lxc.network.link</option> and assigned to
+              the container. The vlan identifier is specified with the
+              option <option>lxc.network.vlan.id</option>.
+            </para>
+
+            <para>
+              <option>macvlan:</option> a macvlan interface is linked
+              with the interface specified by
+              the <option>lxc.network.link</option> and assigned to
+              the container.
+              <option>lxc.network.macvlan.mode</option> specifies the
+              mode the macvlan will use to communicate between
+              different macvlan on the same upper device. The accepted
+              modes are <option>private</option>, the device never
+              communicates with any other device on the same upper_dev (default),
+              <option>vepa</option>, the new Virtual Ethernet Port
+              Aggregator (VEPA) mode, it assumes that the adjacent
+              bridge returns all frames where both source and
+              destination are local to the macvlan port, i.e. the
+              bridge is set up as a reflective relay.  Broadcast
+              frames coming in from the upper_dev get flooded to all
+              macvlan interfaces in VEPA mode, local frames are not
+              delivered locally, or <option>bridge</option>, it
+              provides the behavior of a simple bridge between
+              different macvlan interfaces on the same port. Frames
+              from one interface to another one get delivered directly
+              and are not sent out externally. Broadcast frames get
+              flooded to all other bridge ports and to the external
+              interface, but when they come back from a reflective
+              relay, we don't deliver them again.  Since we know all
+              the MAC addresses, the macvlan bridge mode does not
+              require learning or STP like the bridge module does.
+            </para>
+
+            <para>
+              <option>phys:</option> an already existing interface
+              specified by the <option>lxc.network.link</option> is
+              assigned to the container.
+            </para>
+          </listitem>
+          </varlistentry>
+
+        <varlistentry>
+          <term>
+            <option>lxc.network.flags</option>
+          </term>
+          <listitem>
+            <para>
+              specify an action to do for the
+              network.
+            </para>
+
+            <para><option>up:</option> activates the interface.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>
+            <option>lxc.network.link</option>
+          </term>
+          <listitem>
+            <para>
+              specify the interface to be used for real network
+              traffic.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>
+            <option>lxc.network.mtu</option>
+          </term>
+          <listitem>
+            <para>
+              specify the maximum transfer unit for this interface.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>
+            <option>lxc.network.name</option>
+          </term>
+          <listitem>
+            <para>
+              the interface name is dynamically allocated, but if
+              another name is needed because the configuration files
+              being used by the container use a generic name,
+              eg. eth0, this option will rename the interface in the
+              container.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>
+            <option>lxc.network.hwaddr</option>
+          </term>
+          <listitem>
+            <para>
+              the interface mac address is dynamically allocated by
+              default to the virtual interface, but in some cases,
+              this is needed to resolve a mac address conflict or to
+              always have the same link-local ipv6 address.
+              Any "x" in address will be replaced by random value,
+              this allows setting hwaddr templates.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>
+            <option>lxc.network.ipv4</option>
+          </term>
+          <listitem>
+            <para>
+              specify the ipv4 address to assign to the virtualized
+              interface. Several lines specify several ipv4 addresses.
+              The address is in format x.y.z.t/m,
+              eg. 192.168.1.123/24. The broadcast address should be
+              specified on the same line, right after the ipv4
+              address.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>
+            <option>lxc.network.ipv4.gateway</option>
+          </term>
+          <listitem>
+            <para>
+              specify the ipv4 address to use as the gateway inside the
+              container. The address is in format x.y.z.t, eg.
+              192.168.1.123.
+
+              Can also have the special value <option>auto</option>,
+              which means to take the primary address from the bridge
+              interface (as specified by the
+              <option>lxc.network.link</option> option) and use that as
+              the gateway. <option>auto</option> is only available when
+              using the <option>veth</option> and
+              <option>macvlan</option> network types.
+            </para>
+          </listitem>
+        </varlistentry>
+
+
+        <varlistentry>
+          <term>
+            <option>lxc.network.ipv6</option>
+          </term>
+          <listitem>
+            <para>
+              specify the ipv6 address to assign to the virtualized
+              interface. Several lines specify several ipv6 addresses.
+              The address is in format x::y/m,
+              eg. 2003:db8:1:0:214:1234:fe0b:3596/64
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>
+            <option>lxc.network.ipv6.gateway</option>
+          </term>
+          <listitem>
+            <para>
+              specify the ipv6 address to use as the gateway inside the
+              container. The address is in format x::y,
+              eg. 2003:db8:1:0::1
+
+              Can also have the special value <option>auto</option>,
+              which means to take the primary address from the bridge
+              interface (as specified by the
+              <option>lxc.network.link</option> option) and use that as
+              the gateway. <option>auto</option> is only available when
+              using the <option>veth</option> and
+              <option>macvlan</option> network types.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>
+            <option>lxc.network.script.up</option>
+          </term>
+          <listitem>
+            <para>
+              add a configuration option to specify a script to be
+              executed after creating and configuring the network used
+              from the host side. The following arguments are passed
+              to the script: container name and config section name
+              (net) Additional arguments depend on the config section
+              employing a script hook; the following are used by the
+              network system: execution context (up), network type
+              (empty/veth/macvlan/phys), Depending on the network
+              type, other arguments may be passed:
+              veth/macvlan/phys. And finally (host-sided) device name.
+            </para>
+            <para>
+              Standard output from the script is logged at debug level.
+              Standard error is not logged, but can be captured by the
+              hook redirecting its standard error to standard output.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>
+            <option>lxc.network.script.down</option>
+          </term>
+          <listitem>
+            <para>
+              add a configuration option to specify a script to be
+              executed before destroying the network used from the
+              host side. The following arguments are passed to the
+              script: container name and config section name (net)
+              Additional arguments depend on the config section
+              employing a script hook; the following are used by the
+              network system: execution context (down), network type
+              (empty/veth/macvlan/phys), Depending on the network
+              type, other arguments may be passed:
+              veth/macvlan/phys. And finally (host-sided) device name.
+            </para>
+            <para>
+              Standard output from the script is logged at debug level.
+              Standard error is not logged, but can be captured by the
+              hook redirecting its standard error to standard output.
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
     </refsect2>
 
     <refsect2>
       <title>New pseudo tty instance (devpts)</title>
       <para>
-       For stricter isolation the container can have its own private
-       instance of the pseudo tty.
+        For stricter isolation the container can have its own private
+        instance of the pseudo tty.
       </para>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.pts</option>
-         </term>
-         <listitem>
-           <para>
-             If set, the container will have a new pseudo tty
-             instance, making this private to it. The value specifies
+        <varlistentry>
+          <term>
+            <option>lxc.pts</option>
+          </term>
+          <listitem>
+            <para>
+              If set, the container will have a new pseudo tty
+              instance, making this private to it. The value specifies
               the maximum number of pseudo ttys allowed for a pts
               instance (this limitation is not implemented yet).
-           </para>
-         </listitem>
-       </varlistentry>
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
     </refsect2>
 
     <refsect2>
       <title>Container system console</title>
       <para>
-       If the container is configured with a root filesystem and the
-       inittab file is setup to use the console, you may want to specify
-       where the output of this console goes.
+        If the container is configured with a root filesystem and the
+        inittab file is setup to use the console, you may want to specify
+        where the output of this console goes.
       </para>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.console.logfile</option>
-         </term>
-         <listitem>
-           <para>
-             Specify a path to a file where the console output will
-             be written.
-           </para>
-         </listitem>
-       </varlistentry>
-       <varlistentry>
-         <term>
-           <option>lxc.console</option>
-         </term>
-         <listitem>
-           <para>
-             Specify a path to a device to which the console will be
-             attached.  The keyword 'none' will simply disable the
-             console.  This is dangerous once if have a rootfs with a
-             console device file where the application can write, the
-             messages will fall in the host.
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.console.logfile</option>
+          </term>
+          <listitem>
+            <para>
+              Specify a path to a file where the console output will
+              be written.
+            </para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.console</option>
+          </term>
+          <listitem>
+            <para>
+              Specify a path to a device to which the console will be
+              attached.  The keyword 'none' will simply disable the
+              console.  This is dangerous once if have a rootfs with a
+              console device file where the application can write, the
+              messages will fall in the host.
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
     </refsect2>
 
     <refsect2>
       <title>Console through the ttys</title>
       <para>
-       This option is useful if the container is configured with a root
-       filesystem and the inittab file is setup to launch a getty on the
-       ttys. The option specifies the number of ttys to be available for
-       the container. The number of gettys in the inittab file of the
-       container should not be greater than the number of ttys specified
-       in this option, otherwise the excess getty sessions will die and
-       respawn indefinitely giving annoying messages on the console or in
-       <filename>/var/log/messages</filename>.
+        This option is useful if the container is configured with a root
+        filesystem and the inittab file is setup to launch a getty on the
+        ttys. The option specifies the number of ttys to be available for
+        the container. The number of gettys in the inittab file of the
+        container should not be greater than the number of ttys        specified
+        in this option, otherwise the excess getty sessions will die and
+        respawn indefinitely giving annoying messages on the console or in
+        <filename>/var/log/messages</filename>.
       </para>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.tty</option>
-         </term>
-         <listitem>
-           <para>
-             Specify the number of tty to make available to the
-             container.
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.tty</option>
+          </term>
+          <listitem>
+            <para>
+              Specify the number of tty to make available to the
+              container.
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
     </refsect2>
 
@@ -593,58 +593,58 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
       <title>Console devices location</title>
       <para>
         LXC consoles are provided through Unix98 PTYs created on the
-       host and bind-mounted over the expected devices in the container.
-       By default, they are bind-mounted over <filename>/dev/console</filename>
-       and <filename>/dev/ttyN</filename>.  This can prevent package upgrades
-       in the guest.  Therefore you can specify a directory location (under
-       <filename>/dev</filename> under which LXC will create the files and
-       bind-mount over them.  These will then be symbolically linked to
-       <filename>/dev/console</filename> and <filename>/dev/ttyN</filename>.
-       A package upgrade can then succeed as it is able to remove and replace
-       the symbolic links.
+        host and bind-mounted over the expected devices in the container.
+        By default, they are bind-mounted over <filename>/dev/console</filename>
+        and <filename>/dev/ttyN</filename>.  This can prevent package upgrades
+        in the guest.  Therefore you can specify a directory location (under
+        <filename>/dev</filename> under which LXC will create the files and
+        bind-mount over them.  These will then be symbolically linked to
+        <filename>/dev/console</filename> and <filename>/dev/ttyN</filename>.
+        A package upgrade can then succeed as it is able to remove and replace
+        the symbolic links.
       </para>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.devttydir</option>
-         </term>
-         <listitem>
-           <para>
-             Specify a directory under <filename>/dev</filename>
-             under which to create the container console devices.
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.devttydir</option>
+          </term>
+          <listitem>
+            <para>
+              Specify a directory under <filename>/dev</filename>
+              under which to create the container console devices.
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
     </refsect2>
 
     <refsect2>
       <title>/dev directory</title>
       <para>
-       By default, lxc creates a few symbolic links (fd,stdin,stdout,stderr)
-       in the container's <filename>/dev</filename> directory but does not
-       automatically create device node entries. This allows the container's
-       <filename>/dev</filename> to be set up as needed in the container
-       rootfs.  If lxc.autodev is set to 1, then after mounting the container's
-       rootfs LXC will mount a fresh tmpfs under <filename>/dev</filename>
-       (limited to 100k) and fill in a minimal set of initial devices.
+        By default, lxc creates a few symbolic links (fd,stdin,stdout,stderr)
+        in the container's <filename>/dev</filename> directory but does not
+        automatically create device node entries. This allows the container's
+        <filename>/dev</filename> to be set up as needed in the container
+        rootfs.  If lxc.autodev is set to 1, then after mounting the container's
+        rootfs LXC will mount a fresh tmpfs under <filename>/dev</filename>
+        (limited to 100k) and fill in a minimal set of initial devices.
         This is generally required when starting a container containing
         a "systemd" based "init" but may be optional at other times.  Additional
         devices in the containers /dev directory may be created through the
         use of the <option>lxc.hook.autodev</option> hook.
       </para>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.autodev</option>
-         </term>
-         <listitem>
-           <para>
-             Set this to 1 to have LXC mount and populate a minimal
-             <filename>/dev</filename> when starting the container.
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.autodev</option>
+          </term>
+          <listitem>
+            <para>
+              Set this to 1 to have LXC mount and populate a minimal
+              <filename>/dev</filename> when starting the container.
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
     </refsect2>
 
@@ -670,211 +670,211 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     <refsect2>
       <title>Mount points</title>
       <para>
-       The mount points section specifies the different places to be
-       mounted. These mount points will be private to the container
-       and won't be visible by the processes running outside of the
-       container. This is useful to mount /etc, /var or /home for
-       examples.
+        The mount points section specifies the different places to be
+        mounted. These mount points will be private to the container
+        and won't be visible by the processes running outside of the
+        container. This is useful to mount /etc, /var or /home for
+        examples.
       </para>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.mount</option>
-         </term>
-         <listitem>
-           <para>
-             specify a file location in
-             the <filename>fstab</filename> format, containing the
-             mount information.  The mount target location can and in
-             most cases should be a relative path, which will become
-             relative to the mounted container root.  For instance,
-            </para>
+        <varlistentry>
+          <term>
+            <option>lxc.mount</option>
+          </term>
+          <listitem>
+            <para>
+              specify a file location in
+              the <filename>fstab</filename> format, containing the
+              mount information.  The mount target location can and in
+              most cases should be a relative path, which will become
+              relative to the mounted container root.  For instance,
+             </para>
 <screen>
 proc proc proc nodev,noexec,nosuid 0 0
 </screen>
-            <para>
-             Will mount a proc filesystem under the container's /proc,
-             regardless of where the root filesystem comes from.  This
-             is resilient to block device backed filesystems as well as
-             container cloning.
-            </para>
-            <para>
-             Note that when mounting a filesystem from an
-             image file or block device the third field (fs_vfstype)
-             cannot be auto as with
+             <para>
+              Will mount a proc filesystem under the container's /proc,
+              regardless of where the root filesystem comes from.  This
+              is resilient to block device backed filesystems as well as
+              container cloning.
+             </para>
+             <para>
+              Note that when mounting a filesystem from an
+              image file or block device the third field (fs_vfstype)
+              cannot be auto as with
               <citerefentry>
-               <refentrytitle>mount</refentrytitle>
+                <refentrytitle>mount</refentrytitle>
                 <manvolnum>8</manvolnum>
               </citerefentry>
               but must be explicitly specified.
-           </para>
-         </listitem>
-       </varlistentry>
-
-       <varlistentry>
-         <term>
-           <option>lxc.mount.entry</option>
-         </term>
-         <listitem>
-           <para>
-             specify a mount point corresponding to a line in the
-             fstab format.
-           </para>
-         </listitem>
-       </varlistentry>
-
-       <varlistentry>
-         <term>
-           <option>lxc.mount.auto</option>
-         </term>
-         <listitem>
-           <para>
-             specify which standard kernel file systems should be
-             automatically mounted. This may dramatically simplify
-             the configuration. The file systems are:
-           </para>
-           <itemizedlist>
-             <listitem>
-               <para>
-                 <option>proc:mixed</option> (or <option>proc</option>):
-                 mount <filename>/proc</filename> as read-write, but
-                 remount <filename>/proc/sys</filename> and
-                 <filename>/proc/sysrq-trigger</filename> read-only
-                 for security / container isolation purposes.
-               </para>
-             </listitem>
-             <listitem>
-               <para>
-                 <option>proc:rw</option>: mount
-                 <filename>/proc</filename> as read-write
-               </para>
-             </listitem>
-             <listitem>
-               <para>
-                 <option>sys:ro</option> (or <option>sys</option>):
-                 mount <filename>/sys</filename> as read-only
-                 for security / container isolation purposes.
-               </para>
-             </listitem>
-             <listitem>
-               <para>
-                 <option>sys:rw</option>: mount
-                 <filename>/sys</filename> as read-write
-               </para>
-             </listitem>
-             <listitem>
-               <para>
-                 <option>cgroup:mixed</option>:
-                 mount a tmpfs to <filename>/sys/fs/cgroup</filename>,
-                 create directories for all hierarchies to which
-                 the container is added, create subdirectories
-                 there with the name of the cgroup, and bind-mount
-                 the container's own cgroup into that directory.
-                 The container will be able to write to its own
-                 cgroup directory, but not the parents, since they
-                 will be remounted read-only
-               </para>
-             </listitem>
-             <listitem>
-               <para>
-                 <option>cgroup:ro</option>: similar to
-                 <option>cgroup:mixed</option>, but everything will
-               be mounted read-only.
-               </para>
-             </listitem>
-             <listitem>
-               <para>
-                 <option>cgroup:rw</option>: similar to
-                 <option>cgroup:mixed</option>, but everything will
-                 be mounted read-write. Note that the paths leading
-                 up to the container's own cgroup will be writable,
-                 but will not be a cgroup filesystem but just part
-                 of the tmpfs of <filename>/sys/fs/cgroup</filename>
-               </para>
-             </listitem>
-             <listitem>
-               <para>
-                 <option>cgroup</option> (without specifier):
-                 defaults to <option>cgroup:rw</option> if the
-                 container retains the CAP_SYS_ADMIN capability,
-                 <option>cgroup:mixed</option> otherwise.
-               </para>
-             </listitem>
-             <listitem>
-               <para>
-                 <option>cgroup-full:mixed</option>:
-                 mount a tmpfs to <filename>/sys/fs/cgroup</filename>,
-                 create directories for all hierarchies to which
-                 the container is added, bind-mount the hierarchies
-                 from the host to the container and make everything
-                 read-only except the container's own cgroup. Note
-                 that compared to <option>cgroup</option>, where
-                 all paths leading up to the container's own cgroup
-                 are just simple directories in the underlying
-                 tmpfs, here
-                 <filename>/sys/fs/cgroup/$hierarchy</filename>
-                 will contain the host's full cgroup hierarchy,
-                 albeit read-only outside the container's own cgroup.
-                 This may leak quite a bit of information into the
-                 container.
-               </para>
-             </listitem>
-             <listitem>
-               <para>
-                 <option>cgroup-full:ro</option>: similar to
-                 <option>cgroup-full:mixed</option>, but everything
-                 will be mounted read-only.
-               </para>
-             </listitem>
-             <listitem>
-               <para>
-                 <option>cgroup-full:rw</option>: similar to
-                 <option>cgroup-full:mixed</option>, but everything
-                 will be mounted read-write. Note that in this case,
-                 the container may escape its own cgroup. (Note also
-                 that if the container has CAP_SYS_ADMIN support
-                 and can mount the cgroup filesystem itself, it may
-                 do so anyway.)
-               </para>
-             </listitem>
-             <listitem>
-               <para>
-                 <option>cgroup-full</option> (without specifier):
-                 defaults to <option>cgroup-full:rw</option> if the
-                 container retains the CAP_SYS_ADMIN capability,
-                 <option>cgroup-full:mixed</option> otherwise.
-               </para>
-             </listitem>
-           </itemizedlist>
-           <para>
-             Note that if automatic mounting of the cgroup filesystem
-             is enabled, the tmpfs under
-             <filename>/sys/fs/cgroup</filename> will always be
-             mounted read-write (but for the <option>:mixed</option>
-             and <option>:ro</option> cases, the individual
-             hierarchies,
-             <filename>/sys/fs/cgroup/$hierarchy</filename>, will be
-             read-only). This is in order to work around a quirk in
-             Ubuntu's
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>
+            <option>lxc.mount.entry</option>
+          </term>
+          <listitem>
+            <para>
+              specify a mount point corresponding to a line in the
+              fstab format.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>
+            <option>lxc.mount.auto</option>
+          </term>
+          <listitem>
+            <para>
+              specify which standard kernel file systems should be
+              automatically mounted. This may dramatically simplify
+              the configuration. The file systems are:
+            </para>
+            <itemizedlist>
+              <listitem>
+                <para>
+                  <option>proc:mixed</option> (or <option>proc</option>):
+                  mount <filename>/proc</filename> as read-write, but
+                  remount <filename>/proc/sys</filename> and
+                  <filename>/proc/sysrq-trigger</filename> read-only
+                  for security / container isolation purposes.
+                </para>
+              </listitem>
+              <listitem>
+                <para>
+                  <option>proc:rw</option>: mount
+                  <filename>/proc</filename> as read-write
+                </para>
+              </listitem>
+              <listitem>
+                <para>
+                  <option>sys:ro</option> (or <option>sys</option>):
+                  mount <filename>/sys</filename> as read-only
+                  for security / container isolation purposes.
+                </para>
+              </listitem>
+              <listitem>
+                <para>
+                  <option>sys:rw</option>: mount
+                  <filename>/sys</filename> as read-write
+                </para>
+              </listitem>
+              <listitem>
+                <para>
+                  <option>cgroup:mixed</option>:
+                  mount a tmpfs to <filename>/sys/fs/cgroup</filename>,
+                  create directories for all hierarchies to which
+                  the container is added, create subdirectories
+                  there with the name of the cgroup, and bind-mount
+                  the container's own cgroup into that directory.
+                  The container will be able to write to its own
+                  cgroup directory, but not the parents, since they
+                  will be remounted read-only
+                </para>
+              </listitem>
+              <listitem>
+                <para>
+                  <option>cgroup:ro</option>: similar to
+                  <option>cgroup:mixed</option>, but everything will
+                be mounted read-only.
+                </para>
+              </listitem>
+              <listitem>
+                <para>
+                  <option>cgroup:rw</option>: similar to
+                  <option>cgroup:mixed</option>, but everything will
+                  be mounted read-write. Note that the paths leading
+                  up to the container's own cgroup will be writable,
+                  but will not be a cgroup filesystem but just part
+                  of the tmpfs of <filename>/sys/fs/cgroup</filename>
+                </para>
+              </listitem>
+              <listitem>
+                <para>
+                  <option>cgroup</option> (without specifier):
+                  defaults to <option>cgroup:rw</option> if the
+                  container retains the CAP_SYS_ADMIN capability,
+                  <option>cgroup:mixed</option> otherwise.
+                </para>
+              </listitem>
+              <listitem>
+                <para>
+                  <option>cgroup-full:mixed</option>:
+                  mount a tmpfs to <filename>/sys/fs/cgroup</filename>,
+                  create directories for all hierarchies to which
+                  the container is added, bind-mount the hierarchies
+                  from the host to the container and make everything
+                  read-only except the container's own cgroup. Note
+                  that compared to <option>cgroup</option>, where
+                  all paths leading up to the container's own cgroup
+                  are just simple directories in the underlying
+                  tmpfs, here
+                  <filename>/sys/fs/cgroup/$hierarchy</filename>
+                  will contain the host's full cgroup hierarchy,
+                  albeit read-only outside the container's own cgroup.
+                  This may leak quite a bit of information into the
+                  container.
+                </para>
+              </listitem>
+              <listitem>
+                <para>
+                  <option>cgroup-full:ro</option>: similar to
+                  <option>cgroup-full:mixed</option>, but everything
+                  will be mounted read-only.
+                </para>
+              </listitem>
+              <listitem>
+                <para>
+                  <option>cgroup-full:rw</option>: similar to
+                  <option>cgroup-full:mixed</option>, but everything
+                  will be mounted read-write. Note that in this case,
+                  the container may escape its own cgroup. (Note also
+                  that if the container has CAP_SYS_ADMIN support
+                  and can mount the cgroup filesystem itself, it may
+                  do so anyway.)
+                </para>
+              </listitem>
+              <listitem>
+                <para>
+                  <option>cgroup-full</option> (without specifier):
+                  defaults to <option>cgroup-full:rw</option> if the
+                  container retains the CAP_SYS_ADMIN capability,
+                  <option>cgroup-full:mixed</option> otherwise.
+                </para>
+              </listitem>
+            </itemizedlist>
+            <para>
+              Note that if automatic mounting of the cgroup filesystem
+              is enabled, the tmpfs under
+              <filename>/sys/fs/cgroup</filename> will always be
+              mounted read-write (but for the <option>:mixed</option>
+              and <option>:ro</option> cases, the individual
+              hierarchies,
+              <filename>/sys/fs/cgroup/$hierarchy</filename>, will be
+              read-only). This is in order to work around a quirk in
+              Ubuntu's
               <citerefentry>
-               <refentrytitle>mountall</refentrytitle>
+                <refentrytitle>mountall</refentrytitle>
                 <manvolnum>8</manvolnum>
               </citerefentry>
-             command that will cause containers to wait for user
-             input at boot if
-             <filename>/sys/fs/cgroup</filename> is mounted read-only
-             and the container can't remount it read-write due to a
-             lack of CAP_SYS_ADMIN.
-           </para>
-           <para>
-             Examples:
-           </para>
-           <programlisting>
-             lxc.mount.auto = proc sys cgroup
-             lxc.mount.auto = proc:rw sys:rw cgroup-full:rw
-           </programlisting>
-         </listitem>
-       </varlistentry>
+              command that will cause containers to wait for user
+              input at boot if
+              <filename>/sys/fs/cgroup</filename> is mounted read-only
+              and the container can't remount it read-write due to a
+              lack of CAP_SYS_ADMIN.
+            </para>
+            <para>
+              Examples:
+            </para>
+            <programlisting>
+              lxc.mount.auto = proc sys cgroup
+              lxc.mount.auto = proc:rw sys:rw cgroup-full:rw
+            </programlisting>
+          </listitem>
+        </varlistentry>
 
       </variablelist>
     </refsect2>
@@ -882,189 +882,189 @@ proc proc proc nodev,noexec,nosuid 0 0
     <refsect2>
       <title>Root file system</title>
       <para>
-       The root file system of the container can be different than that
-       of the host system.
+        The root file system of the container can be different than that
+        of the host system.
       </para>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.rootfs</option>
-         </term>
-         <listitem>
-           <para>
-             specify the root file system for the container. It can
-             be an image file, a directory or a block device. If not
-             specified, the container shares its root file system
-             with the host.
-           </para>
-         </listitem>
-       </varlistentry>
-
-       <varlistentry>
-         <term>
-           <option>lxc.rootfs.mount</option>
-         </term>
-         <listitem>
-           <para>
-             where to recursively bind <option>lxc.rootfs</option>
-             before pivoting.  This is to ensure success of the
-             <citerefentry>
-               <refentrytitle><command>pivot_root</command></refentrytitle>
-               <manvolnum>8</manvolnum>
-             </citerefentry>
-             syscall.  Any directory suffices, the default should
-             generally work.
-           </para>
-         </listitem>
-       </varlistentry>
-
-       <varlistentry>
-         <term>
-           <option>lxc.rootfs.options</option>
-         </term>
-         <listitem>
-           <para>
-             extra mount options to use when mounting the rootfs.
-           </para>
-         </listitem>
-       </varlistentry>
-
-       <varlistentry>
-         <term>
-           <option>lxc.pivotdir</option>
-         </term>
-         <listitem>
-           <para>
-             where to pivot the original root file system under
-             <option>lxc.rootfs</option>, specified relatively to
-             that.  The default is <filename>mnt</filename>.
-             It is created if necessary, and also removed after
-             unmounting everything from it during container setup.
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.rootfs</option>
+          </term>
+          <listitem>
+            <para>
+              specify the root file system for the container. It can
+              be an image file, a directory or a block device. If not
+              specified, the container shares its root file system
+              with the host.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>
+            <option>lxc.rootfs.mount</option>
+          </term>
+          <listitem>
+            <para>
+              where to recursively bind <option>lxc.rootfs</option>
+              before pivoting.  This is to ensure success of the
+              <citerefentry>
+                <refentrytitle><command>pivot_root</command></refentrytitle>
+                <manvolnum>8</manvolnum>
+              </citerefentry>
+              syscall.  Any directory suffices, the default should
+              generally work.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>
+            <option>lxc.rootfs.options</option>
+          </term>
+          <listitem>
+            <para>
+              extra mount options to use when mounting the rootfs.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>
+            <option>lxc.pivotdir</option>
+          </term>
+          <listitem>
+            <para>
+              where to pivot the original root file system under
+              <option>lxc.rootfs</option>, specified relatively to
+              that.  The default is <filename>mnt</filename>.
+              It is created if necessary, and also removed after
+              unmounting everything from it during container setup.
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
     </refsect2>
 
     <refsect2>
       <title>Control group</title>
       <para>
-       The control group section contains the configuration for the
-       different subsystem. <command>lxc</command> does not check the
-       correctness of the subsystem name. This has the disadvantage
-       of not detecting configuration errors until the container is
-       started, but has the advantage of permitting any future
-       subsystem.
+        The control group section contains the configuration for the
+        different subsystem. <command>lxc</command> does not check the
+        correctness of the subsystem name. This has the disadvantage
+        of not detecting configuration errors until the container is
+        started, but has the advantage of permitting any future
+        subsystem.
       </para>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.cgroup.[subsystem name]</option>
-         </term>
-         <listitem>
-           <para>
-             specify the control group value to be set.  The
-             subsystem name is the literal name of the control group
-             subsystem.  The permitted names and the syntax of their
-             values is not dictated by LXC, instead it depends on the
-             features of the Linux kernel running at the time the
-             container is started,
-             eg. <option>lxc.cgroup.cpuset.cpus</option>
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.cgroup.[subsystem name]</option>
+          </term>
+          <listitem>
+            <para>
+              specify the control group value to be set.  The
+              subsystem name is the literal name of the control group
+              subsystem.  The permitted names and the syntax of their
+              values is not dictated by LXC, instead it depends on the
+              features of the Linux kernel running at the time the
+              container is started,
+              eg. <option>lxc.cgroup.cpuset.cpus</option>
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
     </refsect2>
 
     <refsect2>
       <title>Capabilities</title>
       <para>
-       The capabilities can be dropped in the container if this one
-       is run as root.
+        The capabilities can be dropped in the container if this one
+        is run as root.
       </para>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.cap.drop</option>
-         </term>
-         <listitem>
-           <para>
-             Specify the capability to be dropped in the container. A
-             single line defining several capabilities with a space
-             separation is allowed. The format is the lower case of
-             the capability definition without the "CAP_" prefix,
-             eg. CAP_SYS_MODULE should be specified as
-             sys_module. See
-             <citerefentry>
-               <refentrytitle><command>capabilities</command></refentrytitle>
-               <manvolnum>7</manvolnum>
-             </citerefentry>,
-           </para>
-         </listitem>
-       </varlistentry>
-       <varlistentry>
-         <term>
-           <option>lxc.cap.keep</option>
-         </term>
-         <listitem>
-           <para>
-             Specify the capability to be kept in the container. All other
-             capabilities will be dropped.
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.cap.drop</option>
+          </term>
+          <listitem>
+            <para>
+              Specify the capability to be dropped in the container. A
+              single line defining several capabilities with a space
+              separation is allowed. The format is the lower case of
+              the capability definition without the "CAP_" prefix,
+              eg. CAP_SYS_MODULE should be specified as
+              sys_module. See
+              <citerefentry>
+                <refentrytitle><command>capabilities</command></refentrytitle>
+                <manvolnum>7</manvolnum>
+              </citerefentry>,
+            </para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.cap.keep</option>
+          </term>
+          <listitem>
+            <para>
+              Specify the capability to be kept in the container. All other
+              capabilities will be dropped.
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
     </refsect2>
 
     <refsect2>
       <title>Apparmor profile</title>
       <para>
-       If lxc was compiled and installed with apparmor support, and the host
-       system has apparmor enabled, then the apparmor profile under which the
-       container should be run can be specified in the container
-       configuration.  The default is <command>lxc-container-default</command>.
+        If lxc was compiled and installed with apparmor support, and the host
+        system has apparmor enabled, then the apparmor profile under which the
+        container should be run can be specified in the container
+        configuration.  The default is <command>lxc-container-default</command>.
       </para>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.aa_profile</option>
-         </term>
-         <listitem>
-           <para>
-             Specify the apparmor profile under which the container should
-             be run.  To specify that the container should be unconfined,
-             use
-           </para>
-             <programlisting>lxc.aa_profile = unconfined</programlisting>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.aa_profile</option>
+          </term>
+          <listitem>
+            <para>
+              Specify the apparmor profile under which the container should
+              be run.  To specify that the container should be unconfined,
+              use
+            </para>
+              <programlisting>lxc.aa_profile = unconfined</programlisting>
+          </listitem>
+        </varlistentry>
       </variablelist>
     </refsect2>
 
     <refsect2>
       <title>SELinux context</title>
       <para>
-       If lxc was compiled and installed with SELinux support, and the host
-       system has SELinux enabled, then the SELinux context under which the
-       container should be run can be specified in the container
-       configuration.  The default is <command>unconfined_t</command>,
-       which means that lxc will not attempt to change contexts.
-       See @DATADIR@/lxc/selinux/lxc.te for an example policy and more
-       information.
+        If lxc was compiled and installed with SELinux support, and the host
+        system has SELinux enabled, then the SELinux context under which the
+        container should be run can be specified in the container
+        configuration.  The default is <command>unconfined_t</command>,
+        which means that lxc will not attempt to change contexts.
+        See @DATADIR@/lxc/selinux/lxc.te for an example policy and more
+        information.
       </para>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.se_context</option>
-         </term>
-         <listitem>
-           <para>
-             Specify the SELinux context under which the container should
-             be run or <command>unconfined_t</command>. For example
-           </para>
-           <programlisting>lxc.se_context = system_u:system_r:lxc_t:s0:c22</programlisting>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.se_context</option>
+          </term>
+          <listitem>
+            <para>
+              Specify the SELinux context under which the container should
+              be run or <command>unconfined_t</command>. For example
+            </para>
+            <programlisting>lxc.se_context = system_u:system_r:lxc_t:s0:c22</programlisting>
+          </listitem>
+        </varlistentry>
       </variablelist>
     </refsect2>
 
@@ -1072,17 +1072,17 @@ proc proc proc nodev,noexec,nosuid 0 0
       <title>Seccomp configuration</title>
       <para>
         A container can be started with a reduced set of available
-       system calls by loading a seccomp profile at startup.  The
-       seccomp configuration file must begin with a version number
-       on the first line, a policy type on the second line, followed
-       by the configuration.
+        system calls by loading a seccomp profile at startup.  The
+        seccomp configuration file must begin with a version number
+        on the first line, a policy type on the second line, followed
+        by the configuration.
       </para>
       <para>
         Versions 1 and 2 are currently supported.  In version 1, the
-       policy is a simple whitelist.  The second line therefore must
-       read "whitelist", with the rest of the file containing one (numeric)
-       sycall number per line.  Each syscall number is whitelisted,
-       while every unlisted number is blacklisted for use in the container
+        policy is a simple whitelist.  The second line therefore must
+        read "whitelist", with the rest of the file containing one (numeric)
+        sycall number per line.  Each syscall number is whitelisted,
+        while every unlisted number is blacklisted for use in the container
       </para>
 
       <para>
@@ -1101,17 +1101,17 @@ blacklist
 mknod errno 0
 </screen>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.seccomp</option>
-         </term>
-         <listitem>
-           <para>
-             Specify a file containing the seccomp configuration to
-             load before the container starts.
-            </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.seccomp</option>
+          </term>
+          <listitem>
+            <para>
+              Specify a file containing the seccomp configuration to
+              load before the container starts.
+             </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
     </refsect2>
 
@@ -1119,30 +1119,30 @@ mknod errno 0
       <title>UID mappings</title>
       <para>
         A container can be started in a private user namespace with
-       user and group id mappings.  For instance, you can map userid
-       0 in the container to userid 200000 on the host.  The root
-       user in the container will be privileged in the container,
-       but unprivileged on the host.  Normally a system container
-       will want a range of ids, so you would map, for instance,
-       user and group ids 0 through 20,000 in the container to the
-       ids 200,000 through 220,000.
+        user and group id mappings.  For instance, you can map userid
+        0 in the container to userid 200000 on the host.  The root
+        user in the container will be privileged in the container,
+        but unprivileged on the host.  Normally a system container
+        will want a range of ids, so you would map, for instance,
+        user and group ids 0 through 20,000 in the container to the
+        ids 200,000 through 220,000.
       </para>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.id_map</option>
-         </term>
-         <listitem>
-           <para>
-             Four values must be provided.  First a character, either
-             'u', or 'g', to specify whether user or group ids are
-             being mapped.  Next is the first userid as seen in the
-             user namespace of the container.  Next is the userid as
-             seen on the host.  Finally, a range indicating the number
-             of consecutive ids to map.
-            </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.id_map</option>
+          </term>
+          <listitem>
+            <para>
+              Four values must be provided.  First a character, either
+              'u', or 'g', to specify whether user or group ids are
+              being mapped.  Next is the first userid as seen in the
+              user namespace of the container.  Next is the userid as
+              seen on the host.  Finally, a range indicating the number
+              of consecutive ids to map.
+             </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
     </refsect2>
 
@@ -1150,28 +1150,28 @@ mknod errno 0
       <title>Container hooks</title>
       <para>
         Container hooks are programs or scripts which can be executed
-       at various times in a container's lifetime.
+        at various times in a container's lifetime.
       </para>
       <para>
         When a container hook is executed, information is passed both
-       as command line arguments and through environment variables.
-       The arguments are:
-       <itemizedlist>
-         <listitem><para> Container name. </para></listitem>
-         <listitem><para> Section (always 'lxc'). </para></listitem>
-         <listitem><para> The hook type (i.e. 'clone' or 'pre-mount'). </para></listitem>
-         <listitem><para> Additional arguments In the
-         case of the clone hook, any extra arguments passed to
-         lxc-clone will appear as further arguments to the hook. </para></listitem>
-       </itemizedlist>
-       The following environment variables are set:
-       <itemizedlist>
-         <listitem><para> LXC_NAME: is the container's name. </para></listitem>
-         <listitem><para> LXC_ROOTFS_MOUNT: the path to the mounted root filesystem. </para></listitem>
-         <listitem><para> LXC_CONFIG_FILE: the path to the container configuration file. </para></listitem>
-         <listitem><para> LXC_SRC_NAME: in the case of the clone hook, this is the original container's name. </para></listitem>
-         <listitem><para> LXC_ROOTFS_PATH: this is the lxc.rootfs entry for the container.  Note this is likely not where the mounted rootfs is to be found, use LXC_ROOTFS_MOUNT for that. </para></listitem>
-       </itemizedlist>
+        as command line arguments and through environment variables.
+        The arguments are:
+        <itemizedlist>
+          <listitem><para> Container name. </para></listitem>
+          <listitem><para> Section (always 'lxc'). </para></listitem>
+          <listitem><para> The hook type (i.e. 'clone' or 'pre-mount'). </para></listitem>
+          <listitem><para> Additional arguments In the
+          case of the clone hook, any extra arguments passed to
+          lxc-clone will appear as further arguments to the hook. </para></listitem>
+        </itemizedlist>
+        The following environment variables are set:
+        <itemizedlist>
+          <listitem><para> LXC_NAME: is the container's name. </para></listitem>
+          <listitem><para> LXC_ROOTFS_MOUNT: the path to the mounted root filesystem. </para></listitem>
+          <listitem><para> LXC_CONFIG_FILE: the path to the container configuration file. </para></listitem>
+          <listitem><para> LXC_SRC_NAME: in the case of the clone hook, this is the original container's name. </para></listitem>
+          <listitem><para> LXC_ROOTFS_PATH: this is the lxc.rootfs entry for the container.  Note this is likely not where the mounted rootfs is to be found, use LXC_ROOTFS_MOUNT for that. </para></listitem>
+        </itemizedlist>
       </para>
       <para>
         Standard output from the hooks is logged at debug level.
@@ -1179,109 +1179,109 @@ mknod errno 0
         hook redirecting its standard error to standard output.
       </para>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.hook.pre-start</option>
-         </term>
-         <listitem>
-           <para>
-             A hook to be run in the host's namespace before the
-             container ttys, consoles, or mounts are up.
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.hook.pre-start</option>
+          </term>
+          <listitem>
+            <para>
+              A hook to be run in the host's namespace before the
+              container ttys, consoles, or mounts are up.
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.hook.pre-mount</option>
-         </term>
-         <listitem>
-           <para>
-             A hook to be run in the container's fs namespace but before
-             the rootfs has been set up.  This allows for manipulation
-             of the rootfs, i.e. to mount an encrypted filesystem.  Mounts
-             done in this hook will not be reflected on the host (apart from
-             mounts propagation), so they will be automatically cleaned up
-             when the container shuts down.
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.hook.pre-mount</option>
+          </term>
+          <listitem>
+            <para>
+              A hook to be run in the container's fs namespace but before
+              the rootfs has been set up.  This allows for manipulation
+              of the rootfs, i.e. to mount an encrypted filesystem.  Mounts
+              done in this hook will not be reflected on the host (apart from
+              mounts propagation), so they will be automatically cleaned up
+              when the container shuts down.
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.hook.mount</option>
-         </term>
-         <listitem>
-           <para>
-             A hook to be run in the container's namespace after
-             mounting has been done, but before the pivot_root.
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.hook.mount</option>
+          </term>
+          <listitem>
+            <para>
+              A hook to be run in the container's namespace after
+              mounting has been done, but before the pivot_root.
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.hook.autodev</option>
-         </term>
-         <listitem>
-           <para>
-             A hook to be run in the container's namespace after
-             mounting has been done and after any mount hooks have
-             run, but before the pivot_root, if
-             <option>lxc.autodev</option> == 1.
-             The purpose of this hook is to assist in populating the
-             /dev directory of the container when using the autodev
-             option for systemd based containers.  The container's /dev
-             directory is relative to the
-             ${<option>LXC_ROOTFS_MOUNT</option>} environment
-             variable available when the hook is run.
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.hook.autodev</option>
+          </term>
+          <listitem>
+            <para>
+              A hook to be run in the container's namespace after
+              mounting has been done and after any mount hooks have
+              run, but before the pivot_root, if
+              <option>lxc.autodev</option> == 1.
+              The purpose of this hook is to assist in populating the
+              /dev directory of the container when using the autodev
+              option for systemd based containers.  The container's /dev
+              directory is relative to the
+              ${<option>LXC_ROOTFS_MOUNT</option>} environment
+              variable available when the hook is run.
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.hook.start</option>
-         </term>
-         <listitem>
-           <para>
-             A hook to be run in the container's namespace immediately
-             before executing the container's init.  This requires the
-             program to be available in the container.
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.hook.start</option>
+          </term>
+          <listitem>
+            <para>
+              A hook to be run in the container's namespace immediately
+              before executing the container's init.  This requires the
+              program to be available in the container.
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.hook.post-stop</option>
-         </term>
-         <listitem>
-           <para>
-             A hook to be run in the host's namespace after the
-             container has been shut down.
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.hook.post-stop</option>
+          </term>
+          <listitem>
+            <para>
+              A hook to be run in the host's namespace after the
+              container has been shut down.
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.hook.clone</option>
-         </term>
-         <listitem>
-           <para>
-             A hook to be run when the container is cloned to a new one.
-             See <citerefentry><refentrytitle><command>lxc-clone</command></refentrytitle>
-             <manvolnum>1</manvolnum></citerefentry> for more information.
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.hook.clone</option>
+          </term>
+          <listitem>
+            <para>
+              A hook to be run when the container is cloned to a new one.
+              See <citerefentry><refentrytitle><command>lxc-clone</command></refentrytitle>
+              <manvolnum>1</manvolnum></citerefentry> for more information.
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
     </refsect2>
 
@@ -1295,89 +1295,89 @@ mknod errno 0
         and, as such, not valid during the <option>lxc.hook.start</option> hook.
       </para>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>LXC_NAME</option>
-         </term>
-         <listitem>
-           <para>
-             The LXC name of the container.  Useful for logging messages
-             in common log environments.  [<option>-n</option>]
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>LXC_NAME</option>
+          </term>
+          <listitem>
+            <para>
+              The LXC name of the container.  Useful for logging messages
+              in common log environments.  [<option>-n</option>]
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>LXC_CONFIG_FILE</option>
-         </term>
-         <listitem>
-           <para>
-             Host relative path to the container configuration file.  This
-             gives the container to reference the original, top level,
-             configuration file for the container in order to locate any
-             additional configuration information not otherwise made
-             available.  [<option>-f</option>]
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>LXC_CONFIG_FILE</option>
+          </term>
+          <listitem>
+            <para>
+              Host relative path to the container configuration file.  This
+              gives the container to reference the original, top level,
+              configuration file for the container in order to locate any
+              additional configuration information not otherwise made
+              available.  [<option>-f</option>]
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>LXC_CONSOLE</option>
-         </term>
-         <listitem>
-           <para>
-             The path to the console output of the container if not NULL.
-             [<option>-c</option>] [<option>lxc.console</option>]
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>LXC_CONSOLE</option>
+          </term>
+          <listitem>
+            <para>
+              The path to the console output of the container if not NULL.
+              [<option>-c</option>] [<option>lxc.console</option>]
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>LXC_CONSOLE_LOGPATH</option>
-         </term>
-         <listitem>
-           <para>
-             The path to the console log output of the container if not NULL.
-             [<option>-L</option>]
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>LXC_CONSOLE_LOGPATH</option>
+          </term>
+          <listitem>
+            <para>
+              The path to the console log output of the container if not NULL.
+              [<option>-L</option>]
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>LXC_ROOTFS_MOUNT</option>
-         </term>
-         <listitem>
-           <para>
-             The mount location to which the container is initially bound.
-             This will be the host relative path to the container rootfs
-             for the container instance being started and is where changes
-             should be made for that instance.
-             [<option>lxc.rootfs.mount</option>]
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>LXC_ROOTFS_MOUNT</option>
+          </term>
+          <listitem>
+            <para>
+              The mount location to which the container is initially bound.
+              This will be the host relative path to the container rootfs
+              for the container instance being started and is where changes
+              should be made for that instance.
+              [<option>lxc.rootfs.mount</option>]
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>LXC_ROOTFS_PATH</option>
-         </term>
-         <listitem>
-           <para>
-             The host relative path to the container root which has been
-             mounted to the rootfs.mount location.
-             [<option>lxc.rootfs</option>]
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>LXC_ROOTFS_PATH</option>
+          </term>
+          <listitem>
+            <para>
+              The host relative path to the container root which has been
+              mounted to the rootfs.mount location.
+              [<option>lxc.rootfs</option>]
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
 
     </refsect2>
@@ -1397,36 +1397,36 @@ mknod errno 0
       command line options to <command>lxc-start</command>.
     </para>
       <variablelist>
-       <varlistentry>
-         <term>
-           <option>lxc.loglevel</option>
-         </term>
-         <listitem>
-           <para>
-           The level at which to log.  The log level is an integer in
-           the range of 0..8 inclusive, where a lower number means more
-           verbose debugging.  In particular 0 = trace, 1 = debug, 2 =
-           info, 3 = notice, 4 = warn, 5 = error, 6 = critical, 7 =
-           alert, and 8 = fatal.  If unspecified, the level defaults
-           to 5 (error), so that only errors and above are logged.
-           </para>
-           <para>
-           Note that when a script (such as either a hook script or a
-           network interface up or down script) is called, the script's
-           standard output is logged at level 1, debug.
-           </para>
-         </listitem>
-       </varlistentry>
-       <varlistentry>
-         <term>
-           <option>lxc.logfile</option>
-         </term>
-         <listitem>
-           <para>
-           The file to which logging info should be written.
-           </para>
-         </listitem>
-       </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.loglevel</option>
+          </term>
+          <listitem>
+            <para>
+            The level at which to log.  The log level is an integer in
+            the range of 0..8 inclusive, where a lower number means more
+            verbose debugging.  In particular 0 = trace, 1 = debug, 2 =
+            info, 3 = notice, 4 = warn, 5 = error, 6 = critical, 7 =
+            alert, and 8 = fatal.  If unspecified, the level defaults
+            to 5 (error), so that only errors and above are logged.
+            </para>
+            <para>
+            Note that when a script (such as either a hook script or a
+            network interface up or down script) is called, the script's
+            standard output is logged at level 1, debug.
+            </para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term>
+            <option>lxc.logfile</option>
+          </term>
+          <listitem>
+            <para>
+            The file to which logging info should be written.
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
     </refsect2>
 
@@ -1515,25 +1515,25 @@ mknod errno 0
   <refsect1>
     <title>Examples</title>
       <para>
-       In addition to the few examples given below, you will find
-       some other examples of configuration file in @DOCDIR@/examples
+        In addition to the few examples given below, you will find
+        some other examples of configuration file in @DOCDIR@/examples
       </para>
     <refsect2>
       <title>Network</title>
       <para>This configuration sets up a container to use a veth pair
-       device with one side plugged to a bridge br0 (which has been
-       configured before on the system by the administrator). The
-       virtual network device visible in the container is renamed to
-       eth0.</para>
+        device with one side plugged to a bridge br0 (which has been
+        configured before on the system by the administrator). The
+        virtual network device visible in the container is renamed to
+        eth0.</para>
       <programlisting>
-       lxc.utsname = myhostname
-       lxc.network.type = veth
-       lxc.network.flags = up
-       lxc.network.link = br0
-       lxc.network.name = eth0
-       lxc.network.hwaddr = 4a:49:43:49:79:bf
-       lxc.network.ipv4 = 10.2.3.5/24 10.2.3.255
-       lxc.network.ipv6 = 2003:db8:1:0:214:1234:fe0b:3597
+        lxc.utsname = myhostname
+        lxc.network.type = veth
+        lxc.network.flags = up
+        lxc.network.link = br0
+        lxc.network.name = eth0
+        lxc.network.hwaddr = 4a:49:43:49:79:bf
+        lxc.network.ipv4 = 10.2.3.5/24 10.2.3.255
+        lxc.network.ipv6 = 2003:db8:1:0:214:1234:fe0b:3597
       </programlisting>
     </refsect2>
 
@@ -1543,8 +1543,8 @@ mknod errno 0
         range 0-9999 in the container to the ids 100000-109999 on the host.
       </para>
       <programlisting>
-       lxc.id_map = u 0 100000 10000
-       lxc.id_map = g 0 100000 10000
+        lxc.id_map = u 0 100000 10000
+        lxc.id_map = g 0 100000 10000
       </programlisting>
     </refsect2>
 
@@ -1555,11 +1555,11 @@ mknod errno 0
       cpus.share prioritize the control group, devices.allow makes
       usable the specified devices.</para>
       <programlisting>
-       lxc.cgroup.cpuset.cpus = 0,1
-       lxc.cgroup.cpu.shares = 1234
-       lxc.cgroup.devices.deny = a
-       lxc.cgroup.devices.allow = c 1:3 rw
-       lxc.cgroup.devices.allow = b 8:0 rw
+        lxc.cgroup.cpuset.cpus = 0,1
+        lxc.cgroup.cpu.shares = 1234
+        lxc.cgroup.devices.deny = a
+        lxc.cgroup.devices.allow = c 1:3 rw
+        lxc.cgroup.devices.allow = b 8:0 rw
       </programlisting>
     </refsect2>
 
@@ -1569,37 +1569,37 @@ mknod errno 0
       network stack, using the control groups, setting a new hostname,
       mounting some locations and a changing root file system.</para>
       <programlisting>
-       lxc.utsname = complex
-       lxc.network.type = veth
-       lxc.network.flags = up
-       lxc.network.link = br0
-       lxc.network.hwaddr = 4a:49:43:49:79:bf
-       lxc.network.ipv4 = 10.2.3.5/24 10.2.3.255
-       lxc.network.ipv6 = 2003:db8:1:0:214:1234:fe0b:3597
-       lxc.network.ipv6 = 2003:db8:1:0:214:5432:feab:3588
-       lxc.network.type = macvlan
-       lxc.network.flags = up
-       lxc.network.link = eth0
-       lxc.network.hwaddr = 4a:49:43:49:79:bd
-       lxc.network.ipv4 = 10.2.3.4/24
-       lxc.network.ipv4 = 192.168.10.125/24
-       lxc.network.ipv6 = 2003:db8:1:0:214:1234:fe0b:3596
-       lxc.network.type = phys
-       lxc.network.flags = up
-       lxc.network.link = dummy0
-       lxc.network.hwaddr = 4a:49:43:49:79:ff
-       lxc.network.ipv4 = 10.2.3.6/24
-       lxc.network.ipv6 = 2003:db8:1:0:214:1234:fe0b:3297
-       lxc.cgroup.cpuset.cpus = 0,1
-       lxc.cgroup.cpu.shares = 1234
-       lxc.cgroup.devices.deny = a
-       lxc.cgroup.devices.allow = c 1:3 rw
-       lxc.cgroup.devices.allow = b 8:0 rw
-       lxc.mount = /etc/fstab.complex
-       lxc.mount.entry = /lib /root/myrootfs/lib none ro,bind 0 0
-       lxc.rootfs = /mnt/rootfs.complex
-       lxc.cap.drop = sys_module mknod setuid net_raw
-       lxc.cap.drop = mac_override
+        lxc.utsname = complex
+        lxc.network.type = veth
+        lxc.network.flags = up
+        lxc.network.link = br0
+        lxc.network.hwaddr = 4a:49:43:49:79:bf
+        lxc.network.ipv4 = 10.2.3.5/24 10.2.3.255
+        lxc.network.ipv6 = 2003:db8:1:0:214:1234:fe0b:3597
+        lxc.network.ipv6 = 2003:db8:1:0:214:5432:feab:3588
+        lxc.network.type = macvlan
+        lxc.network.flags = up
+        lxc.network.link = eth0
+        lxc.network.hwaddr = 4a:49:43:49:79:bd
+        lxc.network.ipv4 = 10.2.3.4/24
+        lxc.network.ipv4 = 192.168.10.125/24
+        lxc.network.ipv6 = 2003:db8:1:0:214:1234:fe0b:3596
+        lxc.network.type = phys
+        lxc.network.flags = up
+        lxc.network.link = dummy0
+        lxc.network.hwaddr = 4a:49:43:49:79:ff
+        lxc.network.ipv4 = 10.2.3.6/24
+        lxc.network.ipv6 = 2003:db8:1:0:214:1234:fe0b:3297
+        lxc.cgroup.cpuset.cpus = 0,1
+        lxc.cgroup.cpu.shares = 1234
+        lxc.cgroup.devices.deny = a
+        lxc.cgroup.devices.allow = c 1:3 rw
+        lxc.cgroup.devices.allow = b 8:0 rw
+        lxc.mount = /etc/fstab.complex
+        lxc.mount.entry = /lib /root/myrootfs/lib none ro,bind 0 0
+        lxc.rootfs = /mnt/rootfs.complex
+        lxc.cap.drop = sys_module mknod setuid net_raw
+        lxc.cap.drop = mac_override
       </programlisting>
     </refsect2>
 
@@ -1609,23 +1609,23 @@ mknod errno 0
     <title>See Also</title>
     <simpara>
       <citerefentry>
-       <refentrytitle><command>chroot</command></refentrytitle>
-       <manvolnum>1</manvolnum>
+        <refentrytitle><command>chroot</command></refentrytitle>
+        <manvolnum>1</manvolnum>
       </citerefentry>,
 
       <citerefentry>
-       <refentrytitle><command>pivot_root</command></refentrytitle>
-       <manvolnum>8</manvolnum>
+        <refentrytitle><command>pivot_root</command></refentrytitle>
+        <manvolnum>8</manvolnum>
       </citerefentry>,
 
       <citerefentry>
-       <refentrytitle><filename>fstab</filename></refentrytitle>
-       <manvolnum>5</manvolnum>
+        <refentrytitle><filename>fstab</filename></refentrytitle>
+        <manvolnum>5</manvolnum>
       </citerefentry>,
 
       <citerefentry>
-       <refentrytitle><filename>capabilities</filename></refentrytitle>
-       <manvolnum>7</manvolnum>
+        <refentrytitle><filename>capabilities</filename></refentrytitle>
+        <manvolnum>7</manvolnum>
       </citerefentry>
     </simpara>
   </refsect1>
index 85cd31a..1bafaf2 100644 (file)
@@ -135,35 +135,20 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
       <para>
 
-       The kernel version >= 2.6.27 shipped with the distros, will
+       The kernel version >= 2.6.32 shipped with the distros, will
        work with <command>lxc</command>, this one will have less
        functionalities but enough to be interesting.
 
-       With the kernel 2.6.29, <command>lxc</command> is fully
-       functional.
-
        The helper script <command>lxc-checkconfig</command> will give
        you information about your kernel configuration.
       </para>
 
       <para>
-       Before using the <command>lxc</command>, your system should be
-       configured with the file capabilities, otherwise you will need
-       to run the <command>lxc</command> commands as root.
-      </para>
-
-      <para>
          The control group can be mounted anywhere, eg:
          <command>mount -t cgroup cgroup /cgroup</command>.
 
-         If you want to dedicate a specific cgroup mount point
-         for <command>lxc</command>, that is to have different cgroups
-         mounted at different places with different options but
-         let <command>lxc</command> to use one location, you can bind
-         the mount point with the <option>lxc</option> name, eg:
-         <command>mount -t cgroup lxc /cgroup4lxc</command> or
-         <command>mount -t cgroup -ons,cpuset,freezer,devices
-         lxc /cgroup4lxc</command>
+         It is however recommended to use cgmanager, cgroup-lite or systemd
+         to mount the cgroup hierarchy under /sys/fs/cgroup.
 
       </para>
 
index 6415f82..ab0b322 100644 (file)
--- a/lxc.spec
+++ b/lxc.spec
@@ -45,7 +45,7 @@ BuildRequires: systemd-units
 %endif
 
 Name: lxc
-Version: 1.0.6
+Version: 1.0.7
 Release: %{?beta_rel:0.1.%{beta_rel}}%{?!beta_rel:%{norm_rel}}%{?dist}
 URL: http://linuxcontainers.org
 Source: http://linuxcontainers.org/downloads/%{name}-%{version}%{?beta_dot}.tar.gz
@@ -178,7 +178,7 @@ rm -rf %{buildroot}
 %changelog
 * Tue Oct 22 2013 Dwight Engen <dwight.engen@oracle.com> - 1.0.0-0.1.alpha2
 - fix some rpmlint warnings/errors
-- split lua bits into seperate package
+- split lua bits into separate package
 
 * Mon Sep 10 2012 Dwight Engen <dwight.engen@oracle.com> - 0.8.0
 - fix lxc-init moved to libexec
index 57912a1..4477033 100644 (file)
@@ -178,7 +178,7 @@ rm -rf %{buildroot}
 %changelog
 * Tue Oct 22 2013 Dwight Engen <dwight.engen@oracle.com> - 1.0.0-0.1.alpha2
 - fix some rpmlint warnings/errors
-- split lua bits into seperate package
+- split lua bits into separate package
 
 * Mon Sep 10 2012 Dwight Engen <dwight.engen@oracle.com> - 0.8.0
 - fix lxc-init moved to libexec
index 923c497..ed6ea8d 100644 (file)
@@ -336,23 +336,8 @@ static int lxc_attach_set_environment(enum lxc_attach_env_policy_t policy, char*
                 * number of C programs out there that just assume
                 * that getenv("PATH") is never NULL and then die a
                 * painful segfault death. */
-               if (!path_kept) {
-#ifdef HAVE_CONFSTR
-                       size_t n;
-                       char *path_env;
-
-                       n = confstr(_CS_PATH, NULL, 0);
-                       path_env = malloc(n);
-                       if (path_env) {
-                               confstr(_CS_PATH, path_env, n);
-                               setenv("PATH", path_env, 1);
-                               free(path_env);
-                       }
-                       /* don't error out, this is just an extra service */
-#else
+               if (!path_kept)
                        setenv("PATH", "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 1);
-#endif
-               }
        }
 
        if (putenv("container=lxc")) {
@@ -744,7 +729,7 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
        if (pid) {
                pid_t to_cleanup_pid = pid;
 
-               /* inital thread, we close the socket that is for the
+               /* initial thread, we close the socket that is for the
                 * subprocesses
                 */
                close(ipc_sockets[1]);
@@ -773,8 +758,10 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
                }
 
                /* ignore SIGKILL (CTRL-C) and SIGQUIT (CTRL-\) - issue #313 */
-               signal(SIGINT, SIG_IGN);
-               signal(SIGQUIT, SIG_IGN);
+               if (options->stdin_fd == 0) {
+                       signal(SIGINT, SIG_IGN);
+                       signal(SIGQUIT, SIG_IGN);
+               }
 
                /* reap intermediate process */
                ret = wait_for_pid(pid);
index b035318..3c54e7c 100644 (file)
@@ -86,7 +86,7 @@ typedef struct lxc_attach_options_t {
         */
        long personality;
 
-       /*! Inital current directory, use \c NULL to use cwd.
+       /*! Initial current directory, use \c NULL to use cwd.
         * If the current directory does not exist in the container, the
         * root directory will be used instead because of kernel defaults.
         */
index 449aca2..7f00da8 100644 (file)
@@ -23,7 +23,7 @@
 
 /*
  * this is all just a first shot for experiment.  If we go this route, much
- * shoudl change.  bdev should be a directory with per-bdev file.  Things which
+ * should change.  bdev should be a directory with per-bdev file.  Things which
  * I'm doing by calling out to userspace should sometimes be done through
  * libraries like liblvm2
  */
@@ -1418,7 +1418,7 @@ static int btrfs_snapshot(const char *orig, const char *new)
                goto out;
        }
        // make sure the directory doesn't already exist
-       if (rmdir(newfull) < 0 && errno != -ENOENT) {
+       if (rmdir(newfull) < 0 && errno != ENOENT) {
                SYSERROR("Error removing empty new rootfs");
                goto out;
        }
@@ -1511,7 +1511,7 @@ static int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *old
                return userns_exec_1(conf, btrfs_snapshot_wrapper, &sdata);
        }
 
-       if (rmdir(new->dest) < 0 && errno != -ENOENT) {
+       if (rmdir(new->dest) < 0 && errno != ENOENT) {
                SYSERROR("removing %s", new->dest);
                return -1;
        }
@@ -2153,10 +2153,12 @@ static int overlayfs_detect(const char *path)
 static int overlayfs_mount(struct bdev *bdev)
 {
        char *options, *dup, *lower, *upper;
-       int len;
+       char *options_work, *work, *lastslash;
+       int lastslashidx;
+       int len, len2;
        unsigned long mntflags;
        char *mntdata;
-       int ret;
+       int ret, ret2;
 
        if (strcmp(bdev->type, "overlayfs"))
                return -22;
@@ -2174,6 +2176,19 @@ static int overlayfs_mount(struct bdev *bdev)
        *upper = '\0';
        upper++;
 
+       // overlayfs.v22 or higher needs workdir option
+       // if upper is /var/lib/lxc/c2/delta0,
+       // then workdir is /var/lib/lxc/c2/olwork
+       lastslash = strrchr(upper, '/');
+       if (!lastslash)
+               return -22;
+       lastslash++;
+       lastslashidx = lastslash - upper;
+
+       work = alloca(lastslashidx + 7);
+       strncpy(work, upper, lastslashidx+7);
+       strcpy(work+lastslashidx, "olwork");
+
        if (parse_mntopts(bdev->mntopts, &mntflags, &mntdata) < 0) {
                free(mntdata);
                return -22;
@@ -2186,21 +2201,44 @@ static int overlayfs_mount(struct bdev *bdev)
                len = strlen(lower) + strlen(upper) + strlen("upperdir=,lowerdir=,") + strlen(mntdata) + 1;
                options = alloca(len);
                ret = snprintf(options, len, "upperdir=%s,lowerdir=%s,%s", upper, lower, mntdata);
+
+               len2 = strlen(lower) + strlen(upper) + strlen(work)
+                       + strlen("upperdir=,lowerdir=,workdir=") + strlen(mntdata) + 1;
+               options_work = alloca(len2);
+               ret2 = snprintf(options, len2, "upperdir=%s,lowerdir=%s,workdir=%s,%s",
+                               upper, lower, work, mntdata);
        }
        else {
                len = strlen(lower) + strlen(upper) + strlen("upperdir=,lowerdir=") + 1;
                options = alloca(len);
                ret = snprintf(options, len, "upperdir=%s,lowerdir=%s", upper, lower);
+
+               len2 = strlen(lower) + strlen(upper) + strlen(work)
+                       + strlen("upperdir=,lowerdir=,workdir=") + 1;
+               options_work = alloca(len2);
+               ret2 = snprintf(options_work, len2, "upperdir=%s,lowerdir=%s,workdir=%s",
+                       upper, lower, work);
        }
-       if (ret < 0 || ret >= len) {
+       if (ret < 0 || ret >= len || ret2 < 0 || ret2 >= len2) {
                free(mntdata);
                return -1;
        }
 
+       // mount without workdir option for overlayfs before v21
        ret = mount(lower, bdev->dest, "overlayfs", MS_MGC_VAL | mntflags, options);
-       if (ret < 0)
-               SYSERROR("overlayfs: error mounting %s onto %s options %s",
+       if (ret < 0) {
+               INFO("overlayfs: error mounting %s onto %s options %s. retry with workdir",
                        lower, bdev->dest, options);
+
+               // retry with workdir option for overlayfs v22 and higher
+               ret = mount(lower, bdev->dest, "overlayfs", MS_MGC_VAL | mntflags, options_work);
+               if (ret < 0)
+                       SYSERROR("overlayfs: error mounting %s onto %s options %s",
+                               lower, bdev->dest, options_work);
+               else
+                       INFO("overlayfs: mounted %s onto %s options %s",
+                               lower, bdev->dest, options_work);
+       }
        else
                INFO("overlayfs: mounted %s onto %s options %s",
                        lower, bdev->dest, options);
@@ -2264,20 +2302,25 @@ static int overlayfs_clonepaths(struct bdev *orig, struct bdev *new, const char
                WARN("Failed to update ownership of %s", new->dest);
 
        if (strcmp(orig->type, "dir") == 0) {
-               char *delta;
-               int ret, len;
+               char *delta, *lastslash;
+               char *work;
+               int ret, len, lastslashidx;
 
                // if we have /var/lib/lxc/c2/rootfs, then delta will be
                //            /var/lib/lxc/c2/delta0
-               delta = strdup(new->dest);
-               if (!delta) {
-                       return -1;
-               }
-               if (strlen(delta) < 6) {
-                       free(delta);
+               lastslash = strrchr(new->dest, '/');
+               if (!lastslash)
                        return -22;
-               }
-               strcpy(&delta[strlen(delta)-6], "delta0");
+               if (strlen(lastslash) < 7)
+                       return -22;
+               lastslash++;
+               lastslashidx = lastslash - new->dest;
+
+               delta = malloc(lastslashidx + 7);
+               if (!delta)
+                       return -1;
+               strncpy(delta, new->dest, lastslashidx+1);
+               strcpy(delta+lastslashidx, "delta0");
                if ((ret = mkdir(delta, 0755)) < 0) {
                        SYSERROR("error: mkdir %s", delta);
                        free(delta);
@@ -2286,6 +2329,25 @@ static int overlayfs_clonepaths(struct bdev *orig, struct bdev *new, const char
                if (am_unpriv() && chown_mapped_root(delta, conf) < 0)
                        WARN("Failed to update ownership of %s", delta);
 
+               // make workdir for overlayfs.v22 or higher
+               // workdir is /var/lib/lxc/c2/olwork
+               // it is used to prepare files before atomically swithing with destination,
+               // and needs to be on the same filesystem as upperdir,
+               // so it's OK for it to be empty.
+               work = malloc(lastslashidx + 7);
+               if (!work)
+                       return -1;
+               strncpy(work, new->dest, lastslashidx+1);
+               strcpy(work+lastslashidx, "olwork");
+               if (mkdir(work, 0755) < 0) {
+                       SYSERROR("error: mkdir %s", work);
+                       free(work);
+                       return -1;
+               }
+               if (am_unpriv() && chown_mapped_root(work, conf) < 0)
+                       WARN("Failed to update ownership of %s", work);
+               free(work);
+
                // the src will be 'overlayfs:lowerdir:upperdir'
                len = strlen(delta) + strlen(orig->src) + 12;
                new->src = malloc(len);
@@ -2302,8 +2364,9 @@ static int overlayfs_clonepaths(struct bdev *orig, struct bdev *new, const char
                // I think we want to use the original lowerdir, with a
                // private delta which is originally rsynced from the
                // original delta
-               char *osrc, *odelta, *nsrc, *ndelta;
-               int len, ret;
+               char *osrc, *odelta, *nsrc, *ndelta, *work;
+               char *lastslash;
+               int len, ret, lastslashidx;
                if (!(osrc = strdup(orig->src)))
                        return -22;
                nsrc = index(osrc, ':') + 1;
@@ -2318,7 +2381,7 @@ static int overlayfs_clonepaths(struct bdev *orig, struct bdev *new, const char
                        free(osrc);
                        return -ENOMEM;
                }
-               if ((ret = mkdir(ndelta, 0755)) < 0) {
+               if ((ret = mkdir(ndelta, 0755)) < 0 && errno != EEXIST) {
                        SYSERROR("error: mkdir %s", ndelta);
                        free(osrc);
                        free(ndelta);
@@ -2326,6 +2389,29 @@ static int overlayfs_clonepaths(struct bdev *orig, struct bdev *new, const char
                }
                if (am_unpriv() && chown_mapped_root(ndelta, conf) < 0)
                        WARN("Failed to update ownership of %s", ndelta);
+
+               // make workdir for overlayfs.v22 or higher
+               // for details, see above.
+               lastslash = strrchr(ndelta, '/');
+               if (!lastslash)
+                       return -1;
+               lastslash++;
+               lastslashidx = lastslash - ndelta;
+
+               work = malloc(lastslashidx + 7);
+               if (!work)
+                       return -1;
+               strncpy(work, ndelta, lastslashidx+1);
+               strcpy(work+lastslashidx, "olwork");
+               if ((mkdir(work, 0755) < 0) && errno != EEXIST) {
+                       SYSERROR("error: mkdir %s", work);
+                       free(work);
+                       return -1;
+               }
+               if (am_unpriv() && chown_mapped_root(work, conf) < 0)
+                       WARN("Failed to update ownership of %s", work);
+               free(work);
+
                struct rsync_data_char rdata;
                rdata.src = odelta;
                rdata.dest = ndelta;
@@ -2559,20 +2645,24 @@ static int aufs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldn
                return -1;
 
        if (strcmp(orig->type, "dir") == 0) {
-               char *delta;
-               int ret, len;
+               char *delta, *lastslash;
+               int ret, len, lastslashidx;
 
                // if we have /var/lib/lxc/c2/rootfs, then delta will be
                //            /var/lib/lxc/c2/delta0
-               delta = strdup(new->dest);
-               if (!delta) {
-                       return -1;
-               }
-               if (strlen(delta) < 6) {
-                       free(delta);
+               lastslash = strrchr(new->dest, '/');
+               if (!lastslash)
                        return -22;
-               }
-               strcpy(&delta[strlen(delta)-6], "delta0");
+               if (strlen(lastslash) < 7)
+                       return -22;
+               lastslash++;
+               lastslashidx = lastslash - new->dest;
+
+               delta = malloc(lastslashidx + 7);
+               if (!delta)
+                       return -1;
+               strncpy(delta, new->dest, lastslashidx+1);
+               strcpy(delta+lastslashidx, "delta0");
                if ((ret = mkdir(delta, 0755)) < 0) {
                        SYSERROR("error: mkdir %s", delta);
                        free(delta);
@@ -2922,6 +3012,7 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
        const char *oldname = c0->name;
        const char *oldpath = c0->config_path;
        struct rsync_data data;
+       char *rootfs;
 
        /* if the container name doesn't show up in the rootfs path, then
         * we don't know how to come up with a new name
@@ -2946,7 +3037,14 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
                        bdev_put(orig);
                        return NULL;
                }
-               ret = snprintf(orig->dest, MAXPATHLEN, "%s/%s/rootfs", oldpath, oldname);
+               rootfs = strrchr(orig->src, '/');
+               if (!rootfs) {
+                       ERROR("invalid rootfs path");
+                       bdev_put(orig);
+                       return NULL;
+               }
+               rootfs++;
+               ret = snprintf(orig->dest, MAXPATHLEN, "%s/%s/%s", oldpath, oldname, rootfs);
                if (ret < 0 || ret >= MAXPATHLEN) {
                        ERROR("rootfs path too long");
                        bdev_put(orig);
@@ -3072,7 +3170,7 @@ static struct bdev * do_bdev_create(const char *dest, const char *type,
 /*
  * bdev_create:
  * Create a backing store for a container.
- * If successfull, return a struct bdev *, with the bdev mounted and ready
+ * If successful, return a struct bdev *, with the bdev mounted and ready
  * for use.  Before completing, the caller will need to call the
  * umount operation and bdev_put().
  * @dest: the mountpoint (i.e. /var/lib/lxc/$name/rootfs)
index 796b220..15346dc 100644 (file)
@@ -1002,7 +1002,7 @@ static struct cgroup_process_info *lxc_cgroupfs_create(const char *name, const c
                continue;
 
        cleanup_from_error:
-               /* called if an error occured in the loop, so we
+               /* called if an error occurred in the loop, so we
                 * do some additional cleanup here
                 */
                saved_errno = errno;
@@ -2226,15 +2226,7 @@ static void *cgfs_init(const char *name)
        if (!d->name)
                goto err1;
 
-       /* if we are running as root, use system cgroup pattern, otherwise
-        * just create a cgroup under the current one. But also fall back to
-        * that if for some reason reading the configuration fails and no
-        * default value is available
-        */
-       if (geteuid() == 0)
-               d->cgroup_pattern = lxc_global_config_value("lxc.cgroup.pattern");
-       if (!d->cgroup_pattern)
-               d->cgroup_pattern = "%n";
+       d->cgroup_pattern = lxc_global_config_value("lxc.cgroup.pattern");
 
        d->meta = lxc_cgroup_load_meta();
        if (!d->meta) {
index a11d42f..1872f03 100644 (file)
@@ -182,9 +182,75 @@ static bool cgm_dbus_connect(void)
        return true;
 }
 
-static inline bool cgm_supports_multiple_controllers(void)
+static bool cgm_supports_multiple_controllers;
+/*
+ * if cgm_all_controllers_same is true, then cgm_supports_multiple_controllers
+ * is true
+ */
+static bool cgm_all_controllers_same;
+
+/*
+ * Check whether we can use "all" when talking to cgmanager.
+ * We check two things:
+ * 1. whether cgmanager is new enough to support this.
+ * 2. whether the task we are interested in is in the same
+ *    cgroup for all controllers.
+ * In cgm_init (before an lxc-start) we care about our own
+ * cgroup.  In cgm_attach, we care about the target task's
+ * cgroup.
+ */
+static void check_supports_multiple_controllers(pid_t pid)
 {
-       return api_version >= CGM_SUPPORTS_MULT_CONTROLLERS;
+       FILE *f;
+       char *line = NULL, *prevpath = NULL;
+       size_t sz = 0;
+       char path[100];
+
+       cgm_supports_multiple_controllers = false;
+       cgm_all_controllers_same = false;
+
+       if (api_version < CGM_SUPPORTS_MULT_CONTROLLERS) {
+               cgm_supports_multiple_controllers = false;
+               return;
+       }
+
+       cgm_supports_multiple_controllers = true;
+
+       if (pid == -1)
+               sprintf(path, "/proc/self/cgroup");
+       else
+               sprintf(path, "/proc/%d/cgroup", pid);
+       f = fopen(path, "r");
+       if (!f)
+               return;
+
+       cgm_all_controllers_same = true;
+
+       while (getline(&line, &sz, f) != -1) {
+               /* file format: hierarchy:subsystems:group */
+               char *colon;
+               if (!line[0])
+                       continue;
+
+               colon = strchr(line, ':');
+               if (!colon)
+                       continue;
+               colon = strchr(colon+1, ':');
+               if (!colon)
+                       continue;
+               colon++;
+               if (!prevpath) {
+                       prevpath = alloca(strlen(colon)+1);
+                       strcpy(prevpath, colon);
+                       continue;
+               }
+               if (strcmp(prevpath, colon) != 0) {
+                       cgm_all_controllers_same = false;
+                       fclose(f);
+                       return;
+               }
+       }
+       fclose(f);
 }
 
 static int send_creds(int sock, int rpid, int ruid, int rgid)
@@ -251,7 +317,7 @@ static bool lxc_cgmanager_escape(void)
        char **slist = subsystems;
        int i;
 
-       if (cgm_supports_multiple_controllers())
+       if (cgm_all_controllers_same)
                slist = subsystems_inone;
 
        for (i = 0; slist[i]; i++) {
@@ -367,7 +433,7 @@ static int chown_cgroup_wrapper(void *data)
        }
        destuid = get_ns_uid(arg->origuid);
 
-       if (cgm_supports_multiple_controllers())
+       if (cgm_supports_multiple_controllers)
                slist = subsystems_inone;
 
        for (i = 0; slist[i]; i++) {
@@ -425,7 +491,7 @@ static bool chown_cgroup(const char *cgroup_path, struct lxc_conf *conf)
         * This can't be done in the child namespace because it only group-owns
         * the cgroup
         */
-       if (cgm_supports_multiple_controllers())
+       if (cgm_supports_multiple_controllers)
                slist = subsystems_inone;
 
        for (i = 0; slist[i]; i++) {
@@ -465,6 +531,9 @@ static void *cgm_init(const char *name)
                ERROR("Error connecting to cgroup manager");
                return NULL;
        }
+
+       check_supports_multiple_controllers(-1);
+
        d = malloc(sizeof(*d));
        if (!d) {
                cgm_dbus_disconnect();
@@ -478,15 +547,8 @@ static void *cgm_init(const char *name)
                goto err1;
        }
 
-       /* if we are running as root, use system cgroup pattern, otherwise
-        * just create a cgroup under the current one. But also fall back to
-        * that if for some reason reading the configuration fails and no
-        * default value is available
-        */
-       if (geteuid() == 0)
-               d->cgroup_pattern = lxc_global_config_value("lxc.cgroup.pattern");
-       if (!d->cgroup_pattern)
-               d->cgroup_pattern = "%n";
+       d->cgroup_pattern = lxc_global_config_value("lxc.cgroup.pattern");
+
        // cgm_create immediately gets called so keep the connection open
        return d;
 
@@ -509,7 +571,7 @@ static void cgm_destroy(void *hdata)
                return;
        }
 
-       if (cgm_supports_multiple_controllers())
+       if (cgm_supports_multiple_controllers)
                slist = subsystems_inone;
        for (i = 0; slist[i]; i++)
                cgm_remove_cgroup(slist[i], d->cgroup_path);
@@ -530,7 +592,7 @@ static inline void cleanup_cgroups(char *path)
        int i;
        char **slist = subsystems;
 
-       if (cgm_supports_multiple_controllers())
+       if (cgm_supports_multiple_controllers)
                slist = subsystems_inone;
        for (i = 0; slist[i]; i++)
                cgm_remove_cgroup(slist[i], path);
@@ -576,7 +638,7 @@ again:
        }
        existed = 0;
 
-       if (cgm_supports_multiple_controllers())
+       if (cgm_supports_multiple_controllers)
                slist = subsystems_inone;
 
        for (i = 0; slist[i]; i++) {
@@ -636,35 +698,29 @@ static bool lxc_cgmanager_enter(pid_t pid, const char *controller,
        return true;
 }
 
-/* Internal helper, must be called with cgmanager dbus socket open */
-static bool do_cgm_enter(pid_t pid, const char *cgroup_path, bool abs)
-{
-       char **slist = subsystems;
-       int i;
-
-       if (cgm_supports_multiple_controllers())
-               slist = subsystems_inone;
-
-       for (i = 0; slist[i]; i++) {
-               if (!lxc_cgmanager_enter(pid, slist[i], cgroup_path, abs))
-                       return false;
-       }
-       return true;
-}
-
 static inline bool cgm_enter(void *hdata, pid_t pid)
 {
        struct cgm_data *d = hdata;
+       char **slist = subsystems;
        bool ret = false;
+       int i;
+
+       if (!d || !d->cgroup_path)
+               return false;
 
        if (!cgm_dbus_connect()) {
                ERROR("Error connecting to cgroup manager");
                return false;
        }
-       if (!d || !d->cgroup_path)
-               goto out;
-       if (do_cgm_enter(pid, d->cgroup_path, false))
-               ret = true;
+
+       if (cgm_all_controllers_same)
+               slist = subsystems_inone;
+
+       for (i = 0; slist[i]; i++) {
+               if (!lxc_cgmanager_enter(pid, slist[i], d->cgroup_path, false))
+                       goto out;
+       }
+       ret = true;
 out:
        cgm_dbus_disconnect();
        return ret;
@@ -784,7 +840,7 @@ static void do_cgm_get(const char *name, const char *lxcpath, const char *filena
                        WARN("Failed to warn cgm_get of error; parent may hang");
                exit(1);
        }
-       cgroup = try_get_abs_cgroup(name, lxcpath, subsystems[0]);
+       cgroup = try_get_abs_cgroup(name, lxcpath, controller);
        if (!cgroup) {
                cgm_dbus_disconnect();
                ret = write(outp, &len, sizeof(len));
@@ -924,7 +980,7 @@ static void do_cgm_set(const char *name, const char *lxcpath, const char *filena
                        WARN("Failed to warn cgm_set of error; parent may hang");
                exit(1);
        }
-       cgroup = try_get_abs_cgroup(name, lxcpath, subsystems[0]);
+       cgroup = try_get_abs_cgroup(name, lxcpath, controller);
        if (!cgroup) {
                cgm_dbus_disconnect();
                ret = write(outp, &retval, sizeof(retval));
@@ -1222,24 +1278,38 @@ static bool cgm_chown(void *hdata, struct lxc_conf *conf)
  */
 static bool cgm_attach(const char *name, const char *lxcpath, pid_t pid)
 {
-       bool pass;
+       bool pass = true;
        char *cgroup = NULL;
+       char **slist = subsystems;
+       int i;
 
        if (!cgm_dbus_connect()) {
                ERROR("Error connecting to cgroup manager");
                return false;
        }
-       // cgm_create makes sure that we have the same cgroup name for all
-       // subsystems, so since this is a slow command over the cmd socket,
-       // just get the cgroup name for the first one.
-       cgroup = try_get_abs_cgroup(name, lxcpath, subsystems[0]);
-       if (!cgroup) {
-               ERROR("Failed to get cgroup for controller %s", subsystems[0]);
-               cgm_dbus_disconnect();
-               return false;
-       }
 
-       pass = do_cgm_enter(pid, cgroup, abs_cgroup_supported());
+       check_supports_multiple_controllers(pid);
+
+       if (cgm_all_controllers_same)
+               slist = subsystems_inone;
+
+       for (i = 0; slist[i]; i++) {
+               if (slist == subsystems_inone)
+                       cgroup = try_get_abs_cgroup(name, lxcpath, subsystems[0]);
+               else
+                       cgroup = try_get_abs_cgroup(name, lxcpath, slist[i]);
+               if (!cgroup) {
+                       ERROR("Failed to get cgroup for controller %s", slist[i]);
+                       cgm_dbus_disconnect();
+                       return false;
+               }
+
+               if (!lxc_cgmanager_enter(pid, slist[i], cgroup, abs_cgroup_supported())) {
+                       pass = false;
+                       break;
+               }
+
+       }
        cgm_dbus_disconnect();
        if (!pass)
                ERROR("Failed to enter group %s", cgroup);
index 2845614..b70ee72 100644 (file)
@@ -55,7 +55,7 @@
  * Each command is transactional, the clients send a request to
  * the server and the server answers the request with a message
  * giving the request's status (zero or a negative errno value).
- * Both the request and response may contain addtional data.
+ * Both the request and response may contain additional data.
  *
  * Each command is wrapped in a ancillary message in order to pass
  * a credential making possible to the server to check if the client
index b4ee277..320b6c9 100644 (file)
@@ -160,10 +160,14 @@ return -1;
 #define        __S_ISTYPE(mode, mask)  (((mode) & S_IFMT) == (mask))
 #endif
 
+#ifndef MS_PRIVATE
+#define MS_PRIVATE (1<<18)
+#endif
+
 char *lxchook_names[NUM_LXC_HOOKS] = {
        "pre-start", "pre-mount", "mount", "autodev", "start", "post-stop", "clone" };
 
-typedef int (*instanciate_cb)(struct lxc_handler *, struct lxc_netdev *);
+typedef int (*instantiate_cb)(struct lxc_handler *, struct lxc_netdev *);
 
 struct mount_opt {
        char *name;
@@ -179,20 +183,20 @@ struct caps_opt {
 /* Declare this here, since we don't want to reshuffle the whole file. */
 static int in_caplist(int cap, struct lxc_list *caps);
 
-static int instanciate_veth(struct lxc_handler *, struct lxc_netdev *);
-static int instanciate_macvlan(struct lxc_handler *, struct lxc_netdev *);
-static int instanciate_vlan(struct lxc_handler *, struct lxc_netdev *);
-static int instanciate_phys(struct lxc_handler *, struct lxc_netdev *);
-static int instanciate_empty(struct lxc_handler *, struct lxc_netdev *);
-static int instanciate_none(struct lxc_handler *, struct lxc_netdev *);
-
-static  instanciate_cb netdev_conf[LXC_NET_MAXCONFTYPE + 1] = {
-       [LXC_NET_VETH]    = instanciate_veth,
-       [LXC_NET_MACVLAN] = instanciate_macvlan,
-       [LXC_NET_VLAN]    = instanciate_vlan,
-       [LXC_NET_PHYS]    = instanciate_phys,
-       [LXC_NET_EMPTY]   = instanciate_empty,
-       [LXC_NET_NONE]    = instanciate_none,
+static int instantiate_veth(struct lxc_handler *, struct lxc_netdev *);
+static int instantiate_macvlan(struct lxc_handler *, struct lxc_netdev *);
+static int instantiate_vlan(struct lxc_handler *, struct lxc_netdev *);
+static int instantiate_phys(struct lxc_handler *, struct lxc_netdev *);
+static int instantiate_empty(struct lxc_handler *, struct lxc_netdev *);
+static int instantiate_none(struct lxc_handler *, struct lxc_netdev *);
+
+static  instantiate_cb netdev_conf[LXC_NET_MAXCONFTYPE + 1] = {
+       [LXC_NET_VETH]    = instantiate_veth,
+       [LXC_NET_MACVLAN] = instantiate_macvlan,
+       [LXC_NET_VLAN]    = instantiate_vlan,
+       [LXC_NET_PHYS]    = instantiate_phys,
+       [LXC_NET_EMPTY]   = instantiate_empty,
+       [LXC_NET_NONE]    = instantiate_none,
 };
 
 static int shutdown_veth(struct lxc_handler *, struct lxc_netdev *);
@@ -202,7 +206,7 @@ static int shutdown_phys(struct lxc_handler *, struct lxc_netdev *);
 static int shutdown_empty(struct lxc_handler *, struct lxc_netdev *);
 static int shutdown_none(struct lxc_handler *, struct lxc_netdev *);
 
-static  instanciate_cb netdev_deconf[LXC_NET_MAXCONFTYPE + 1] = {
+static  instantiate_cb netdev_deconf[LXC_NET_MAXCONFTYPE + 1] = {
        [LXC_NET_VETH]    = shutdown_veth,
        [LXC_NET_MACVLAN] = shutdown_macvlan,
        [LXC_NET_VLAN]    = shutdown_vlan,
@@ -1426,7 +1430,7 @@ static int mount_autodev(const char *name, char *root, const char *lxcpath)
                 * Get rid of old links and directoriess
                 * This could be either a symlink and we remove it,
                 * or an empty directory and we remove it,
-                * or non-existant and we don't care,
+                * or non-existent and we don't care,
                 * or a non-empty directory, and we will then emit an error
                 * but we will not fail out the process.
                 */
@@ -1582,68 +1586,6 @@ int lxc_delete_autodev(struct lxc_handler *handler)
        return 0;
 }
 
-/*
- * I'll forgive you for asking whether all of this is needed :)  The
- * answer is yes.
- * pivot_root will fail if the new root, the put_old dir, or the parent
- * of current->fs->root are MS_SHARED.  (parent of current->fs_root may
- * or may not be current->fs_root - if we assumed it always was, we could
- * just mount --make-rslave /).  So,
- *    1. mount a tiny tmpfs to be parent of current->fs->root.
- *    2. make that MS_SLAVE
- *    3. make a 'root' directory under that
- *    4. mount --rbind / under the $tinyroot/root.
- *    5. make that rslave
- *    6. chdir and chroot into $tinyroot/root
- *    7. $tinyroot will be unmounted by our parent in start.c
- */
-static int chroot_into_slave(struct lxc_conf *conf)
-{
-       char path[MAXPATHLEN];
-       const char *destpath = conf->rootfs.mount;
-       int ret;
-
-       if (mount(destpath, destpath, NULL, MS_BIND, 0)) {
-               SYSERROR("failed to mount %s bind", destpath);
-               return -1;
-       }
-       if (mount("", destpath, NULL, MS_SLAVE, 0)) {
-               SYSERROR("failed to make %s slave", destpath);
-               return -1;
-       }
-       if (mount("none", destpath, "tmpfs", 0, "size=10000,mode=755")) {
-               SYSERROR("Failed to mount tmpfs / at %s", destpath);
-               return -1;
-       }
-       ret = snprintf(path, MAXPATHLEN, "%s/root", destpath);
-       if (ret < 0 || ret >= MAXPATHLEN) {
-               ERROR("out of memory making root path");
-               return -1;
-       }
-       if (mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
-               SYSERROR("Failed to create /dev/pts in container");
-               return -1;
-       }
-       if (mount("/", path, NULL, MS_BIND|MS_REC, 0)) {
-               SYSERROR("Failed to rbind mount / to %s", path);
-               return -1;
-       }
-       if (mount("", destpath, NULL, MS_SLAVE|MS_REC, 0)) {
-               SYSERROR("Failed to make tmp-/ at %s rslave", path);
-               return -1;
-       }
-       if (chroot(path)) {
-               SYSERROR("Failed to chroot into tmp-/");
-               return -1;
-       }
-       if (chdir("/")) {
-               SYSERROR("Failed to chdir into tmp-/");
-               return -1;
-       }
-       INFO("Chrooted into tmp-/ at %s", path);
-       return 0;
-}
-
 static int setup_rootfs(struct lxc_conf *conf)
 {
        const struct lxc_rootfs *rootfs = &conf->rootfs;
@@ -1681,12 +1623,106 @@ static int setup_rootfs(struct lxc_conf *conf)
        return 0;
 }
 
+int prepare_ramfs_root(char *root)
+{
+       char buf[LINELEN], *p;
+       char nroot[PATH_MAX];
+       FILE *f;
+       int i;
+       char *p2;
+
+       if (realpath(root, nroot) == NULL)
+               return -1;
+
+       if (chdir("/") == -1)
+               return -1;
+
+       /*
+        * We could use here MS_MOVE, but in userns this mount is
+        * locked and can't be moved.
+        */
+       if (mount(root, "/", NULL, MS_REC | MS_BIND, NULL)) {
+               SYSERROR("Failed to move %s into /", root);
+               return -1;
+       }
+
+       if (mount(".", NULL, NULL, MS_REC | MS_PRIVATE, NULL)) {
+               SYSERROR("Failed to make . rprivate");
+               return -1;
+       }
+
+       /*
+        * The following code cleans up inhereted mounts which are not
+        * required for CT.
+        *
+        * The mountinfo file shows not all mounts, if a few points have been
+        * unmounted between read operations from the mountinfo. So we need to
+        * read mountinfo a few times.
+        *
+        * This loop can be skipped if a container uses unserns, because all
+        * inherited mounts are locked and we should live with all this trash.
+        */
+       while (1) {
+               int progress = 0;
+
+               f = fopen("./proc/self/mountinfo", "r");
+               if (!f) {
+                       SYSERROR("Unable to open /proc/self/mountinfo");
+                       return -1;
+               }
+               while (fgets(buf, LINELEN, f)) {
+                       for (p = buf, i=0; p && i < 4; i++)
+                               p = strchr(p+1, ' ');
+                       if (!p)
+                               continue;
+                       p2 = strchr(p+1, ' ');
+                       if (!p2)
+                               continue;
+
+                       *p2 = '\0';
+                       *p = '.';
+
+                       if (strcmp(p + 1, "/") == 0)
+                               continue;
+                       if (strcmp(p + 1, "/proc") == 0)
+                               continue;
+
+                       if (umount2(p, MNT_DETACH) == 0)
+                               progress++;
+               }
+               fclose(f);
+               if (!progress)
+                       break;
+       }
+
+       if (umount2("./proc", MNT_DETACH)) {
+               SYSERROR("Unable to umount /proc");
+               return -1;
+       }
+
+       /* It is weird, but chdir("..") moves us in a new root */
+       if (chdir("..") == -1) {
+               SYSERROR("Unable to change working directory");
+               return -1;
+       }
+
+       if (chroot(".") == -1) {
+               SYSERROR("Unable to chroot");
+               return -1;
+       }
+
+       return 0;
+}
+
 static int setup_pivot_root(const struct lxc_rootfs *rootfs)
 {
        if (!rootfs->path)
                return 0;
 
-       if (setup_rootfs_pivot_root(rootfs->mount, rootfs->pivot)) {
+       if (detect_ramfs_rootfs()) {
+               if (prepare_ramfs_root(rootfs->mount))
+                       return -1;
+       } else if (setup_rootfs_pivot_root(rootfs->mount, rootfs->pivot)) {
                ERROR("failed to setup pivot root");
                return -1;
        }
@@ -2018,10 +2054,12 @@ static int mount_entry(const char *fsname, const char *target,
        if ((mountflags & MS_REMOUNT) || (mountflags & MS_BIND)) {
                DEBUG("remounting %s on %s to respect bind or remount options",
                      fsname ? fsname : "(none)", target ? target : "(none)");
-
+               unsigned long rqd_flags = 0;
+               if (mountflags & MS_RDONLY)
+                       rqd_flags |= MS_RDONLY;
 #ifdef HAVE_STATVFS
                if (statvfs(fsname, &sb) == 0) {
-                       unsigned long required_flags = 0;
+                       unsigned long required_flags = rqd_flags;
                        if (sb.f_flag & MS_NOSUID)
                                required_flags |= MS_NOSUID;
                        if (sb.f_flag & MS_NODEV)
@@ -2037,7 +2075,7 @@ static int mount_entry(const char *fsname, const char *target,
                         * mountflags, then skip the remount
                         */
                        if (!(mountflags & MS_REMOUNT)) {
-                               if (!(required_flags & ~mountflags)) {
+                               if (!(required_flags & ~mountflags) && rqd_flags == 0) {
                                        DEBUG("mountflags already was %lu, skipping remount",
                                                mountflags);
                                        goto skipremount;
@@ -2794,7 +2832,7 @@ void restore_phys_nics_to_netns(int netnsfd, struct lxc_conf *conf)
        }
        for (i=0; i<conf->num_savednics; i++) {
                struct saved_nic *s = &conf->saved_nics[i];
-               if (lxc_netdev_move_by_index(s->ifindex, 1))
+               if (lxc_netdev_move_by_index(s->ifindex, 1, NULL))
                        WARN("Error moving nic index:%d back to host netns",
                                        s->ifindex);
        }
@@ -2875,7 +2913,7 @@ struct lxc_conf *lxc_conf_init(void)
        return new;
 }
 
-static int instanciate_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
+static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
 {
        char veth1buf[IFNAMSIZ], *veth1;
        char veth2buf[IFNAMSIZ], *veth2;
@@ -2907,7 +2945,7 @@ static int instanciate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
 
        err = lxc_veth_create(veth1, veth2);
        if (err) {
-               ERROR("failed to create %s-%s : %s", veth1, veth2,
+               ERROR("failed to create veth pair (%s and %s): %s", veth1, veth2,
                      strerror(-err));
                goto out_delete;
        }
@@ -2917,7 +2955,7 @@ static int instanciate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
         * of a container */
        err = setup_private_host_hw_addr(veth1);
        if (err) {
-               ERROR("failed to change mac address of host interface '%s' : %s",
+               ERROR("failed to change mac address of host interface '%s': %s",
                        veth1, strerror(-err));
                goto out_delete;
        }
@@ -2927,7 +2965,7 @@ static int instanciate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
                if (!err)
                        err = lxc_netdev_set_mtu(veth2, atoi(netdev->mtu));
                if (err) {
-                       ERROR("failed to set mtu '%s' for %s-%s : %s",
+                       ERROR("failed to set mtu '%s' for veth pair (%s and %s): %s",
                              netdev->mtu, veth1, veth2, strerror(-err));
                        goto out_delete;
                }
@@ -2936,7 +2974,7 @@ static int instanciate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
        if (netdev->link) {
                err = lxc_bridge_attach(netdev->link, veth1);
                if (err) {
-                       ERROR("failed to attach '%s' to the bridge '%s' : %s",
+                       ERROR("failed to attach '%s' to the bridge '%s': %s",
                                      veth1, netdev->link, strerror(-err));
                        goto out_delete;
                }
@@ -2961,7 +2999,7 @@ static int instanciate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
                        goto out_delete;
        }
 
-       DEBUG("instanciated veth '%s/%s', index is '%d'",
+       DEBUG("instantiated veth '%s/%s', index is '%d'",
              veth1, veth2, netdev->ifindex);
 
        return 0;
@@ -2994,7 +3032,7 @@ static int shutdown_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
        return 0;
 }
 
-static int instanciate_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
+static int instantiate_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
 {
        char peerbuf[IFNAMSIZ], *peer;
        int err;
@@ -3035,7 +3073,7 @@ static int instanciate_macvlan(struct lxc_handler *handler, struct lxc_netdev *n
                        goto out;
        }
 
-       DEBUG("instanciated macvlan '%s', index is '%d' and mode '%d'",
+       DEBUG("instantiated macvlan '%s', index is '%d' and mode '%d'",
              peer, netdev->ifindex, netdev->priv.macvlan_attr.mode);
 
        return 0;
@@ -3059,8 +3097,8 @@ static int shutdown_macvlan(struct lxc_handler *handler, struct lxc_netdev *netd
        return 0;
 }
 
-/* XXX: merge with instanciate_macvlan */
-static int instanciate_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
+/* XXX: merge with instantiate_macvlan */
+static int instantiate_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
 {
        char peer[IFNAMSIZ];
        int err;
@@ -3090,7 +3128,7 @@ static int instanciate_vlan(struct lxc_handler *handler, struct lxc_netdev *netd
                return -1;
        }
 
-       DEBUG("instanciated vlan '%s', ifindex is '%d'", " vlan1000",
+       DEBUG("instantiated vlan '%s', ifindex is '%d'", " vlan1000",
              netdev->ifindex);
 
        return 0;
@@ -3101,7 +3139,7 @@ static int shutdown_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
        return 0;
 }
 
-static int instanciate_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
+static int instantiate_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
 {
        if (!netdev->link) {
                ERROR("no link specified for the physical interface");
@@ -3138,13 +3176,13 @@ static int shutdown_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
        return 0;
 }
 
-static int instanciate_none(struct lxc_handler *handler, struct lxc_netdev *netdev)
+static int instantiate_none(struct lxc_handler *handler, struct lxc_netdev *netdev)
 {
        netdev->ifindex = 0;
        return 0;
 }
 
-static int instanciate_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
+static int instantiate_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
 {
        netdev->ifindex = 0;
        if (netdev->upscript) {
@@ -3372,7 +3410,7 @@ int lxc_assign_network(struct lxc_list *network, pid_t pid)
                if (!netdev->ifindex)
                        continue;
 
-               err = lxc_netdev_move_by_index(netdev->ifindex, pid);
+               err = lxc_netdev_move_by_index(netdev->ifindex, pid, NULL);
                if (err) {
                        ERROR("failed to move '%s' to the container : %s",
                              netdev->link, strerror(-err));
@@ -3978,7 +4016,7 @@ void tmp_proc_unmount(struct lxc_conf *lxc_conf)
        }
 }
 
-static void remount_all_slave(void)
+void remount_all_slave(void)
 {
        /* walk /proc/mounts and change any shared entries to slave */
        FILE *f = fopen("/proc/self/mountinfo", "r");
@@ -4027,15 +4065,9 @@ int do_rootfs_setup(struct lxc_conf *conf, const char *name, const char *lxcpath
                const char *path = conf->rootfs.mount;
                if (mount(path, path, "rootfs", MS_BIND, NULL) < 0) {
                        ERROR("Failed to bind-mount container / onto itself");
-                       return false;
-               }
-       }
-
-       if (detect_ramfs_rootfs()) {
-               if (chroot_into_slave(conf)) {
-                       ERROR("Failed to chroot into slave /");
                        return -1;
                }
+               return 0;
        }
 
        remount_all_slave();
@@ -4073,6 +4105,7 @@ static bool verify_start_hooks(struct lxc_conf *conf)
                                        hookname);
                        return false;
                }
+               return true;
        }
 
        return true;
@@ -4363,12 +4396,12 @@ int lxc_clear_nic(struct lxc_conf *c, const char *key)
                        free(netdev->mtu);
                        netdev->mtu = NULL;
                }
-       } else if (strcmp(p1, ".ipv4_gateway") == 0) {
+       } else if (strcmp(p1, ".ipv4.gateway") == 0) {
                if (netdev->ipv4_gateway) {
                        free(netdev->ipv4_gateway);
                        netdev->ipv4_gateway = NULL;
                }
-       } else if (strcmp(p1, ".ipv6_gateway") == 0) {
+       } else if (strcmp(p1, ".ipv6.gateway") == 0) {
                if (netdev->ipv6_gateway) {
                        free(netdev->ipv6_gateway);
                        netdev->ipv6_gateway = NULL;
index 7434748..3416124 100644 (file)
@@ -140,7 +140,7 @@ struct lxc_netdev {
 /*
  * Defines a generic struct to configure the control group.
  * It is up to the programmer to specify the right subsystem.
- * @subsystem : the targetted subsystem
+ * @subsystem : the targeted subsystem
  * @value     : the value to set
  */
 struct lxc_cgroup {
@@ -184,7 +184,7 @@ struct lxc_pty_info {
 
 /*
  * Defines the number of tty configured and contains the
- * instanciated ptys
+ * instantiated ptys
  * @nbtty = number of configured ttys
  */
 struct lxc_tty_info {
@@ -399,5 +399,6 @@ extern int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data);
 extern int parse_mntopts(const char *mntopts, unsigned long *mntflags,
                         char **mntdata);
 extern void tmp_proc_unmount(struct lxc_conf *lxc_conf);
+void remount_all_slave(void);
 extern void suggest_default_idmap(void);
 #endif
index bd6196a..5594362 100644 (file)
@@ -433,9 +433,9 @@ extern int lxc_list_nicconfigs(struct lxc_conf *c, const char *key,
                strprint(retv, inlen, "hwaddr\n");
                strprint(retv, inlen, "mtu\n");
                strprint(retv, inlen, "ipv6\n");
-               strprint(retv, inlen, "ipv6_gateway\n");
+               strprint(retv, inlen, "ipv6.gateway\n");
                strprint(retv, inlen, "ipv4\n");
-               strprint(retv, inlen, "ipv4_gateway\n");
+               strprint(retv, inlen, "ipv4.gateway\n");
        }
        switch(netdev->type) {
        case LXC_NET_VETH:
@@ -1353,6 +1353,8 @@ out:
 static int config_fstab(const char *key, const char *value,
                        struct lxc_conf *lxc_conf)
 {
+       if (!value || strlen(value) == 0)
+               return -1;
        return config_path_item(&lxc_conf->fstab, value);
 }
 
@@ -1384,8 +1386,10 @@ static int config_mount_auto(const char *key, const char *value,
        int i;
        int ret = -1;
 
-       if (!strlen(value))
-               return -1;
+       if (!value || strlen(value) == 0) {
+               lxc_conf->auto_mounts = 0;
+               return 0;
+       }
 
        autos = strdup(value);
        if (!autos) {
@@ -1419,6 +1423,12 @@ static int config_mount_auto(const char *key, const char *value,
        return ret;
 }
 
+/*
+ * TODO
+ * This fn is handling lxc.mount, lxc.mount.entry, and lxc.mount.auto.
+ * It should probably be split into 3 separate functions indexed by
+ * the config[] entries at top.
+ */
 static int config_mount(const char *key, const char *value,
                        struct lxc_conf *lxc_conf)
 {
@@ -1429,9 +1439,6 @@ static int config_mount(const char *key, const char *value,
        char *mntelem;
        struct lxc_list *mntlist;
 
-       if (!value || strlen(value) == 0)
-               return lxc_clear_mount_entries(lxc_conf);
-
        subkey = strstr(key, token);
 
        if (!subkey) {
@@ -1449,8 +1456,9 @@ static int config_mount(const char *key, const char *value,
                return config_mount_auto(key, value, lxc_conf);
        }
 
-       if (!strlen(subkey))
-               return -1;
+       /* At this point we definitely have key = lxc.mount.entry */
+       if (!value || strlen(value) == 0)
+               return lxc_clear_mount_entries(lxc_conf);
 
        mntlist = malloc(sizeof(*mntlist));
        if (!mntlist)
@@ -2012,7 +2020,7 @@ static int lxc_get_auto_mounts(struct lxc_conf *c, char *retv, int inlen)
 /*
  * lxc.network.0.XXX, where XXX can be: name, type, link, flags, type,
  * macvlan.mode, veth.pair, vlan, ipv4, ipv6, script.up, hwaddr, mtu,
- * ipv4_gateway, ipv6_gateway.  ipvX_gateway can return 'auto' instead
+ * ipv4.gateway, ipv6.gateway.  ipvX.gateway can return 'auto' instead
  * of an address.  ipv4 and ipv6 return lists (newline-separated).
  * things like veth.pair return '' if invalid (i.e. if called for vlan
  * type).
@@ -2081,7 +2089,7 @@ static int lxc_get_item_nic(struct lxc_conf *c, char *retv, int inlen,
                if (netdev->type == LXC_NET_VLAN) {
                        strprint(retv, inlen, "%d", netdev->priv.vlan_attr.vid);
                }
-       } else if (strcmp(p1, "ipv4_gateway") == 0) {
+       } else if (strcmp(p1, "ipv4.gateway") == 0) {
                if (netdev->ipv4_gateway_auto) {
                        strprint(retv, inlen, "auto");
                } else if (netdev->ipv4_gateway) {
@@ -2095,9 +2103,9 @@ static int lxc_get_item_nic(struct lxc_conf *c, char *retv, int inlen,
                        struct lxc_inetdev *i = it2->elem;
                        char buf[INET_ADDRSTRLEN];
                        inet_ntop(AF_INET, &i->addr, buf, sizeof(buf));
-                       strprint(retv, inlen, "%s\n", buf);
+                       strprint(retv, inlen, "%s/%d\n", buf, i->prefix);
                }
-       } else if (strcmp(p1, "ipv6_gateway") == 0) {
+       } else if (strcmp(p1, "ipv6.gateway") == 0) {
                if (netdev->ipv6_gateway_auto) {
                        strprint(retv, inlen, "auto");
                } else if (netdev->ipv6_gateway) {
@@ -2111,7 +2119,7 @@ static int lxc_get_item_nic(struct lxc_conf *c, char *retv, int inlen,
                        struct lxc_inet6dev *i = it2->elem;
                        char buf[INET6_ADDRSTRLEN];
                        inet_ntop(AF_INET6, &i->addr, buf, sizeof(buf));
-                       strprint(retv, inlen, "%s\n", buf);
+                       strprint(retv, inlen, "%s/%d\n", buf, i->prefix);
                }
        }
        return fulllen;
@@ -2233,6 +2241,9 @@ int lxc_clear_config_item(struct lxc_conf *c, const char *key)
                lxc_seccomp_free(c);
                return 0;
        }
+       else if (strncmp(key, "lxc.id_map", 10) == 0) {
+               return lxc_clear_idmaps(c);
+       }
 
        return -1;
 }
index a7b3b19..a823bd0 100644 (file)
@@ -86,7 +86,7 @@ done
 containers=""
 if [ ! -z "$directory" ]; then
        if [ x"$parent_cgroup" = x ]; then
-               containers=$(find $directory -mindepth 2 -maxdepth 2 -name config -type f |awk -F "/" '{print $(NF-1)}')
+               containers=$(find -L $directory -mindepth 2 -maxdepth 2 -name config -type f |awk -F "/" '{print $(NF-1)}')
        else
                containers=$(find $directory -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sed 's:.*/::')
        fi
index 5ff1794..c2dba7b 100644 (file)
@@ -72,6 +72,7 @@ static int log_append_stderr(const struct lxc_log_appender *appender,
                return 0;
 
        fprintf(stderr, "%s: ", log_prefix);
+       fprintf(stderr, "%s: %s: %d ", event->locinfo->file, event->locinfo->func, event->locinfo->line);
        vfprintf(stderr, event->fmt, *event->vap);
        fprintf(stderr, "\n");
        return 0;
@@ -90,12 +91,14 @@ static int log_append_logfile(const struct lxc_log_appender *appender,
 
        ms = event->timestamp.tv_usec / 1000;
        n = snprintf(buffer, sizeof(buffer),
-                    "%15s %10ld.%03d %-8s %s - ",
+                    "%15s %10ld.%03d %-8s %s - %s:%s:%d - ",
                     log_prefix,
                     event->timestamp.tv_sec,
                     ms,
                     lxc_log_priority_to_string(event->priority),
-                    event->category);
+                    event->category,
+                    event->locinfo->file, event->locinfo->func,
+                    event->locinfo->line);
 
        n += vsnprintf(buffer + n, sizeof(buffer) - n, event->fmt,
                       *event->vap);
@@ -156,7 +159,7 @@ static int build_dir(const char *name)
                *p = '\0';
                if (access(n, F_OK)) {
                        ret = lxc_unpriv(mkdir(n, 0755));
-                       if (ret && errno != -EEXIST) {
+                       if (ret && errno != EEXIST) {
                                SYSERROR("failed to create directory '%s'.", n);
                                free(n);
                                return -1;
@@ -197,7 +200,7 @@ static int log_open(const char *name)
  * Build the path to the log file
  * @name     : the name of the container
  * @lxcpath  : the lxcpath to use as a basename or NULL to use LOGPATH
- * Returns malloced path on sucess, or NULL on failure
+ * Returns malloced path on success, or NULL on failure
  */
 static char *build_log_path(const char *name, const char *lxcpath)
 {
index 035479e..e263538 100644 (file)
@@ -245,7 +245,7 @@ struct btrfs_root_item {
 
        /*
         * This generation number is used to test if the new fields are valid
-        * and up to date while reading the root item. Everytime the root item
+        * and up to date while reading the root item. Every time the root item
         * is written out, the "generation" field is copied into this field. If
         * anyone ever mounted the fs with an older kernel, we will have
         * mismatching generation values here and thus must invalidate the
index 6182454..8e7d9f5 100644 (file)
@@ -42,7 +42,7 @@ if [ ! -f $CONFIG ]; then
     if [ ! -f "$CONFIG" ]; then
         MODULEFILE=$(modinfo -k $KVER -n $MODNAME 2> /dev/null)
         # don't want to modprobe, so give user a hint
-        # altho scripts/extract-ikconfig could be used to extract contents without loading kernel module
+        # although scripts/extract-ikconfig could be used to extract contents without loading kernel module
         # http://svn.pld-linux.org/trac/svn/browser/geninitrd/trunk/geninitrd?rev=12696#L327
     fi
     GREP=grep
index e340382..dd1048c 100644 (file)
@@ -47,7 +47,7 @@ struct lxc_arguments;
  * @name     : the name of the container
  * @argv     : an array of char * corresponding to the commande line
  * @conf     : configuration
- * Returns 0 on sucess, < 0 otherwise
+ * Returns 0 on success, < 0 otherwise
  */
 extern int lxc_start(const char *name, char *const argv[], struct lxc_conf *conf,
                     const char *lxcpath);
@@ -58,7 +58,7 @@ extern int lxc_start(const char *name, char *const argv[], struct lxc_conf *conf
  * @argv     : an array of char * corresponding to the commande line
  * @quiet    : if != 0 then lxc-init won't produce any output
  * @conf     : configuration
- * Returns 0 on sucess, < 0 otherwise
+ * Returns 0 on success, < 0 otherwise
  */
 extern int lxc_execute(const char *name, char *const argv[], int quiet,
                       struct lxc_conf *conf, const char *lxcpath);
@@ -118,7 +118,7 @@ extern int lxc_freeze(const char *name, const char *lxcpath);
 /*
  * Unfreeze all previously frozen tasks.
  * @name : the name of the container
- * Return 0 on sucess, < 0 otherwise
+ * Return 0 on success, < 0 otherwise
  */
 extern int lxc_unfreeze(const char *name, const char *lxcpath);
 
index e1e39c0..b360aa8 100644 (file)
@@ -169,6 +169,7 @@ static void print_net_stats(struct lxc_container *c)
                if (!ifname)
                        return;
                printf("%-15s %s\n", "Link:", ifname);
+               fflush(stdout);
 
                /* XXX: tx and rx are reversed from the host vs container
                 * perspective, print them from the container perspective
@@ -179,6 +180,7 @@ static void print_net_stats(struct lxc_container *c)
                        str_chomp(buf);
                        rx_bytes = str_size_humanize(buf, sizeof(buf));
                        printf("%-15s %s\n", " TX bytes:", buf);
+                       fflush(stdout);
                }
 
                snprintf(path, sizeof(path), "/sys/class/net/%s/statistics/tx_bytes", ifname);
@@ -187,11 +189,13 @@ static void print_net_stats(struct lxc_container *c)
                        str_chomp(buf);
                        tx_bytes = str_size_humanize(buf, sizeof(buf));
                        printf("%-15s %s\n", " RX bytes:", buf);
+                       fflush(stdout);
                }
 
                sprintf(buf, "%llu", rx_bytes + tx_bytes);
                str_size_humanize(buf, sizeof(buf));
                printf("%-15s %s\n", " Total bytes:", buf);
+               fflush(stdout);
                free(ifname);
        }
 }
@@ -210,6 +214,7 @@ static void print_stats(struct lxc_container *c)
                } else {
                        printf("%-15s %s\n", "CPU use:", buf);
                }
+               fflush(stdout);
        }
 
        ret = c->get_cgroup_item(c, "blkio.throttle.io_service_bytes", buf, sizeof(buf));
@@ -229,6 +234,7 @@ static void print_stats(struct lxc_container *c)
                        str_size_humanize(buf, sizeof(buf));
                        printf("%-15s %s\n", "BlkIO use:", buf);
                }
+               fflush(stdout);
        }
 
        static const struct {
@@ -246,6 +252,7 @@ static void print_stats(struct lxc_container *c)
                        str_chomp(buf);
                        str_size_humanize(buf, sizeof(buf));
                        printf("%-15s %s\n", lxstat[i].name, buf);
+                       fflush(stdout);
                }
        }
 }
@@ -260,6 +267,7 @@ static void print_info_msg_int(const char *key, int value)
                else
                        printf("%-15s %d\n", key, value);
        }
+       fflush(stdout);
 }
 
 static void print_info_msg_str(const char *key, const char *value)
@@ -272,6 +280,7 @@ static void print_info_msg_str(const char *key, const char *value)
                else
                        printf("%-15s %s\n", key, value);
        }
+       fflush(stdout);
 }
 
 static int print_info(const char *name, const char *lxcpath)
@@ -359,6 +368,7 @@ static int print_info(const char *name, const char *lxcpath)
                } else {
                        fprintf(stderr, "%s invalid\n", key[i]);
                }
+               fflush(stdout);
        }
 
        lxc_container_put(c);
index d55746e..d193273 100644 (file)
@@ -276,6 +276,11 @@ int main(int argc, char *argv[])
                }
        }
 
+       if (c->is_running(c)) {
+               ERROR("Container is already running.");
+               err = 0;
+               goto out;
+       }
        /*
         * We should use set_config_item() over &defines, which would handle
         * unset c->lxc_conf for us and let us not use lxc_config_define_load()
index fc6f9db..59a231e 100644 (file)
@@ -240,7 +240,7 @@ int main(int argc, char *argv[])
 
        if (my_iflist) {
                for (tmpif = my_iflist; tmpif; tmpif = tmpif->mi_next) {
-                       if (lxc_netdev_move_by_name(tmpif->mi_ifname, pid) < 0)
+                       if (lxc_netdev_move_by_name(tmpif->mi_ifname, pid, NULL) < 0)
                                fprintf(stderr,"Could not move interface %s into container %d: %s\n", tmpif->mi_ifname, pid, strerror(errno));
                }
        }
index 64e9d1a..ed63ea8 100644 (file)
@@ -197,7 +197,7 @@ static bool nic_exists(char *nic)
        return true;
 }
 
-static int instanciate_veth(char *n1, char **n2)
+static int instantiate_veth(char *n1, char **n2)
 {
        int err;
 
@@ -246,7 +246,7 @@ static bool create_nic(char *nic, char *br, int pid, char **cnic)
        }
 
        /* create the nics */
-       if (instanciate_veth(veth1buf, &veth2buf) < 0) {
+       if (instantiate_veth(veth1buf, &veth2buf) < 0) {
                fprintf(stderr, "Error creating veth tunnel\n");
                return false;
        }
@@ -268,7 +268,7 @@ static bool create_nic(char *nic, char *br, int pid, char **cnic)
        }
 
        /* pass veth2 to target netns */
-       ret = lxc_netdev_move_by_name(veth2buf, pid);
+       ret = lxc_netdev_move_by_name(veth2buf, pid, NULL);
        if (ret < 0) {
                fprintf(stderr, "Error moving %s to netns %d\n", veth2buf, pid);
                goto out_del;
@@ -541,7 +541,7 @@ out_err:
 
 /*
  * If the caller (real uid, not effective uid) may read the
- * /proc/pid/net/ns, then it is either the caller's netns or one
+ * /proc/[pid]/ns/net, then it is either the caller's netns or one
  * which it created.
  */
 static bool may_access_netns(int pid)
index 2582da0..eb3ea37 100644 (file)
@@ -1460,7 +1460,7 @@ static bool lxcapi_clear_config_item(struct lxc_container *c, const char *key)
        return ret == 0;
 }
 
-static inline bool enter_to_ns(struct lxc_container *c) {
+static inline bool enter_net_ns(struct lxc_container *c) {
        int netns, userns, ret = 0, init_pid = 0;;
        char new_netns_path[MAXPATHLEN];
        char new_userns_path[MAXPATHLEN];
@@ -1610,7 +1610,7 @@ static char** lxcapi_get_interfaces(struct lxc_container *c)
                /* close the read-end of the pipe */
                close(pipefd[0]);
 
-               if (!enter_to_ns(c)) {
+               if (!enter_net_ns(c)) {
                        SYSERROR("failed to enter namespace");
                        goto out;
                }
@@ -1700,7 +1700,7 @@ static char** lxcapi_get_ips(struct lxc_container *c, const char* interface, con
                /* close the read-end of the pipe */
                close(pipefd[0]);
 
-               if (!enter_to_ns(c)) {
+               if (!enter_net_ns(c)) {
                        SYSERROR("failed to enter namespace");
                        goto out;
                }
index 1d0628a..5ef10dd 100644 (file)
@@ -569,7 +569,7 @@ struct lxc_container {
         * \param c Container.
         * \param[in,out] ttynum Terminal number to attempt to allocate,
         *  or \c -1 to allocate the first available tty.
-        * \param[out] masterfd File descriptor refering to the master side of the pty.
+        * \param[out] masterfd File descriptor referring to the master side of the pty.
         *
         * \return tty file descriptor number on success, or \c -1 on
         *  failure.
index 1d62729..0cd09be 100644 (file)
@@ -343,7 +343,7 @@ void process_unlock(void)
 }
 
 /* One thread can do fork() while another one is holding a mutex.
- * There is only one thread in child just after the fork(), so noone will ever release that mutex.
+ * There is only one thread in child just after the fork(), so no one will ever release that mutex.
  * We setup a "child" fork handler to unlock the mutex just after the fork().
  * For several mutex types, unlocking an unlocked mutex can lead to undefined behavior.
  * One way to deal with it is to setup "prepare" fork handler
index a9900de..54367c8 100644 (file)
 # define IFLA_MACVLAN_MODE 1
 #endif
 
-struct link_req {
-       struct nlmsg nlmsg;
-       struct ifinfomsg ifinfomsg;
-};
-
-struct ip_req {
-       struct nlmsg nlmsg;
-       struct ifaddrmsg ifa;
-};
-
-struct rt_req {
-       struct nlmsg nlmsg;
-       struct rtmsg rt;
-};
 
-int lxc_netdev_move_by_index(int ifindex, pid_t pid)
+int lxc_netdev_move_by_index(int ifindex, pid_t pid, const char* ifname)
 {
        struct nl_handler nlh;
        struct nlmsg *nlmsg = NULL;
-       struct link_req *link_req;
+       struct ifinfomsg *ifi;
        int err;
 
        err = netlink_open(&nlh, NETLINK_ROUTE);
@@ -118,16 +104,21 @@ int lxc_netdev_move_by_index(int ifindex, pid_t pid)
        if (!nlmsg)
                goto out;
 
-       link_req = (struct link_req *)nlmsg;
-       link_req->ifinfomsg.ifi_family = AF_UNSPEC;
-       link_req->ifinfomsg.ifi_index = ifindex;
-       nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
-       nlmsg->nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
-       nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
+       nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
+       nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
+
+       ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
+       ifi->ifi_family = AF_UNSPEC;
+       ifi->ifi_index = ifindex;
 
        if (nla_put_u32(nlmsg, IFLA_NET_NS_PID, pid))
                goto out;
 
+       if (ifname != NULL) {
+               if (nla_put_string(nlmsg, IFLA_IFNAME, ifname))
+                       goto out;
+       }
+
        err = netlink_transaction(&nlh, nlmsg, nlmsg);
 out:
        netlink_close(&nlh);
@@ -135,7 +126,7 @@ out:
        return err;
 }
 
-int lxc_netdev_move_by_name(char *ifname, pid_t pid)
+int lxc_netdev_move_by_name(const char *ifname, pid_t pid, const char* newname)
 {
        int index;
 
@@ -143,15 +134,17 @@ int lxc_netdev_move_by_name(char *ifname, pid_t pid)
                return -EINVAL;
 
        index = if_nametoindex(ifname);
+       if (!index)
+               return -EINVAL;
 
-       return lxc_netdev_move_by_index(index, pid);
+       return lxc_netdev_move_by_index(index, pid, newname);
 }
 
 int lxc_netdev_delete_by_index(int ifindex)
 {
        struct nl_handler nlh;
        struct nlmsg *nlmsg = NULL, *answer = NULL;
-       struct link_req *link_req;
+       struct ifinfomsg *ifi;
        int err;
 
        err = netlink_open(&nlh, NETLINK_ROUTE);
@@ -163,16 +156,16 @@ int lxc_netdev_delete_by_index(int ifindex)
        if (!nlmsg)
                goto out;
 
-       answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
+       answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
        if (!answer)
                goto out;
 
-       link_req = (struct link_req *)nlmsg;
-       link_req->ifinfomsg.ifi_family = AF_UNSPEC;
-       link_req->ifinfomsg.ifi_index = ifindex;
-       nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
-       nlmsg->nlmsghdr.nlmsg_flags = NLM_F_ACK|NLM_F_REQUEST;
-       nlmsg->nlmsghdr.nlmsg_type = RTM_DELLINK;
+       nlmsg->nlmsghdr->nlmsg_flags = NLM_F_ACK|NLM_F_REQUEST;
+       nlmsg->nlmsghdr->nlmsg_type = RTM_DELLINK;
+
+       ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
+       ifi->ifi_family = AF_UNSPEC;
+       ifi->ifi_index = ifindex;
 
        err = netlink_transaction(&nlh, nlmsg, answer);
 out:
@@ -197,7 +190,7 @@ int lxc_netdev_rename_by_index(int ifindex, const char *newname)
 {
        struct nl_handler nlh;
        struct nlmsg *nlmsg = NULL, *answer = NULL;
-       struct link_req *link_req;
+       struct ifinfomsg *ifi;
        int len, err;
 
        err = netlink_open(&nlh, NETLINK_ROUTE);
@@ -213,16 +206,16 @@ int lxc_netdev_rename_by_index(int ifindex, const char *newname)
        if (!nlmsg)
                goto out;
 
-       answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
+       answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
        if (!answer)
                goto out;
 
-       link_req = (struct link_req *)nlmsg;
-       link_req->ifinfomsg.ifi_family = AF_UNSPEC;
-       link_req->ifinfomsg.ifi_index = ifindex;
-       nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
-       nlmsg->nlmsghdr.nlmsg_flags = NLM_F_ACK|NLM_F_REQUEST;
-       nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
+       nlmsg->nlmsghdr->nlmsg_flags = NLM_F_ACK|NLM_F_REQUEST;
+       nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
+
+       ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
+       ifi->ifi_family = AF_UNSPEC;
+       ifi->ifi_index = ifindex;
 
        if (nla_put_string(nlmsg, IFLA_IFNAME, newname))
                goto out;
@@ -254,7 +247,7 @@ int netdev_set_flag(const char *name, int flag)
 {
        struct nl_handler nlh;
        struct nlmsg *nlmsg = NULL, *answer = NULL;
-       struct link_req *link_req;
+       struct ifinfomsg *ifi;
        int index, len, err;
 
        err = netlink_open(&nlh, NETLINK_ROUTE);
@@ -271,7 +264,7 @@ int netdev_set_flag(const char *name, int flag)
        if (!nlmsg)
                goto out;
 
-       answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
+       answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
        if (!answer)
                goto out;
 
@@ -280,14 +273,14 @@ int netdev_set_flag(const char *name, int flag)
        if (!index)
                goto out;
 
-       link_req = (struct link_req *)nlmsg;
-       link_req->ifinfomsg.ifi_family = AF_UNSPEC;
-       link_req->ifinfomsg.ifi_index = index;
-       link_req->ifinfomsg.ifi_change |= IFF_UP;
-       link_req->ifinfomsg.ifi_flags |= flag;
-       nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
-       nlmsg->nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
-       nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
+       nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
+       nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
+
+       ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
+       ifi->ifi_family = AF_UNSPEC;
+       ifi->ifi_index = index;
+       ifi->ifi_change |= IFF_UP;
+       ifi->ifi_flags |= flag;
 
        err = netlink_transaction(&nlh, nlmsg, answer);
 out:
@@ -297,11 +290,90 @@ out:
        return err;
 }
 
+int netdev_get_flag(const char* name, int *flag)
+{
+       struct nl_handler nlh;
+       struct nlmsg *nlmsg = NULL, *answer = NULL;
+       struct ifinfomsg *ifi;
+       int index, len, err;
+
+       if (!name)
+               return -EINVAL;
+
+       err = netlink_open(&nlh, NETLINK_ROUTE);
+       if (err)
+               return err;
+
+       err = -EINVAL;
+       len = strlen(name);
+       if (len == 1 || len >= IFNAMSIZ)
+               goto out;
+
+       err = -ENOMEM;
+       nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
+       if (!nlmsg)
+               goto out;
+
+       answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
+       if (!answer)
+               goto out;
+
+       err = -EINVAL;
+       index = if_nametoindex(name);
+       if (!index)
+               goto out;
+
+       nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST;
+       nlmsg->nlmsghdr->nlmsg_type = RTM_GETLINK;
+
+       ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
+       ifi->ifi_family = AF_UNSPEC;
+       ifi->ifi_index = index;
+
+       err = netlink_transaction(&nlh, nlmsg, answer);
+       if (err)
+               goto out;
+
+       ifi = NLMSG_DATA(answer->nlmsghdr);
+
+       *flag = ifi->ifi_flags;
+out:
+       netlink_close(&nlh);
+       nlmsg_free(nlmsg);
+       nlmsg_free(answer);
+       return err;
+}
+
+/*
+ * \brief Check a interface is up or not.
+ *
+ * \param name: name for the interface.
+ *
+ * \return int.
+ * 0 means interface is down.
+ * 1 means interface is up.
+ * Others means error happened, and ret-value is the error number.
+ */
+int lxc_netdev_isup(const char* name)
+{
+       int flag;
+       int err;
+
+       err = netdev_get_flag(name, &flag);
+       if (err)
+               goto out;
+       if (flag & IFF_UP)
+               return 1;
+       return 0;
+out:
+       return err;
+}
+
 int netdev_get_mtu(int ifindex)
 {
        struct nl_handler nlh;
        struct nlmsg *nlmsg = NULL, *answer = NULL;
-       struct ip_req *ip_req;
+       struct ifinfomsg *ifi;
        struct nlmsghdr *msg;
        int err, res;
        int recv_len = 0, answer_len;
@@ -316,21 +388,20 @@ int netdev_get_mtu(int ifindex)
        if (!nlmsg)
                goto out;
 
-       answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
+       answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
        if (!answer)
                goto out;
 
        /* Save the answer buffer length, since it will be overwritten
         * on the first receive (and we might need to receive more than
         * once. */
-       answer_len = answer->nlmsghdr.nlmsg_len;
+       answer_len = answer->nlmsghdr->nlmsg_len;
+
+       nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP;
+       nlmsg->nlmsghdr->nlmsg_type = RTM_GETLINK;
 
-       ip_req = (struct ip_req *)nlmsg;
-       ip_req->nlmsg.nlmsghdr.nlmsg_len =
-               NLMSG_LENGTH(sizeof(struct ifaddrmsg));
-       ip_req->nlmsg.nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP;
-       ip_req->nlmsg.nlmsghdr.nlmsg_type = RTM_GETLINK;
-       ip_req->ifa.ifa_family = AF_UNSPEC;
+       ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
+       ifi->ifi_family = AF_UNSPEC;
 
        /* Send the request for addresses, which returns all addresses
         * on all interfaces. */
@@ -341,7 +412,7 @@ int netdev_get_mtu(int ifindex)
        do {
                /* Restore the answer buffer length, it might have been
                 * overwritten by a previous receive. */
-               answer->nlmsghdr.nlmsg_len = answer_len;
+               answer->nlmsghdr->nlmsg_len = answer_len;
 
                /* Get the (next) batch of reply messages */
                err = netlink_rcv(&nlh, answer);
@@ -352,7 +423,7 @@ int netdev_get_mtu(int ifindex)
                err = 0;
 
                /* Satisfy the typing for the netlink macros */
-               msg = &answer->nlmsghdr;
+               msg = answer->nlmsghdr;
 
                while (NLMSG_OK(msg, recv_len)) {
 
@@ -369,7 +440,7 @@ int netdev_get_mtu(int ifindex)
                                break;
                        }
 
-                       struct ifinfomsg *ifi = NLMSG_DATA(msg);
+                       ifi = NLMSG_DATA(msg);
                        if (ifi->ifi_index == ifindex) {
                                struct rtattr *rta = IFLA_RTA(ifi);
                                int attr_len = msg->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
@@ -411,7 +482,7 @@ int lxc_netdev_set_mtu(const char *name, int mtu)
 {
        struct nl_handler nlh;
        struct nlmsg *nlmsg = NULL, *answer = NULL;
-       struct link_req *link_req;
+       struct ifinfomsg *ifi;
        int index, len, err;
 
        err = netlink_open(&nlh, NETLINK_ROUTE);
@@ -428,7 +499,7 @@ int lxc_netdev_set_mtu(const char *name, int mtu)
        if (!nlmsg)
                goto out;
 
-       answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
+       answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
        if (!answer)
                goto out;
 
@@ -437,12 +508,12 @@ int lxc_netdev_set_mtu(const char *name, int mtu)
        if (!index)
                goto out;
 
-       link_req = (struct link_req *)nlmsg;
-       link_req->ifinfomsg.ifi_family = AF_UNSPEC;
-       link_req->ifinfomsg.ifi_index = index;
-       nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
-       nlmsg->nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
-       nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
+       nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
+       nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
+
+       ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
+       ifi->ifi_family = AF_UNSPEC;
+       ifi->ifi_index = index;
 
        if (nla_put_u32(nlmsg, IFLA_MTU, mtu))
                goto out;
@@ -469,7 +540,7 @@ int lxc_veth_create(const char *name1, const char *name2)
 {
        struct nl_handler nlh;
        struct nlmsg *nlmsg = NULL, *answer = NULL;
-       struct link_req *link_req;
+       struct ifinfomsg *ifi;
        struct rtattr *nest1, *nest2, *nest3;
        int len, err;
 
@@ -491,16 +562,16 @@ int lxc_veth_create(const char *name1, const char *name2)
        if (!nlmsg)
                goto out;
 
-       answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
+       answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
        if (!answer)
                goto out;
 
-       link_req = (struct link_req *)nlmsg;
-       link_req->ifinfomsg.ifi_family = AF_UNSPEC;
-       nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
-       nlmsg->nlmsghdr.nlmsg_flags =
+       nlmsg->nlmsghdr->nlmsg_flags =
                NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
-       nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
+       nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
+
+       ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
+       ifi->ifi_family = AF_UNSPEC;
 
        err = -EINVAL;
        nest1 = nla_begin_nested(nlmsg, IFLA_LINKINFO);
@@ -518,7 +589,9 @@ int lxc_veth_create(const char *name1, const char *name2)
        if (!nest3)
                goto out;
 
-       nlmsg->nlmsghdr.nlmsg_len += sizeof(struct ifinfomsg);
+       ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
+       if (!ifi)
+               goto out;
 
        if (nla_put_string(nlmsg, IFLA_IFNAME, name2))
                goto out;
@@ -545,7 +618,7 @@ int lxc_vlan_create(const char *master, const char *name, unsigned short vlanid)
 {
        struct nl_handler nlh;
        struct nlmsg *nlmsg = NULL, *answer = NULL;
-       struct link_req *link_req;
+       struct ifinfomsg *ifi;
        struct rtattr *nest, *nest2;
        int lindex, len, err;
 
@@ -567,7 +640,7 @@ int lxc_vlan_create(const char *master, const char *name, unsigned short vlanid)
        if (!nlmsg)
                goto err3;
 
-       answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
+       answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
        if (!answer)
                goto err2;
 
@@ -576,12 +649,12 @@ int lxc_vlan_create(const char *master, const char *name, unsigned short vlanid)
        if (!lindex)
                goto err1;
 
-       link_req = (struct link_req *)nlmsg;
-       link_req->ifinfomsg.ifi_family = AF_UNSPEC;
-       nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
-       nlmsg->nlmsghdr.nlmsg_flags =
+       nlmsg->nlmsghdr->nlmsg_flags =
                NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
-       nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
+       nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
+
+       ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
+       ifi->ifi_family = AF_UNSPEC;
 
        nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
        if (!nest)
@@ -621,7 +694,7 @@ int lxc_macvlan_create(const char *master, const char *name, int mode)
 {
        struct nl_handler nlh;
        struct nlmsg *nlmsg = NULL, *answer = NULL;
-       struct link_req *link_req;
+       struct ifinfomsg *ifi;
        struct rtattr *nest, *nest2;
        int index, len, err;
 
@@ -643,7 +716,7 @@ int lxc_macvlan_create(const char *master, const char *name, int mode)
        if (!nlmsg)
                goto out;
 
-       answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
+       answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
        if (!answer)
                goto out;
 
@@ -652,12 +725,12 @@ int lxc_macvlan_create(const char *master, const char *name, int mode)
        if (!index)
                goto out;
 
-       link_req = (struct link_req *)nlmsg;
-       link_req->ifinfomsg.ifi_family = AF_UNSPEC;
-       nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
-       nlmsg->nlmsghdr.nlmsg_flags =
+       nlmsg->nlmsghdr->nlmsg_flags =
                NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
-       nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
+       nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
+
+       ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
+       ifi->ifi_family = AF_UNSPEC;
 
        nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
        if (!nest)
@@ -813,7 +886,7 @@ static int ip_addr_add(int family, int ifindex,
 {
        struct nl_handler nlh;
        struct nlmsg *nlmsg = NULL, *answer = NULL;
-       struct ip_req *ip_req;
+       struct ifaddrmsg *ifa;
        int addrlen;
        int err;
 
@@ -829,20 +902,19 @@ static int ip_addr_add(int family, int ifindex,
        if (!nlmsg)
                goto out;
 
-       answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
+       answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
        if (!answer)
                goto out;
 
-       ip_req = (struct ip_req *)nlmsg;
-        ip_req->nlmsg.nlmsghdr.nlmsg_len =
-               NLMSG_LENGTH(sizeof(struct ifaddrmsg));
-        ip_req->nlmsg.nlmsghdr.nlmsg_flags =
+       nlmsg->nlmsghdr->nlmsg_flags =
                NLM_F_ACK|NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
-        ip_req->nlmsg.nlmsghdr.nlmsg_type = RTM_NEWADDR;
-       ip_req->ifa.ifa_prefixlen = prefix;
-        ip_req->ifa.ifa_index = ifindex;
-        ip_req->ifa.ifa_family = family;
-       ip_req->ifa.ifa_scope = 0;
+       nlmsg->nlmsghdr->nlmsg_type = RTM_NEWADDR;
+
+       ifa = nlmsg_reserve(nlmsg, sizeof(struct ifaddrmsg));
+       ifa->ifa_prefixlen = prefix;
+       ifa->ifa_index = ifindex;
+       ifa->ifa_family = family;
+       ifa->ifa_scope = 0;
        
        err = -EINVAL;
        if (nla_put_buffer(nlmsg, IFA_LOCAL, addr, addrlen))
@@ -887,12 +959,13 @@ int lxc_ipv4_addr_add(int ifindex, struct in_addr *addr,
  * address and stores that pointer in *res (so res should be an
  * in_addr** or in6_addr**).
  */
-static int ifa_get_local_ip(int family, struct ip_req *ip_info, void** res) {
-       struct rtattr *rta = IFA_RTA(&ip_info->ifa);
-       int attr_len = IFA_PAYLOAD(&ip_info->nlmsg.nlmsghdr);
+static int ifa_get_local_ip(int family, struct nlmsghdr *msg, void** res) {
+       struct ifaddrmsg *ifa = NLMSG_DATA(msg);
+       struct rtattr *rta = IFA_RTA(ifa);
+       int attr_len = NLMSG_PAYLOAD(msg, sizeof(struct ifaddrmsg));
        int addrlen;
 
-       if (ip_info->ifa.ifa_family != family)
+       if (ifa->ifa_family != family)
                return 0;
 
        addrlen = family == AF_INET ? sizeof(struct in_addr) :
@@ -931,7 +1004,7 @@ static int ip_addr_get(int family, int ifindex, void **res)
 {
        struct nl_handler nlh;
        struct nlmsg *nlmsg = NULL, *answer = NULL;
-       struct ip_req *ip_req, *ip_info;
+       struct ifaddrmsg *ifa;
        struct nlmsghdr *msg;
        int err;
        int recv_len = 0, answer_len;
@@ -946,21 +1019,20 @@ static int ip_addr_get(int family, int ifindex, void **res)
        if (!nlmsg)
                goto out;
 
-       answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
+       answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
        if (!answer)
                goto out;
 
        /* Save the answer buffer length, since it will be overwritten
         * on the first receive (and we might need to receive more than
         * once. */
-       answer_len = answer->nlmsghdr.nlmsg_len;
+       answer_len = answer->nlmsghdr->nlmsg_len;
+
+       nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST|NLM_F_ROOT;
+       nlmsg->nlmsghdr->nlmsg_type = RTM_GETADDR;
 
-       ip_req = (struct ip_req *)nlmsg;
-       ip_req->nlmsg.nlmsghdr.nlmsg_len =
-               NLMSG_LENGTH(sizeof(struct ifaddrmsg));
-       ip_req->nlmsg.nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_ROOT;
-       ip_req->nlmsg.nlmsghdr.nlmsg_type = RTM_GETADDR;
-       ip_req->ifa.ifa_family = family;
+       ifa = nlmsg_reserve(nlmsg, sizeof(struct ifaddrmsg));
+       ifa->ifa_family = family;
 
        /* Send the request for addresses, which returns all addresses
         * on all interfaces. */
@@ -971,7 +1043,7 @@ static int ip_addr_get(int family, int ifindex, void **res)
        do {
                /* Restore the answer buffer length, it might have been
                 * overwritten by a previous receive. */
-               answer->nlmsghdr.nlmsg_len = answer_len;
+               answer->nlmsghdr->nlmsg_len = answer_len;
 
                /* Get the (next) batch of reply messages */
                err = netlink_rcv(&nlh, answer);
@@ -982,7 +1054,7 @@ static int ip_addr_get(int family, int ifindex, void **res)
                err = 0;
 
                /* Satisfy the typing for the netlink macros */
-               msg = &answer->nlmsghdr;
+               msg = answer->nlmsghdr;
 
                while (NLMSG_OK(msg, recv_len)) {
                        /* Stop reading if we see an error message */
@@ -1003,9 +1075,9 @@ static int ip_addr_get(int family, int ifindex, void **res)
                                goto out;
                        }
 
-                       ip_info = (struct ip_req *)msg;
-                       if (ip_info->ifa.ifa_index == ifindex) {
-                               if (ifa_get_local_ip(family, ip_info, res) < 0) {
+                       ifa = (struct ifaddrmsg *)NLMSG_DATA(msg);
+                       if (ifa->ifa_index == ifindex) {
+                               if (ifa_get_local_ip(family, msg, res) < 0) {
                                        err = -1;
                                        goto out;
                                }
@@ -1049,7 +1121,7 @@ static int ip_gateway_add(int family, int ifindex, void *gw)
 {
        struct nl_handler nlh;
        struct nlmsg *nlmsg = NULL, *answer = NULL;
-       struct rt_req *rt_req;
+       struct rtmsg *rt;
        int addrlen;
        int err;
 
@@ -1065,23 +1137,22 @@ static int ip_gateway_add(int family, int ifindex, void *gw)
        if (!nlmsg)
                goto out;
 
-       answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
+       answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
        if (!answer)
                goto out;
 
-       rt_req = (struct rt_req *)nlmsg;
-       rt_req->nlmsg.nlmsghdr.nlmsg_len =
-               NLMSG_LENGTH(sizeof(struct rtmsg));
-       rt_req->nlmsg.nlmsghdr.nlmsg_flags =
+       nlmsg->nlmsghdr->nlmsg_flags =
                NLM_F_ACK|NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
-       rt_req->nlmsg.nlmsghdr.nlmsg_type = RTM_NEWROUTE;
-       rt_req->rt.rtm_family = family;
-       rt_req->rt.rtm_table = RT_TABLE_MAIN;
-       rt_req->rt.rtm_scope = RT_SCOPE_UNIVERSE;
-       rt_req->rt.rtm_protocol = RTPROT_BOOT;
-       rt_req->rt.rtm_type = RTN_UNICAST;
+       nlmsg->nlmsghdr->nlmsg_type = RTM_NEWROUTE;
+
+       rt = nlmsg_reserve(nlmsg, sizeof(struct rtmsg));
+       rt->rtm_family = family;
+       rt->rtm_table = RT_TABLE_MAIN;
+       rt->rtm_scope = RT_SCOPE_UNIVERSE;
+       rt->rtm_protocol = RTPROT_BOOT;
+       rt->rtm_type = RTN_UNICAST;
        /* "default" destination */
-       rt_req->rt.rtm_dst_len = 0;
+       rt->rtm_dst_len = 0;
 
        err = -EINVAL;
        if (nla_put_buffer(nlmsg, RTA_GATEWAY, gw, addrlen))
@@ -1114,7 +1185,7 @@ static int ip_route_dest_add(int family, int ifindex, void *dest)
 {
        struct nl_handler nlh;
        struct nlmsg *nlmsg = NULL, *answer = NULL;
-       struct rt_req *rt_req;
+       struct rtmsg *rt;
        int addrlen;
        int err;
        
@@ -1130,22 +1201,21 @@ static int ip_route_dest_add(int family, int ifindex, void *dest)
        if (!nlmsg)
                goto out;
        
-       answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
+       answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
        if (!answer)
                goto out;
        
-       rt_req = (struct rt_req *)nlmsg;
-       rt_req->nlmsg.nlmsghdr.nlmsg_len =
-               NLMSG_LENGTH(sizeof(struct rtmsg));
-       rt_req->nlmsg.nlmsghdr.nlmsg_flags =
+       nlmsg->nlmsghdr->nlmsg_flags =
                NLM_F_ACK|NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
-       rt_req->nlmsg.nlmsghdr.nlmsg_type = RTM_NEWROUTE;
-       rt_req->rt.rtm_family = family;
-       rt_req->rt.rtm_table = RT_TABLE_MAIN;
-       rt_req->rt.rtm_scope = RT_SCOPE_LINK;
-       rt_req->rt.rtm_protocol = RTPROT_BOOT;
-       rt_req->rt.rtm_type = RTN_UNICAST;
-       rt_req->rt.rtm_dst_len = addrlen*8;
+       nlmsg->nlmsghdr->nlmsg_type = RTM_NEWROUTE;
+
+       rt = nlmsg_reserve(nlmsg, sizeof(struct rtmsg));
+       rt->rtm_family = family;
+       rt->rtm_table = RT_TABLE_MAIN;
+       rt->rtm_scope = RT_SCOPE_LINK;
+       rt->rtm_protocol = RTPROT_BOOT;
+       rt->rtm_type = RTN_UNICAST;
+       rt->rtm_dst_len = addrlen*8;
        
        err = -EINVAL;
        if (nla_put_buffer(nlmsg, RTA_DST, dest, addrlen))
index 079d52a..cd42c8f 100644 (file)
@@ -31,8 +31,8 @@ extern int lxc_convert_mac(char *macaddr, struct sockaddr *sockaddr);
 /*
  * Move a device between namespaces
  */
-extern int lxc_netdev_move_by_index(int ifindex, pid_t pid);
-extern int lxc_netdev_move_by_name(char *ifname, pid_t pid);
+extern int lxc_netdev_move_by_index(int ifindex, pid_t pid, const char* ifname);
+extern int lxc_netdev_move_by_name(const char *ifname, pid_t pid, const char* newname);
 
 /*
  * Delete a network device
@@ -51,6 +51,8 @@ extern int netdev_set_flag(const char *name, int flag);
 /*
  * Set the device network up or down
  */
+
+extern int lxc_netdev_isup(const char *name);
 extern int lxc_netdev_up(const char *name);
 extern int lxc_netdev_down(const char *name);
 
index 7c0f1e5..dd044f0 100644 (file)
 
 extern size_t nlmsg_len(const struct nlmsg *nlmsg)
 {
-       return nlmsg->nlmsghdr.nlmsg_len - NLMSG_HDRLEN;
+       return nlmsg->nlmsghdr->nlmsg_len - NLMSG_HDRLEN;
 }
 
 extern void *nlmsg_data(struct nlmsg *nlmsg)
 {
-       char *data = ((char *)nlmsg) + NLMSG_ALIGN(sizeof(struct nlmsghdr));
+       char *data = ((char *)nlmsg) + NLMSG_HDRLEN;
        if (!nlmsg_len(nlmsg))
                return NULL;
        return data;
@@ -53,13 +53,16 @@ static int nla_put(struct nlmsg *nlmsg, int attr,
 {
        struct rtattr *rta;
        size_t rtalen = RTA_LENGTH(len);
+       size_t tlen = NLMSG_ALIGN(nlmsg->nlmsghdr->nlmsg_len) + RTA_ALIGN(rtalen);
        
-        rta = NLMSG_TAIL(&nlmsg->nlmsghdr);
-        rta->rta_type = attr;
-        rta->rta_len = rtalen;
-        memcpy(RTA_DATA(rta), data, len);
-        nlmsg->nlmsghdr.nlmsg_len =
-               NLMSG_ALIGN(nlmsg->nlmsghdr.nlmsg_len) + RTA_ALIGN(rtalen);
+       if (tlen > nlmsg->cap)
+               return -ENOMEM;
+
+       rta = NLMSG_TAIL(nlmsg->nlmsghdr);
+       rta->rta_type = attr;
+       rta->rta_len = rtalen;
+       memcpy(RTA_DATA(rta), data, len);
+       nlmsg->nlmsghdr->nlmsg_len = tlen;
        return 0;
 }
 
@@ -91,7 +94,7 @@ extern int nla_put_attr(struct nlmsg *nlmsg, int attr)
 
 struct rtattr *nla_begin_nested(struct nlmsg *nlmsg, int attr)
 {
-       struct rtattr *rtattr = NLMSG_TAIL(&nlmsg->nlmsghdr);
+       struct rtattr *rtattr = NLMSG_TAIL(nlmsg->nlmsghdr);
 
        if (nla_put_attr(nlmsg, attr))
                return NULL;
@@ -101,26 +104,69 @@ struct rtattr *nla_begin_nested(struct nlmsg *nlmsg, int attr)
 
 void nla_end_nested(struct nlmsg *nlmsg, struct rtattr *attr)
 {
-       attr->rta_len = (void *)NLMSG_TAIL(&nlmsg->nlmsghdr) - (void *)attr;
+       attr->rta_len = (void *)NLMSG_TAIL(nlmsg->nlmsghdr) - (void *)attr;
 }
 
 extern struct nlmsg *nlmsg_alloc(size_t size)
 {
        struct nlmsg *nlmsg;
-       size_t len = NLMSG_ALIGN(size) + NLMSG_ALIGN(sizeof(struct nlmsghdr *));
+       size_t len = NLMSG_HDRLEN + NLMSG_ALIGN(size);
 
-       nlmsg = (struct nlmsg *)malloc(len);
+       nlmsg = (struct nlmsg *)malloc(sizeof(struct nlmsg));
        if (!nlmsg)
                return NULL;
 
-       memset(nlmsg, 0, len);
-       nlmsg->nlmsghdr.nlmsg_len = NLMSG_ALIGN(size);
+       nlmsg->nlmsghdr = (struct nlmsghdr *)malloc(len);
+       if (!nlmsg->nlmsghdr)
+               goto errout;
+
+       memset(nlmsg->nlmsghdr, 0, len);
+       nlmsg->cap = len;
+       nlmsg->nlmsghdr->nlmsg_len = NLMSG_HDRLEN;
 
        return nlmsg;
+errout:
+       free(nlmsg);
+       return NULL;
+}
+
+extern void *nlmsg_reserve(struct nlmsg *nlmsg, size_t len)
+{
+       void *buf;
+       size_t nlmsg_len = nlmsg->nlmsghdr->nlmsg_len;
+       size_t tlen = NLMSG_ALIGN(len);
+
+       if (nlmsg_len + tlen > nlmsg->cap)
+               return NULL;
+
+       buf = ((char *)(nlmsg->nlmsghdr)) + nlmsg_len;
+       nlmsg->nlmsghdr->nlmsg_len += tlen;
+
+       if (tlen > len)
+               memset(buf + len, 0, tlen - len);
+
+       return buf;
+}
+
+extern struct nlmsg *nlmsg_alloc_reserve(size_t size)
+{
+       struct nlmsg *nlmsg;
+
+       nlmsg = nlmsg_alloc(size);
+       if (!nlmsg)
+               return NULL;
+
+       // just set message length to cap directly
+       nlmsg->nlmsghdr->nlmsg_len = nlmsg->cap;
+       return nlmsg;
 }
 
 extern void nlmsg_free(struct nlmsg *nlmsg)
 {
+       if (!nlmsg)
+               return;
+
+       free(nlmsg->nlmsghdr);
        free(nlmsg);
 }
 
@@ -129,8 +175,8 @@ extern int netlink_rcv(struct nl_handler *handler, struct nlmsg *answer)
        int ret;
         struct sockaddr_nl nladdr;
         struct iovec iov = {
-                .iov_base = answer,
-                .iov_len = answer->nlmsghdr.nlmsg_len,
+                .iov_base = answer->nlmsghdr,
+                .iov_len = answer->nlmsghdr->nlmsg_len,
         };
        
        struct msghdr msg = {
@@ -157,7 +203,7 @@ again:
                return 0;
 
        if (msg.msg_flags & MSG_TRUNC &&
-           ret == answer->nlmsghdr.nlmsg_len)
+           ret == answer->nlmsghdr->nlmsg_len)
                return -EMSGSIZE;
 
        return ret;
@@ -167,8 +213,8 @@ extern int netlink_send(struct nl_handler *handler, struct nlmsg *nlmsg)
 {
         struct sockaddr_nl nladdr;
         struct iovec iov = {
-                .iov_base = (void*)nlmsg,
-                .iov_len = nlmsg->nlmsghdr.nlmsg_len,
+                .iov_base = nlmsg->nlmsghdr,
+                .iov_len = nlmsg->nlmsghdr->nlmsg_len,
         };
        struct msghdr msg = {
                 .msg_name = &nladdr,
@@ -206,8 +252,8 @@ extern int netlink_transaction(struct nl_handler *handler,
        if (ret < 0)
                return ret;
 
-       if (answer->nlmsghdr.nlmsg_type == NLMSG_ERROR) {
-               struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(answer);
+       if (answer->nlmsghdr->nlmsg_type == NLMSG_ERROR) {
+               struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(answer->nlmsghdr);
                return err->error;
        }
 
index 8e737fc..f6f2fd0 100644 (file)
@@ -53,14 +53,16 @@ struct nl_handler {
 };
 
 /*
- * struct nlmsg : the netlink message structure, it consists just
- *  on a definition for a nlmsghdr. This message is to be used to
+ * struct nlmsg : the netlink message structure. This message is to be used to
  *  be allocated with netlink_alloc.
- * @nlmsghdr : a pointer to a netlink message header, this field
- *   _must_ be always the first field of this structure
+ *
+ * @nlmsghdr: a pointer to a netlink message header
+ * @cap: capacity of the netlink message, this is the initially allocated size
+ *             and later operations (e.g. reserve and put) can not exceed this limit.
  */
 struct nlmsg {
-       struct nlmsghdr nlmsghdr;
+       struct nlmsghdr *nlmsghdr;
+       ssize_t cap;
 };
 
 /*
@@ -210,16 +212,35 @@ void nla_end_nested(struct nlmsg *nlmsg, struct rtattr *attr);
  *  is sizeof(header) + sizeof(padding) + payloadsize + sizeof(padding),
  *  in other words, the function will allocate more than specified. When
  *  the buffer is allocated, the content is zeroed.
- *  The function will also fill the field nlmsg_len with computed size.
+ *  The function will also fill the field nlmsg_len with NLMSG_HDRLEN.
  *  If the allocation must be for the specified size, just use malloc.
  *
- * @size: the size of the payload to be allocated
+ * @size: the capacity of the payload to be allocated
  *
  * Returns a pointer to the newly allocated netlink message, NULL otherwise
  */
 struct nlmsg *nlmsg_alloc(size_t size);
 
 /*
+ * nlmsg_alloc_reserve: like nlmsg_alloc(), but reserve the whole payload
+ *  after allocated, that is, the field nlmsg_len be set to the capacity
+ *  of nlmsg. Often used to allocate a message for the reply.
+ *
+ * @size: the capacity of the payload to be allocated.
+ */
+struct nlmsg *nlmsg_alloc_reserve(size_t size);
+
+/*
+ * Reserve room for additional data at the tail of a netlink message
+ *
+ * @nlmsg: the netlink message
+ * @len: length of additional data to reserve room for
+ *
+ * Returns a pointer to newly reserved room or NULL
+ */
+void *nlmsg_reserve(struct nlmsg *nlmsg, size_t len);
+
+/*
  * nlmsg_free : free a previously allocate message
  *
  * @nlmsg: the netlink message to be freed
index 90572f0..4d84794 100644 (file)
@@ -722,7 +722,7 @@ static int do_start(void *data)
        }
 
        /* The clearenv() and putenv() calls have been moved here
-        * to allow us to use enviroment variables passed to the various
+        * to allow us to use environment variables passed to the various
         * hooks, such as the start hook above.  Not all of the
         * variables like CONFIG_PATH or ROOTFS are valid in this
         * context but others are. */
@@ -1066,6 +1066,7 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
                                ERROR("Error unsharing mounts");
                                goto out_fini_nonet;
                        }
+                       remount_all_slave();
                        if (do_rootfs_setup(conf, name, lxcpath) < 0) {
                                ERROR("Error setting up rootfs mount as root before spawn");
                                goto out_fini_nonet;
index efec414..5ef04fc 100644 (file)
@@ -238,7 +238,7 @@ const char *lxc_global_config_value(const char *option_name)
                { "lxc.bdev.zfs.root",      DEFAULT_ZFSROOT },
                { "lxc.lxcpath",            NULL            },
                { "lxc.default_config",     NULL            },
-               { "lxc.cgroup.pattern",     DEFAULT_CGROUP_PATTERN },
+               { "lxc.cgroup.pattern",     NULL            },
                { "lxc.cgroup.use",         NULL            },
                { NULL, NULL },
        };
@@ -249,9 +249,17 @@ const char *lxc_global_config_value(const char *option_name)
 #else
        static const char *values[sizeof(options) / sizeof(options[0])] = { 0 };
 #endif
+
+       /* user_config_path is freed as soon as it is used */
        char *user_config_path = NULL;
+
+       /*
+        * The following variables are freed at bottom unconditionally.
+        * So NULL the value if it is to be returned to the caller
+        */
        char *user_default_config_path = NULL;
        char *user_lxc_path = NULL;
+       char *user_cgroup_pattern = NULL;
 
        if (geteuid() > 0) {
                const char *user_home = getenv("HOME");
@@ -265,11 +273,13 @@ const char *lxc_global_config_value(const char *option_name)
                sprintf(user_config_path, "%s/.config/lxc/lxc.conf", user_home);
                sprintf(user_default_config_path, "%s/.config/lxc/default.conf", user_home);
                sprintf(user_lxc_path, "%s/.local/share/lxc/", user_home);
+               user_cgroup_pattern = strdup("%n");
        }
        else {
                user_config_path = strdup(LXC_GLOBAL_CONF);
                user_default_config_path = strdup(LXC_DEFAULT_CONFIG);
                user_lxc_path = strdup(LXCPATH);
+               user_cgroup_pattern = strdup(DEFAULT_CGROUP_PATTERN);
        }
 
        const char * const (*ptr)[2];
@@ -285,6 +295,7 @@ const char *lxc_global_config_value(const char *option_name)
                free(user_config_path);
                free(user_default_config_path);
                free(user_lxc_path);
+               free(user_cgroup_pattern);
                errno = EINVAL;
                return NULL;
        }
@@ -293,6 +304,7 @@ const char *lxc_global_config_value(const char *option_name)
                free(user_config_path);
                free(user_default_config_path);
                free(user_lxc_path);
+               free(user_cgroup_pattern);
                return values[i];
        }
 
@@ -331,18 +343,16 @@ const char *lxc_global_config_value(const char *option_name)
                        if (!*p)
                                continue;
 
-                       free(user_default_config_path);
-
                        if (strcmp(option_name, "lxc.lxcpath") == 0) {
                                free(user_lxc_path);
                                user_lxc_path = copy_global_config_value(p);
                                remove_trailing_slashes(user_lxc_path);
                                values[i] = user_lxc_path;
+                               user_lxc_path = NULL;
                                goto out;
                        }
 
                        values[i] = copy_global_config_value(p);
-                       free(user_lxc_path);
                        goto out;
                }
        }
@@ -350,17 +360,19 @@ const char *lxc_global_config_value(const char *option_name)
        if (strcmp(option_name, "lxc.lxcpath") == 0) {
                remove_trailing_slashes(user_lxc_path);
                values[i] = user_lxc_path;
-               free(user_default_config_path);
+               user_lxc_path = NULL;
        }
        else if (strcmp(option_name, "lxc.default_config") == 0) {
                values[i] = user_default_config_path;
-               free(user_lxc_path);
+               user_default_config_path = NULL;
        }
-       else {
-               free(user_default_config_path);
-               free(user_lxc_path);
-               values[i] = (*ptr)[1];
+       else if (strcmp(option_name, "lxc.cgroup.pattern") == 0) {
+               values[i] = user_cgroup_pattern;
+               user_cgroup_pattern = NULL;
        }
+       else
+               values[i] = (*ptr)[1];
+
        /* special case: if default value is NULL,
         * and there is no config, don't view that
         * as an error... */
@@ -371,6 +383,10 @@ out:
        if (fin)
                fclose(fin);
 
+       free(user_cgroup_pattern);
+       free(user_default_config_path);
+       free(user_lxc_path);
+
        return values[i];
 }
 
index 66864f2..00fcbe9 100644 (file)
@@ -25,7 +25,7 @@
 
 #define LXC_VERSION_MAJOR 1
 #define LXC_VERSION_MINOR 0
-#define LXC_VERSION_MICRO 6
-#define LXC_VERSION "1.0.6"
+#define LXC_VERSION_MICRO 7
+#define LXC_VERSION "1.0.7"
 
 #endif
index 6b4fceb..19a4205 100644 (file)
@@ -73,7 +73,6 @@ EXTRA_DIST = \
        lxc-test-autostart \
        lxc-test-ubuntu \
        lxc-test-unpriv \
-       lxc-test-usernic \
        may_control.c \
        saveconfig.c \
        shutdowntest.c \
index 3ebced5..0d7062d 100644 (file)
@@ -565,7 +565,6 @@ EXTRA_DIST = \
        lxc-test-autostart \
        lxc-test-ubuntu \
        lxc-test-unpriv \
-       lxc-test-usernic \
        may_control.c \
        saveconfig.c \
        shutdowntest.c \
index 9230853..d093a02 100644 (file)
@@ -48,7 +48,7 @@ static int destroy_busybox(void)
 again:
        ret = waitpid(pid, &status, 0);
        if (ret == -1) {
-               if (errno == -EINTR)
+               if (errno == EINTR)
                        goto again;
                perror("waitpid");
                return -1;
@@ -80,7 +80,7 @@ static int create_busybox(void)
 again:
        ret = waitpid(pid, &status, 0);
        if (ret == -1) {
-               if (errno == -EINTR)
+               if (errno == EINTR)
                        goto again;
                perror("waitpid");
                return -1;
index 4bb6aae..eaf3c84 100644 (file)
@@ -46,7 +46,7 @@ static int create_container(void)
 again:
        ret = waitpid(pid, &status, 0);
        if (ret == -1) {
-               if (errno == -EINTR)
+               if (errno == EINTR)
                        goto again;
                perror("waitpid");
                return -1;
index d9c5aef..abf50e8 100644 (file)
@@ -237,6 +237,30 @@ int main(int argc, char *argv[])
                goto out;
        }
 
+       if (!c->set_config_item(c, "lxc.network.ipv4.gateway", "10.2.3.254")) {
+               fprintf(stderr, "%d: failed to set ipv4.gateway\n", __LINE__);
+               ret = 1;
+               goto out;
+       }
+
+       ret = c->get_config_item(c, "lxc.network.0.ipv4.gateway", v2, 255);
+       if (ret <= 0) {
+               fprintf(stderr, "%d: lxc.network.0.ipv4.gateway returned %d\n", __LINE__, ret);
+               ret = 1;
+               goto out;
+       }
+       if (!c->clear_config_item(c, "lxc.network.0.ipv4.gateway")) {
+               fprintf(stderr, "%d: failed clearing ipv4.gateway\n", __LINE__);
+               ret = 1;
+               goto out;
+       }
+       ret = c->get_config_item(c, "lxc.network.0.ipv4.gateway", v2, 255);
+       if (ret != 0) {
+               fprintf(stderr, "%d: after clearing ipv4.gateway get_item(lxc.network.0.ipv4.gateway returned %d\n", __LINE__, ret);
+               ret = 1;
+               goto out;
+       }
+
        ret = c->get_config_item(c, "lxc.network.0.link", v2, 255);
        if (ret < 0) {
                fprintf(stderr, "%d: get_config_item returned %d\n", __LINE__, ret);
index 6235901..93c91a9 100755 (executable)
@@ -73,7 +73,7 @@ deluser $TUSER && rm -Rf $HDIR || true
 useradd $TUSER
 
 mkdir -p $HDIR
-echo "$TUSER veth lxcbr0 2" > /etc/lxc/lxc-usernet
+echo "$TUSER veth lxcbr0 2" >> /etc/lxc/lxc-usernet
 sed -i '/^lxcunpriv:/d' /etc/subuid /etc/subgid
 
 usermod -v 910000-919999 -w 910000-919999 $TUSER
@@ -141,4 +141,22 @@ p1=$(run_cmd lxc-info -n c2 -p -H)
 
 run_cmd lxc-stop -n c2
 
+if which cgm >/dev/null 2>&1; then
+    echo "Testing containers under different cgroups per subsystem"
+    run_cmd cgm create freezer x1/x2
+    cgm movepid freezer x1 $$
+    run_cmd lxc-start -n c1 -d
+    p1=$(run_cmd lxc-info -n c1 -p -H)
+    [ "$p1" != "-1" ] || { echo "Failed to start container c1"; false; }
+    run_cmd lxc-info -n c1
+    run_cmd lxc-attach -n c1 -- /bin/true
+    run_cmd lxc-cgroup -n c1 freezer.state
+
+    echo "Testing lxc-attach and lxc-cgroup from different cgroup"
+    cgm movepid freezer x2 $$
+    run_cmd lxc-attach -n c1 -- /bin/true
+    run_cmd lxc-cgroup -n c1 freezer.state
+    run_cmd lxc-cgroup -n c1 memory.limit_in_bytes
+fi
+
 DONE=1
diff --git a/src/tests/lxc-test-usernic b/src/tests/lxc-test-usernic
deleted file mode 100644 (file)
index e6e3b6a..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-#!/bin/bash
-
-# lxc: linux Container library
-
-# Authors:
-# Serge Hallyn <serge.hallyn@ubuntu.com>
-#
-# This is a test script for the lxc-user-nic program
-
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# Lesser General Public License for more details.
-
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-# This test assumes an Ubuntu host
-
-DONE=0
-LXC_USER_NIC="/usr/local/libexec/lxc/lxc-user-nic"
-
-cleanup() {
-       (
-               set +e
-
-               lxc-stop -n usernic-c1 -k
-               lxc-destroy -n usernic-c1
-
-               sed -i '/usernic-user/d' /run/lxc/nics /etc/lxc/lxc-usernet
-               ifconfig usernic-br0 down
-               ifconfig usernic-br1 down
-               brctl delbr usernic-br0
-               brctl delbr usernic-br1
-
-               run_cmd "lxc-stop -n b1 -k"
-               pkill -u $(id -u usernic-user) -9
-
-               rm -rf /tmp/usernic-test /home/usernic-user /run/user/$(id -u usernic-user)
-
-               deluser usernic-user
-       ) >/dev/null 2>&1
-
-       if [ "$DONE" = "1" ]; then
-               echo "PASS"
-               exit 0
-       fi
-
-       echo "FAIL"
-       exit 1
-}
-
-run_cmd() {
-       sudo -i -u usernic-user \
-           env http_proxy=${http_proxy:-} https_proxy=${https_proxy:-} \
-               XDG_RUNTIME_DIR=/run/user/$(id -u usernic-user) $*
-}
-
-ARCH=i386
-if type dpkg >/dev/null 2>&1; then
-       ARCH=$(dpkg --print-architecture)
-fi
-
-set -eu
-trap cleanup EXIT SIGHUP SIGINT SIGTERM
-
-# create a test user
-deluser usernic-user || true
-useradd usernic-user
-sudo mkdir -p /home/usernic-user
-sudo chown usernic-user: /home/usernic-user
-usermod -v 910000-919999 -w 910000-919999 usernic-user
-
-mkdir -p /home/usernic-user/.config/lxc/
-cat > /home/usernic-user/.config/lxc/default.conf << EOF
-lxc.network.type = empty
-lxc.id_map = u 0 910000 10000
-lxc.id_map = g 0 910000 10000
-EOF
-
-if which cgm >/dev/null 2>&1; then
-       cgm create all $TUSER
-       cgm chown all $TUSER $(id -u $TUSER) $(id -g $TUSER)
-       cgm movepid all $TUSER $$
-elif [ -e /sys/fs/cgroup/cgmanager/sock ]; then
-       for d in $(cut -d : -f 2 /proc/self/cgroup); do
-               dbus-send --print-reply --address=unix:path=/sys/fs/cgroup/cgmanager/sock \
-                       --type=method_call /org/linuxcontainers/cgmanager org.linuxcontainers.cgmanager0_0.Create \
-                       string:$d string:usernic-user >/dev/null
-
-               dbus-send --print-reply --address=unix:path=/sys/fs/cgroup/cgmanager/sock \
-                       --type=method_call /org/linuxcontainers/cgmanager org.linuxcontainers.cgmanager0_0.Chown \
-                       string:$d string:usernic-user int32:$(id -u usernic-user) int32:$(id -g usernic-user) >/dev/null
-
-               dbus-send --print-reply --address=unix:path=/sys/fs/cgroup/cgmanager/sock \
-                       --type=method_call /org/linuxcontainers/cgmanager org.linuxcontainers.cgmanager0_0.MovePid \
-                       string:$d string:usernic-user int32:$$ >/dev/null
-       done
-else
-       for d in /sys/fs/cgroup/*; do
-               [ ! -d $d/lxctest ] && mkdir $d/lxctest
-               chown -R usernic-user: $d/lxctest
-               echo $$ > $d/lxctest/tasks
-       done
-fi
-
-mkdir -p /run/user/$(id -u usernic-user)
-chown -R usernic-user: /run/user/$(id -u usernic-user) /home/usernic-user
-
-# Copy the download template cache if available
-run_cmd "mkdir -p /home/usernic-user/.cache/lxc"
-[ -d /var/cache/lxc/download ] && \
-    cp -R /var/cache/lxc/download /home/usernic-user/.cache/lxc && \
-    chown -R usernic-user: /home/usernic-user/.cache/lxc
-
-
-# Create two test bridges
-brctl addbr usernic-br0
-brctl addbr usernic-br1
-ifconfig usernic-br0 0.0.0.0 up
-ifconfig usernic-br1 0.0.0.0 up
-
-ARCH=i386
-if type dpkg >/dev/null 2>&1; then
-       ARCH=$(dpkg --print-architecture)
-fi
-
-# Create three containers
-run_cmd "lxc-create -t download -n b1 -- -d ubuntu -r trusty -a $ARCH"
-run_cmd "lxc-start -n b1 -d"
-p1=$(run_cmd "lxc-info -n b1 -p -H")
-
-# Assign one veth, should fail as no allowed entries yet
-if run_cmd "$LXC_USER_NIC $p1 veth usernic-br0 xx1"; then
-       echo "FAIL: able to create nic with no entries"
-       exit 1
-fi
-
-# Give him a quota of two
-touch /etc/lxc/lxc-usernet
-sed -i '/^usernic-user/d' /etc/lxc/lxc-usernet
-echo "usernic-user veth usernic-br0 2" >> /etc/lxc/lxc-usernet
-
-# Assign one veth to second bridge, should fail
-if run_cmd "$LXC_USER_NIC $p1 veth usernic-br1 xx1"; then
-       echo "FAIL: able to create nic with no entries"
-       exit 1
-fi
-
-# Assign two veths, should succeed
-if ! run_cmd "$LXC_USER_NIC $p1 veth usernic-br0 xx2"; then
-       echo "FAIL: unable to create first nic"
-       exit 1
-fi
-
-if ! run_cmd "$LXC_USER_NIC $p1 veth usernic-br0 xx3"; then
-       echo "FAIL: unable to create second nic"
-       exit 1
-fi
-
-# Assign one more veth, should fail.
-if run_cmd "$LXC_USER_NIC $p1 veth usernic-br0 xx4"; then
-       echo "FAIL: able to create third nic"
-       exit 1
-fi
-
-# Shut down and restart the container, should be able to assign more nics
-run_cmd "lxc-stop -n b1 -k"
-run_cmd "lxc-start -n b1 -d"
-p1=$(run_cmd "lxc-info -n b1 -p -H")
-
-if ! run_cmd "$LXC_USER_NIC $p1 veth usernic-br0 xx5"; then
-       echo "FAIL: unable to create nic after destroying the old"
-       cleanup 1
-fi
-
-run_cmd "lxc-stop -n b1 -k"
-
-# Create a root-owned ns
-lxc-create -t busybox -n usernic-c1
-lxc-start -n usernic-c1 -d
-p2=$(lxc-info -n usernic-c1 -p -H)
-
-# assign veth to it - should fail
-if run_cmd "$LXC_USER_NIC $p2 veth usernic-br0 xx6"; then
-       echo "FAIL: able to attach nic to root-owned container"
-       cleanup 1
-fi
-
-echo "All tests passed"
-DONE=1
index 8d78fea..75dd984 100755 (executable)
@@ -85,9 +85,9 @@ lxc.id_map = g 0 910000 10000
 EOF
 
 if which cgm >/dev/null 2>&1; then
-       cgm create all $TUSER
-       cgm chown all $TUSER $(id -u $TUSER) $(id -g $TUSER)
-       cgm movepid all $TUSER $$
+       cgm create all usernic-user
+       cgm chown all usernic-user $(id -u usernic-user) $(id -g usernic-user)
+       cgm movepid all usernic-user $$
 elif [ -e /sys/fs/cgroup/cgmanager/sock ]; then
        for d in $(cut -d : -f 2 /proc/self/cgroup); do
                dbus-send --print-reply --address=unix:path=/sys/fs/cgroup/cgmanager/sock \
index de2fa82..d8a4ca2 100644 (file)
@@ -46,7 +46,7 @@ static int create_container(void)
 again:
        ret = waitpid(pid, &status, 0);
        if (ret == -1) {
-               if (errno == -EINTR)
+               if (errno == EINTR)
                        goto again;
                perror("waitpid");
                return -1;
index 9dd4ec3..6b7344f 100644 (file)
@@ -48,7 +48,7 @@ static int destroy_container(void)
 again:
        ret = waitpid(pid, &status, 0);
        if (ret == -1) {
-               if (errno == -EINTR)
+               if (errno == EINTR)
                        goto again;
                perror("waitpid");
                return -1;
@@ -80,7 +80,7 @@ static int create_container(void)
 again:
        ret = waitpid(pid, &status, 0);
        if (ret == -1) {
-               if (errno == -EINTR)
+               if (errno == EINTR)
                        goto again;
                perror("waitpid");
                return -1;
index 7a22d5e..ba27aea 100644 (file)
@@ -121,6 +121,7 @@ configure_alpine() {
     cat >"$rootfs"/etc/inittab<<EOF
 ::sysinit:/sbin/rc sysinit
 ::wait:/sbin/rc default
+console:12345:respawn:/sbin/getty 38400 console
 tty1:12345:respawn:/sbin/getty 38400 tty1
 tty2:12345:respawn:/sbin/getty 38400 tty2
 tty3:12345:respawn:/sbin/getty 38400 tty3
@@ -246,7 +247,7 @@ lxc.cgroup.devices.allow = c 254:0 rm
 lxc.mount.entry=proc proc proc nodev,noexec,nosuid 0 0
 lxc.mount.entry=run run tmpfs nodev,noexec,nosuid,relatime,size=1m,mode=0755 0 0
 lxc.mount.entry=none dev/pts devpts gid=5,mode=620 0 0
-lxc.mount.entry=shm dev/shm tmpfs nodev,nosuid,noexec 0 0
+lxc.mount.entry=shm dev/shm tmpfs nodev,nosuid,noexec,mode=1777 0 0
 
 EOF
 
index 246e743..ee54a7a 100644 (file)
 # License along with this library; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
-# Detect use under userns (unsupported)
-for arg in "$@"; do
-    [ "$arg" = "--" ] && break
-    if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
-        echo "This template can't be used for unprivileged containers." 1>&2
-        echo "You may want to try the \"download\" template instead." 1>&2
-        exit 1
-    fi
-done
+LXC_MAPPED_UID=
+LXC_MAPPED_GID=
 
 # Make sure the usual locations are in PATH
 export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
@@ -308,6 +301,25 @@ EOF
     done
     echo "lxc.mount.entry = /sys/kernel/security sys/kernel/security none ro,bind,optional 0 0" >>$path/config
     echo "lxc.mount.auto = proc:mixed sys" >>$path/config
+
+    if [ -f "$path/fstab" ]; then
+        echo "lxc.mount = $path/fstab" >>$path/config
+    fi
+}
+
+remap_userns()
+{
+    path=$1
+
+    if [ -n "$LXC_MAPPED_UID" ] && [ "$LXC_MAPPED_UID" != "-1" ]; then
+        chown $LXC_MAPPED_UID $path/config $path/fstab >/dev/null 2>&1
+        chown -R root $path/rootfs >/dev/null 2>&1
+    fi
+
+    if [ -n "$LXC_MAPPED_GID" ] && [ "$LXC_MAPPED_GID" != "-1" ]; then
+        chgrp $LXC_MAPPED_GID $path/config $path/fstab >/dev/null 2>&1
+        chgrp -R root $path/rootfs >/dev/null 2>&1
+    fi
 }
 
 usage()
@@ -318,7 +330,7 @@ EOF
     return 0
 }
 
-options=$(getopt -o hp:n: -l help,rootfs:,path:,name: -- "$@")
+options=$(getopt -o hp:n: -l help,rootfs:,path:,name:,mapped-uid:,mapped-gid: -- "$@")
 if [ $? -ne 0 ]; then
     usage $(basename $0)
     exit 1
@@ -332,6 +344,8 @@ do
         -p|--path)      path=$2; shift 2;;
         --rootfs)       rootfs=$2; shift 2;;
         -n|--name)      name=$2; shift 2;;
+        --mapped-uid)   LXC_MAPPED_UID=$2; shift 2;;
+        --mapped-gid)   LXC_MAPPED_GID=$2; shift 2;;
         --)             shift 1; break ;;
         *)              break ;;
     esac
@@ -374,3 +388,9 @@ if [ $? -ne 0 ]; then
     echo "failed to write configuration file"
     exit 1
 fi
+
+remap_userns $path
+if [ $? -ne 0 ]; then
+    echo "failed to remap files to user"
+    exit 1
+fi
index 3a256db..3edc80a 100644 (file)
@@ -38,7 +38,7 @@ default_path=@LXCPATH@
 #
 # If the root password contains a ding ($) then try to expand it.
 # That will pick up things like ${name} and ${RANDOM}.
-# If the root password contians more than 3 consecutive X's, pass it as
+# If the root password contains more than 3 consecutive X's, pass it as
 # a template to mktemp and take the result.
 #
 # If root_display_password = yes, display the temporary root password at exit.
@@ -656,7 +656,7 @@ usage()
     cat <<EOF
 usage:
     $1 -n|--name=<container_name>
-        [-p|--path=<path>] [-c|--clean] [-R|--release=<CentOS_release>] [-A|--arch=<arch of the container>]
+        [-p|--path=<path>] [-c|--clean] [-R|--release=<CentOS_release>] [-a|--arch=<arch of the container>]
         [-h|--help]
 Mandatory args:
   -n,--name         container name, used to as an identifier for that container from now on
@@ -761,7 +761,7 @@ else
         root_password=$(eval echo "${root_password}")
     fi
 
-    # If it has more than 3 consequtive X's in it, feed it
+    # If it has more than 3 consecutive X's in it, feed it
     # through mktemp as a template.
     if [ $(expr "${root_password}" : '.*XXXX') != 0 ]
     then
index 24b9210..c8a8b36 100644 (file)
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
 # Detect use under userns (unsupported)
-for arg in "$@"; do
-    [ "$arg" = "--" ] && break
-    if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
-        echo "This template can't be used for unprivileged containers." 1>&2
-        echo "You may want to try the \"download\" template instead." 1>&2
-        exit 1
-    fi
-done
-
 # Make sure the usual locations are in PATH
 export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
 
 VERBOSITY=0
 DOWNLOAD_URL="http://download.cirros-cloud.net/"
-CACHE_D="@LOCALSTATEDIR@/cache/lxc/cirros"
 
 UNAME_M=$(uname -m)
 ARCHES=( i386 x86_64 amd64 arm )
 STREAMS=( released devel )
 SOURCES=( nocloud none )
 BUILD="standard"
+LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@"
+
+LXC_MAPPED_GID=
+LXC_MAPPED_UID=
 
 DEF_VERSION="released"
 DEF_SOURCE="nocloud"
@@ -53,6 +47,23 @@ case "${UNAME_M}" in
     *) DEF_ARCH="i386";;
 esac
 
+am_in_userns() {
+    [ -e /proc/self/uid_map ] || { echo no; return; }
+    [ "$(wc -l /proc/self/uid_map | awk '{ print $1 }')" -eq 1 ] || { echo yes; return; }
+    line=$(awk '{ print $1 " " $2 " " $3 }' /proc/self/uid_map)
+    [ "$line" = "0 0 4294967295" ] && { echo no; return; }
+    echo yes
+}
+
+in_userns=0
+[ $(am_in_userns) = "yes" ] && in_userns=1
+
+if [ $(id -u) -eq 0 ]; then
+    CACHE_D="@LOCALSTATEDIR@/cache/lxc/cirros"
+else
+    CACHE_D="$HOME/.cache/lxc/cirros"
+fi
+
 error() { echo "$@" 1>&2; }
 inargs() {
     local needle="$1" x=""
@@ -151,6 +162,12 @@ lxc.cgroup.devices.allow = c 10:228 rwm
 # kvm
 lxc.cgroup.devices.allow = c 10:232 rwm
 EOF
+
+    if [ $in_userns -eq 1 ] && [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.userns.conf" ]; then
+        echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu.userns.conf" >> $path/config
+        echo "lxc.mount.auto = cgroup:mixed proc:mixed sys:ro" >> $path/config
+    fi
+
 }
 
 insert_ds_nocloud() {
@@ -187,8 +204,13 @@ extract_rootfs() {
     mkdir -p "${rootfs_d}" ||
         { error "failed to make rootfs dir ${rootfs_d}"; return 1; }
 
-    tar -C "${rootfs_d}" -Sxzf "${tarball}" ||
-        { error "failed to populate ${rootfs_d}"; return 1; }
+    if [ $in_userns -eq 1 ]; then
+        tar -C "${rootfs_d}" --anchored --exclude="dev/*" -Sxzf "${tarball}" ||
+            { error "failed to populate ${rootfs_d}"; return 1; }
+    else
+        tar -C "${rootfs_d}" -Sxzf "${tarball}" ||
+            { error "failed to populate ${rootfs_d}"; return 1; }
+    fi
     return 0
 }
 
@@ -218,7 +240,7 @@ download_tarball() {
 
 create_main() {
     local short_opts="a:hn:p:S:uvV"
-    local long_opts="arch:,auth-key:,name:,path:,tarball:,userdata:,verbose,version:,rootfs:"
+    local long_opts="arch:,auth-key:,name:,path:,tarball:,userdata:,verbose,version:,rootfs:,mapped-uid:,mapped-gid:"
     local getopt_out=""
     getopt_out=$(getopt --name "${0##*/}" \
         --options "${short_opts}" --long "${long_opts}" -- "$@") &&
@@ -244,6 +266,8 @@ create_main() {
                --tarball) tarball="$next"; shift;;
                --source) dsource="$next"; shift;;
                --rootfs) rootfs_d="$next"; shift;;
+            --mapped-uid) LXC_MAPPED_UID=$next; shift;;
+            --mapped-gid) LXC_MAPPED_GID=$next; shift;;
             --) shift; break;;
         esac
         shift;
@@ -300,18 +324,6 @@ create_main() {
 
     extract_rootfs "${tarball}" "${rootfs_d}" || return
 
-    # cirros 0.3.1 was broken for /dev/random and /dev/urandom
-    if [ -b "$rootfs_d/dev/random" ]; then
-        rm -f "$rootfs_d/dev/random" &&
-            mknod --mode=666 "$rootfs_d/dev/random" c 1 8 ||
-           { error "failed to fix /dev/random"; return 1; }
-    fi
-    if [ -b "$rootfs_d/dev/urandom" ]; then
-        rm -f "$rootfs_d/dev/urandom" &&
-        mknod --mode=666 "$rootfs_d/dev/urandom" c 1 9 ||
-           { error "failed to fix /dev/urandom"; return 1; }
-    fi
-
     if [ "$version" = "0.3.2~pre1" ]; then
         debug 1 "fixing console for lxc and '$version'"
         sed -i 's,^\(#console.* 115200 \)# /dev/console,\1 console,g' \
index c2076dc..706ed32 100644 (file)
@@ -33,7 +33,8 @@ done
 # Make sure the usual locations are in PATH
 export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
 
-MIRROR=${MIRROR:-http://cdn.debian.net/debian}
+MIRROR=${MIRROR:-http://http.debian.net/debian}
+SECURITY_MIRROR=${SECURITY_MIRROR:-http://security.debian.org/}
 LOCALSTATEDIR="@LOCALSTATEDIR@"
 LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@"
 
@@ -107,10 +108,10 @@ EOF
     fi
 
     # remove pointless services in a container
-    chroot $rootfs /usr/sbin/update-rc.d -f checkroot.sh remove
-    chroot $rootfs /usr/sbin/update-rc.d -f umountfs remove
-    chroot $rootfs /usr/sbin/update-rc.d -f hwclock.sh remove
-    chroot $rootfs /usr/sbin/update-rc.d -f hwclockfirst.sh remove
+    chroot $rootfs /usr/sbin/update-rc.d -f checkroot.sh disable
+    chroot $rootfs /usr/sbin/update-rc.d -f umountfs disable
+    chroot $rootfs /usr/sbin/update-rc.d -f hwclock.sh disable
+    chroot $rootfs /usr/sbin/update-rc.d -f hwclockfirst.sh disable
 
     # generate new SSH keys
     if [ -x $rootfs/var/lib/dpkg/info/openssh-server.postinst ]; then
@@ -154,6 +155,63 @@ EOF
     return 0
 }
 
+write_sourceslist()
+{
+    local rootfs="$1";  shift
+    local release="$1"; shift
+    local arch="$1";    shift
+
+    local prefix="deb"
+    if [ -n "${arch}" ]; then
+        prefix="deb [arch=${arch}]"
+    fi
+
+    cat >> "${rootfs}/etc/apt/sources.list" << EOF
+${prefix} $MIRROR          ${release}         main contrib non-free
+${prefix} $SECURITY_MIRROR ${release}/updates main contrib non-free
+EOF
+}
+
+configure_debian_systemd()
+{
+    path=$1
+    rootfs=$2
+
+    init="$(chroot ${rootfs} dpkg-query --search /sbin/init | cut -d : -f 1)"
+    if [ "$init" = "systemd-sysv" ]; then
+       # only appropriate when systemd is PID 1
+       echo 'lxc.autodev = 1' >> "$path/config"
+       echo 'lxc.kmsg = 0' >> "$path/config"
+    fi
+
+    # this only works if we have getty@.service to manipulate
+    if [ -f ${rootfs}/lib/systemd/system/getty\@.service ]; then
+       sed -e 's/^ConditionPathExists=/# ConditionPathExists=/' \
+           -e 's/After=dev-%i.device/After=/' \
+           < ${rootfs}/lib/systemd/system/getty\@.service \
+           > ${rootfs}/etc/systemd/system/getty\@.service
+    fi
+
+    # just in case systemd is not installed
+    mkdir -p ${rootfs}/{lib,etc}/systemd/system
+    mkdir -p ${rootfs}/etc/systemd/system/getty.target.wants
+
+    # This function has been copied and adapted from lxc-fedora
+    rm -f ${rootfs}/etc/systemd/system/default.target
+    touch ${rootfs}/etc/fstab
+    chroot ${rootfs} ln -s /dev/null /etc/systemd/system/udev.service
+    chroot ${rootfs} ln -s /dev/null /etc/systemd/system/systemd-udevd.service
+    chroot ${rootfs} ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target
+    # Make systemd honor SIGPWR
+    chroot ${rootfs} ln -s /lib/systemd/system/halt.target /etc/systemd/system/sigpwr.target
+    # Setup getty service on the 4 ttys we are going to allow in the
+    # default config.  Number should match lxc.tty
+    ( cd ${rootfs}/etc/systemd/system/getty.target.wants
+        for i in 1 2 3 4 ; do ln -sf ../getty\@.service getty@tty${i}.service; done )
+
+    return 0
+}
+
 cleanup()
 {
     rm -rf $cache/partial-$release-$arch
@@ -302,6 +360,38 @@ EOF
     return 0
 }
 
+post_process()
+{
+    local rootfs="$1";  shift
+    local release="$1"; shift
+    local arch="$1"; shift
+    local hostarch="$1"; shift
+
+    # Disable service startup
+    cat > ${rootfs}/usr/sbin/policy-rc.d << EOF
+#!/bin/sh
+exit 101
+EOF
+    chmod +x ${rootfs}/usr/sbin/policy-rc.d
+
+    # If the container isn't running a native architecture, setup multiarch
+    if [ "${arch}" != "${hostarch}" ]; then
+        mkdir -p ${rootfs}/etc/dpkg/dpkg.cfg.d
+        echo "foreign-architecture ${hostarch}" > ${rootfs}/etc/dpkg/dpkg.cfg.d/lxc-multiarch
+    fi
+
+    # Write a new sources.list containing both native and multiarch entries
+    > ${rootfs}/etc/apt/sources.list
+    if [ "${arch}" = "${hostarch}" ]; then
+        write_sourceslist ${rootfs} ${release} ${arch}
+    else
+        write_sourceslist ${rootfs} ${release}
+    fi
+
+    # Re-enable service startup
+    rm ${rootfs}/usr/sbin/policy-rc.d
+}
+
 clean()
 {
     cache="$LOCALSTATEDIR/cache/lxc/debian"
@@ -328,14 +418,16 @@ clean()
 usage()
 {
     cat <<EOF
-$1 -h|--help -p|--path=<path> [-a|--arch] [-r|--release=<release>] [-c|--clean]
-release: the debian release (e.g. wheezy): defaults to current stable
+$1 -h|--help -p|--path=<path> [-a|--arch] [-c|--clean] [--mirror=<mirror>] [-r|--release=<release>] [--security-mirror=<security mirror>]
 arch: the container architecture (e.g. amd64): defaults to host arch
+release: the debian release (e.g. wheezy): defaults to current stable
+mirror: debain mirror to use during installation
+security mirror: debain mirror to use for security updates
 EOF
     return 0
 }
 
-options=$(getopt -o hp:n:a:r:c -l help,rootfs:,path:,name:,arch:,release:,clean -- "$@")
+options=$(getopt -o hp:n:a:r:c -l arch:,clean,help,mirror:,name:,path:,release:,rootfs:,security-mirror: -- "$@")
 if [ $? -ne 0 ]; then
         usage $(basename $0)
         exit 1
@@ -359,15 +451,18 @@ hostarch=$arch
 while true
 do
     case "$1" in
-        -h|--help)      usage $0 && exit 1;;
-        -p|--path)      path=$2; shift 2;;
-        --rootfs)       rootfs=$2; shift 2;;
-        -a|--arch)      arch=$2; shift 2;;
-        -r|--release)   release=$2; shift 2;;
-        -n|--name)      name=$2; shift 2;;
-        -c|--clean)     clean=$2; shift 1;;
-        --)             shift 1; break ;;
-        *)              break ;;
+        -h|--help)            usage $0 && exit 1;;
+           --)                shift 1; break ;;
+
+        -a|--arch)            arch=$2; shift 2;;
+        -c|--clean)           clean=$2; shift 1;;
+           --mirror)          MIRROR=$2; shift 2;;
+        -n|--name)            name=$2; shift 2;;
+        -p|--path)            path=$2; shift 2;;
+        -r|--release)         release=$2; shift 2;;
+           --rootfs)          rootfs=$2; shift 2;;
+           --security-mirror) SECURITY_MIRROR=$2; shift 2;;
+        *)                    break ;;
     esac
 done
 
@@ -434,7 +529,6 @@ if [ -z "$rootfs" ]; then
     fi
 fi
 
-
 install_debian $rootfs $release $arch
 if [ $? -ne 0 ]; then
     echo "failed to install debian"
@@ -453,6 +547,10 @@ if [ $? -ne 0 ]; then
     exit 1
 fi
 
+configure_debian_systemd $path $rootfs
+
+post_process ${rootfs} ${release} ${arch} ${hostarch}
+
 if [ ! -z $clean ]; then
     clean || exit 1
     exit 0
index da1207b..f2aab42 100644 (file)
@@ -38,7 +38,7 @@ default_path=@LXCPATH@
 #
 # If the root password contains a ding ($) then try to expand it.
 # That will pick up things like ${name} and ${RANDOM}.
-# If the root password contians more than 3 consecutive X's, pass it as
+# If the root password contains more than 3 consecutive X's, pass it as
 # a template to mktemp and take the result.
 #
 # If root_display_password = yes, display the temporary root password at exit.
@@ -425,7 +425,7 @@ configure_fedora_systemd()
 #       (mounting the iso) to the stage0 setup.
 
 # This system is designed to be as autonomous as possible so all whitelists
-# and controlls are self-contained.
+# and controls are self-contained.
 
 # Initial testing - Whitelist nobody.  Build for everybody...
 # Initial deployment - Whitelist Fedora.
@@ -495,7 +495,7 @@ an Installation Bootstrap  Please install rsync and then rerun this process.
     # We know we don't have a cache directory of this version or we
     # would have never reached this code to begin with.  But we may
     # have another Fedora cache directory from which we could run...
-    # We'll give a preference for close matches prefering higher over
+    # We'll give a preference for close matches preferring higher over
     # lower - which makes for really ugly code...
 
     # Is this a "bashism" that will need cleaning up????
@@ -1236,7 +1236,7 @@ else
         root_password=$(eval echo "${root_password}")
     fi
 
-    # If it has more than 3 consequtive X's in it, feed it
+    # If it has more than 3 consecutive X's in it, feed it
     # through mktemp as a template.
     if [ $(expr "${root_password}" : '.*XXXX') != 0 ]
     then
index 659fd28..d0df899 100644 (file)
@@ -142,7 +142,7 @@ cache_precheck()
     printf "### cache_precheck(): doing some pre-start checks ...\n"
     # never hurts to have a fail-safe.
     [[ -n "${cacheroot//\/}" ]] \
-        || die 8 "\$cacheroot (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPERATORS, THIS IS *VERY* BAD!\n" "${cacheroot}"
+        || die 8 "\$cacheroot (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPARATORS, THIS IS *VERY* BAD!\n" "${cacheroot}"
 }
 
 #get latest stage3 tarball
@@ -320,13 +320,13 @@ container_precheck()
     printf "### container_precheck(): doing some pre-start checks ...\n"
     # never hurts to have a fail-safe.
     [[ -n "${name//\/}" ]] \
-        || die 8 "\$name (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPERATORS, THIS IS *VERY* BAD!\n" "${name}"
+        || die 8 "\$name (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPARATORS, THIS IS *VERY* BAD!\n" "${name}"
 
     [[ -n "${rootfs//\/}" ]] \
-        || die 8 "\$rootfs (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPERATORS, THIS IS *VERY* BAD!\n" "${rootfs}"
+        || die 8 "\$rootfs (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPARATORS, THIS IS *VERY* BAD!\n" "${rootfs}"
 
     [[ -n "${cachefs//\/}" ]] \
-        || die 8 "\$cachefs (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPERATORS, THIS IS *VERY* BAD!\n" "${cachefs}"
+        || die 8 "\$cachefs (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPARATORS, THIS IS *VERY* BAD!\n" "${cachefs}"
 
     # check if the rootfs already exists
     [[ -d "${rootfs}/etc" ]] && die 18 "Error: \$rootfs (%s) already exists!" "${rootfs}"
@@ -473,7 +473,7 @@ lxc.mount.entry=${portage_distfiles_dir} ${portage_container/\//}/distfiles none
 #PKGDIR="\${PKGDIR}/amd64
 #or PKGDIR="\${PKGDIR}/hardened"
 EOF
-    printf " => portage stuff done, see /etc/portage/make.conf for additionnal tricks\n"
+    printf " => portage stuff done, see /etc/portage/make.conf for additional tricks\n"
 
 }
 
@@ -564,7 +564,7 @@ container_net()
     #Analyse network configuration in config
     container_conf_net "$path/config" >> "${rootfs}/etc/conf.d/net"
 
-        # found how much nic finaly have
+        # found how much nic finally have
     nic_count=$(( ${nic_last} + 1 ))
 
         # unless openrc manage a nic, we now have to force openrc to automatic
@@ -623,7 +623,7 @@ and man lxc.conf"
 container_hostname()
 {
     printf "#### container_hostname(): setting hostname... \n"
-    printf "hostnale=%s\n" "${name}" > "${rootfs}/etc/conf.d/hostname"
+    printf "hostname=\"%s\"\n" "${name}" > "${rootfs}/etc/conf.d/hostname"
     printf " => done.\n"
 }
 
@@ -788,7 +788,7 @@ do
     -n|--name)             name=$2; shift 2;;
     -a|--arch)             arch=$2; shift 2;;
     -F|--flush-cache)      flush_cache=1; shift 1;;
-    -c|--cache-only)       cache_only=1; shitf 1;;
+    -c|--cache-only)       cache_only=1; shift 1;;
     -P|--private-portage)  private_portage=1; shift 1;;
     -v|--variant)          variant=$2; shift 2;;
     --portage-dir)         portage_dir=$2; shift 2;;
index 4fdaece..45e2efa 100644 (file)
@@ -379,7 +379,7 @@ do
         -P|--profile)   profile=$2; shift 2;;
         -c|--clean)     clean=$2; shift 2;;
         -R|--release)   release=$2; shift 2;;
-        -a|--arch)      arch=$2; shift 2;;
+        -A|--arch)      arch=$2; shift 2;;
         -4|--ipv4)      ipv4=$2; shift 2;;
         -6|--ipv6)      ipv6=$2; shift 2;;
         -g|--gw)        gw=$2; shift 2;;
index 3999df6..91ef726 100644 (file)
@@ -394,6 +394,11 @@ if [ -z "$path" ]; then
     exit 1
 fi
 
+if grep -q Harlequin /etc/os-release || grep -q Tumbleweed /etc/os-release ; then
+    echo "Building containers on openSUSE 13.2 or Tumbleweed is broken at the moment. We are working on this problem."
+    exit 1
+fi
+
 if [ "$(id -u)" != "0" ]; then
     echo "This script should be run as 'root'"
     exit 1
index ce98c1a..5061056 100644 (file)
@@ -153,6 +153,7 @@ configure_plamo() {
   chmod    666 $rootfs/dev/random
   mknod -m 666 $rootfs/dev/urandom c 1 9
   mkdir -m 755 $rootfs/dev/pts
+  mkdir -m 755 $rootfs/dev/shm
   chmod    666 $rootfs/dev/tty
   chmod    600 $rootfs/dev/console
   mknod -m 666 $rootfs/dev/tty0 c 4 0
index 5f2ca6b..d1798f5 100644 (file)
@@ -224,13 +224,13 @@ choose_container_proxy()
 
 write_sourceslist()
 {
-    # $1 => path to the rootfs
+    # $1 => path to the partial cache or the rootfs
     # $2 => architecture we want to add
     # $3 => whether to use the multi-arch syntax or not
 
     if [ -n "$APT_PROXY" ]; then
-        mkdir -p $rootfs/etc/apt/apt.conf.d
-        cat > $rootfs/etc/apt/apt.conf.d/70proxy << EOF
+        mkdir -p $1/etc/apt/apt.conf.d
+        cat > $1/etc/apt/apt.conf.d/70proxy << EOF
 Acquire::http::Proxy "$APT_PROXY" ;
 EOF
     fi