From 8d0609371e8831fbe185452ee51f784200e52fbf Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Wed, 14 Feb 2018 11:33:33 +0100 Subject: [PATCH 01/12] autotools: add --{enable,disable}-{commands,tools} This allows users to only compile the shared libray without having to compile any of the command line tools or command helpers for the shared library. Signed-off-by: Christian Brauner --- configure.ac | 45 ++++++++++++++++++++++++++++ doc/Makefile.am | 73 +++++++++++++++++++++------------------------ src/lxc/Makefile.am | 23 ++++++++++++-- 3 files changed, 100 insertions(+), 41 deletions(-) diff --git a/configure.ac b/configure.ac index 52c068e54..87c6384b8 100644 --- a/configure.ac +++ b/configure.ac @@ -477,6 +477,18 @@ AM_COND_IF([ENABLE_BASH], AC_SUBST(bashcompdir) ]) +# Build the command line tools +AC_ARG_ENABLE([tools], + [AC_HELP_STRING([--enable-tools], [build the command line tools [default=yes]])], + [], [enable_tools=yes]) +AM_CONDITIONAL([ENABLE_TOOLS], [test "x$enable_tools" = "xyes"]) + +# Build the liblxc commands +AC_ARG_ENABLE([commands], + [AC_HELP_STRING([--enable-commands], [build the liblxc commands [default=yes]])], + [], [enable_commands=yes]) +AM_CONDITIONAL([ENABLE_COMMANDS], [test "x$enable_commands" = "xyes"]) + # Optional test binaries AC_ARG_ENABLE([tests], [AC_HELP_STRING([--enable-tests], [build test/example binaries [default=no]])], @@ -950,6 +962,39 @@ AC_OUTPUT cat << EOF ---------------------------- +Binaries + - Command Line Tools: + - lxc-attach: $enable_tools + - lxc-autostart: $enable_tools + - lxc-cgroup: $enable_tools + - lxc-checkpoint: $enable_tools + - lxc-config: $enable_tools + - lxc-console: $enable_tools + - lxc-copy: $enable_tools + - lxc-create: $enable_tools + - lxc-destroy: $enable_tools + - lxc-device: $enable_tools + - lxc-execute: $enable_tools + - lxc-freeze: $enable_tools + - lxc-info: $enable_tools + - lxc-ls: $enable_tools + - lxc-monitor: $enable_tools + - lxc-snapshot: $enable_tools + - lxc-start: $enable_tools + - lxc-stop: $enable_tools + - lxc-top: $enable_tools + - lxc-unfreeze: $enable_tools + - lxc-unshare: $enable_tools + - lxc-wait: $enable_tools + + - liblxc Commands: + - lxc-checkconfig: $enable_commands + - lxc-update-config: $enable_commands + - lxc-init: $enable_commands + - lxc-monitord: $enable_commands + - lxc-user-nic: $enable_commands + - lxc-usernsexec: $enable_commands + Environment: - compiler: $CC - distribution: $with_distro diff --git a/doc/Makefile.am b/doc/Makefile.am index ae023e411..2bf92a0a8 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -15,46 +15,41 @@ EXTRA_DIST = \ FAQ.txt if ENABLE_DOCBOOK -man_MANS = \ - lxc-attach.1 \ - lxc-autostart.1 \ - lxc-cgroup.1 \ - lxc-checkconfig.1 \ - lxc-checkpoint.1 \ - lxc-config.1 \ - lxc-console.1 \ - lxc-copy.1 \ - lxc-create.1 \ - lxc-destroy.1 \ - lxc-device.1 \ - lxc-execute.1 \ - lxc-freeze.1 \ - lxc-info.1 \ - lxc-ls.1 \ - lxc-monitor.1 \ - lxc-snapshot.1 \ - lxc-start.1 \ - lxc-stop.1 \ - lxc-top.1 \ - lxc-unfreeze.1 \ - lxc-unshare.1 \ - lxc-update-config.1 \ - lxc-user-nic.1 \ - lxc-usernsexec.1 \ - lxc-wait.1 \ - \ - lxc.conf.5 \ - lxc.container.conf.5 \ - lxc.system.conf.5 \ - lxc-usernet.5 \ - \ - lxc.7 - -if ENABLE_DEPRECATED - man_MANS += lxc-clone.1 -if ENABLE_PYTHON - man_MANS += lxc-start-ephemeral.1 +man_MANS = lxc.conf.5 \ + lxc.container.conf.5 \ + lxc.system.conf.5 \ + lxc-usernet.5 \ + lxc.7 +if ENABLE_TOOLS +man_MANS += lxc-attach.1 \ + lxc-autostart.1 \ + lxc-cgroup.1 \ + lxc-checkconfig.1 \ + lxc-checkpoint.1 \ + lxc-config.1 \ + lxc-console.1 \ + lxc-copy.1 \ + lxc-create.1 \ + lxc-destroy.1 \ + lxc-device.1 \ + lxc-execute.1 \ + lxc-freeze.1 \ + lxc-info.1 \ + lxc-ls.1 \ + lxc-monitor.1 \ + lxc-snapshot.1 \ + lxc-start.1 \ + lxc-stop.1 \ + lxc-top.1 \ + lxc-unfreeze.1 \ + lxc-unshare.1 \ + lxc-wait.1 endif + +if ENABLE_COMMANDS +man_MANS += lxc-update-config.1 \ + lxc-user-nic.1 \ + lxc-usernsexec.1 endif %.1 : %.sgml diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am index fb799c8db..b7c4dfccc 100644 --- a/src/lxc/Makefile.am +++ b/src/lxc/Makefile.am @@ -200,9 +200,14 @@ liblxc_la_LDFLAGS = \ liblxc_la_LIBADD = $(CAP_LIBS) $(SELINUX_LIBS) $(SECCOMP_LIBS) -bin_SCRIPTS = cmd/lxc-checkconfig \ - cmd/lxc-update-config +bin_SCRIPTS= +if ENABLE_COMMANDS +bin_SCRIPTS += cmd/lxc-checkconfig \ + cmd/lxc-update-config +endif + +if ENABLE_TOOLS EXTRA_DIST = \ tools/lxc-top.lua @@ -211,7 +216,9 @@ if ENABLE_PYTHON bin_SCRIPTS += tools/lxc-start-ephemeral endif endif +endif +if ENABLE_TOOLS bin_PROGRAMS = \ lxc-attach \ lxc-autostart \ @@ -240,11 +247,14 @@ bin_PROGRAMS = \ if ENABLE_DEPRECATED bin_PROGRAMS += lxc-clone endif +endif +if ENABLE_COMMANDS sbin_PROGRAMS = init.lxc pkglibexec_PROGRAMS = \ lxc-monitord \ lxc-user-nic +endif AM_LDFLAGS = -Wl,-E if ENABLE_RPATH @@ -252,6 +262,7 @@ AM_LDFLAGS += -Wl,-rpath -Wl,$(libdir) endif LDADD=liblxc.la @CAP_LIBS@ @SELINUX_LIBS@ @SECCOMP_LIBS@ +if ENABLE_TOOLS lxc_attach_SOURCES = tools/lxc_attach.c tools/arguments.c tools/tool_utils.c lxc_autostart_SOURCES = tools/lxc_autostart.c tools/arguments.c tools/tool_utils.c lxc_cgroup_SOURCES = tools/lxc_cgroup.c tools/arguments.c tools/tool_utils.c @@ -274,13 +285,18 @@ lxc_wait_SOURCES = tools/lxc_wait.c tools/arguments.c tools/tool_utils.c lxc_create_SOURCES = tools/lxc_create.c tools/arguments.c tools/tool_utils.c lxc_snapshot_SOURCES = tools/lxc_snapshot.c tools/arguments.c tools/tool_utils.c lxc_checkpoint_SOURCES = tools/lxc_checkpoint.c tools/arguments.c tools/tool_utils.c +endif +if ENABLE_COMMANDS # Binaries shipping with liblxc init_lxc_SOURCES = cmd/lxc_init.c lxc_monitord_SOURCES = cmd/lxc_monitord.c lxc_user_nic_SOURCES = cmd/lxc_user_nic.c namespace.c network.c parse.c lxc_usernsexec_SOURCES = cmd/lxc_usernsexec.c +endif + +if ENABLE_TOOLS if ENABLE_DEPRECATED lxc_clone_SOURCES = tools/lxc_clone.c tools/arguments.c endif @@ -288,7 +304,9 @@ endif if !HAVE_GETSUBOPT lxc_copy_SOURCES += tools/include/getsubopt.c tools/include/getsubopt.h endif +endif +if ENABLE_COMMANDS if HAVE_STATIC_LIBCAP sbin_PROGRAMS += init.lxc.static @@ -304,6 +322,7 @@ init_lxc_static_LDFLAGS = -all-static init_lxc_static_LDADD = @CAP_LIBS@ init_lxc_static_CFLAGS = $(AM_CFLAGS) -DNO_LXC_CONF endif +endif if ENABLE_PAM if HAVE_PAM From a9145d622f9169581b499ec6841378d68f833b62 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Wed, 14 Feb 2018 11:45:09 +0100 Subject: [PATCH 02/12] tree-wide: cleanup - remove legacy binaries - conditionalize creation of docs and tests for the command line tools and the shared library helper commands Signed-off-by: Christian Brauner --- .gitignore | 2 - config/apparmor/abstractions/start-container | 2 +- config/bash/lxc.in | 1 - configure.ac | 7 - doc/ja/Makefile.am | 7 - doc/ja/lxc-clone.sgml.in | 386 ----------------- doc/ja/lxc-start-ephemeral.sgml.in | 316 -------------- doc/ko/lxc-clone.sgml.in | 377 ----------------- doc/ko/lxc-start-ephemeral.sgml.in | 318 -------------- doc/lxc-clone.sgml.in | 310 -------------- doc/lxc-copy.sgml.in | 3 +- doc/lxc-start-ephemeral.sgml.in | 261 ------------ doc/lxc.container.conf.sgml.in | 9 +- src/lxc/Makefile.am | 19 - src/lxc/tools/lxc-start-ephemeral.in | 418 ------------------- src/lxc/tools/lxc-top.lua | 243 ----------- src/lxc/tools/lxc_clone.c | 246 ----------- src/tests/Makefile.am | 5 +- 18 files changed, 10 insertions(+), 2920 deletions(-) delete mode 100644 doc/ja/lxc-clone.sgml.in delete mode 100644 doc/ja/lxc-start-ephemeral.sgml.in delete mode 100644 doc/ko/lxc-clone.sgml.in delete mode 100644 doc/ko/lxc-start-ephemeral.sgml.in delete mode 100644 doc/lxc-clone.sgml.in delete mode 100644 doc/lxc-start-ephemeral.sgml.in delete mode 100644 src/lxc/tools/lxc-start-ephemeral.in delete mode 100755 src/lxc/tools/lxc-top.lua delete mode 100644 src/lxc/tools/lxc_clone.c diff --git a/.gitignore b/.gitignore index 3410daa38..d48daf2cc 100644 --- a/.gitignore +++ b/.gitignore @@ -39,7 +39,6 @@ src/lxc/lxc-cgroup src/lxc/tools/lxc-checkconfig src/lxc/tools/lxc-update-config src/lxc/lxc-checkpoint -src/lxc/lxc-clone src/lxc/lxc-console src/lxc/lxc-config src/lxc/lxc-copy @@ -57,7 +56,6 @@ src/lxc/lxc-monitord src/lxc/lxc-shutdown src/lxc/lxc-snapshot src/lxc/lxc-start -src/lxc/tools/lxc-start-ephemeral src/lxc/lxc-stop src/lxc/lxc-top src/lxc/lxc-unfreeze diff --git a/config/apparmor/abstractions/start-container b/config/apparmor/abstractions/start-container index 508bbf32e..fa64c278c 100644 --- a/config/apparmor/abstractions/start-container +++ b/config/apparmor/abstractions/start-container @@ -20,7 +20,7 @@ # allow pre-mount hooks to stage mounts under /var/lib/lxc// mount -> /var/lib/lxc/{**,}, - # required for some pre-mount hooks (like the new lxc-start-ephemeral) + # required for some pre-mount hooks mount fstype=overlayfs, mount fstype=aufs, mount fstype=ecryptfs, diff --git a/config/bash/lxc.in b/config/bash/lxc.in index 72d5f0817..43056882f 100644 --- a/config/bash/lxc.in +++ b/config/bash/lxc.in @@ -108,5 +108,4 @@ _have lxc-start && { complete -o default -F _lxc_generic_t lxc-create complete -o default -F _lxc_generic_o lxc-copy - complete -o default -F _lxc_generic_o lxc-start-ephemeral } diff --git a/configure.ac b/configure.ac index 87c6384b8..6da315952 100644 --- a/configure.ac +++ b/configure.ac @@ -793,7 +793,6 @@ AC_CONFIG_FILES([ doc/lxc-cgroup.sgml doc/lxc-checkconfig.sgml doc/lxc-checkpoint.sgml - doc/lxc-clone.sgml doc/lxc-config.sgml doc/lxc-console.sgml doc/lxc-copy.sgml @@ -806,7 +805,6 @@ AC_CONFIG_FILES([ doc/lxc-ls.sgml doc/lxc-monitor.sgml doc/lxc-snapshot.sgml - doc/lxc-start-ephemeral.sgml doc/lxc-start.sgml doc/lxc-stop.sgml doc/lxc-top.sgml @@ -842,7 +840,6 @@ AC_CONFIG_FILES([ doc/ja/lxc-cgroup.sgml doc/ja/lxc-checkconfig.sgml doc/ja/lxc-checkpoint.sgml - doc/ja/lxc-clone.sgml doc/ja/lxc-config.sgml doc/ja/lxc-console.sgml doc/ja/lxc-copy.sgml @@ -855,7 +852,6 @@ AC_CONFIG_FILES([ doc/ja/lxc-ls.sgml doc/ja/lxc-monitor.sgml doc/ja/lxc-snapshot.sgml - doc/ja/lxc-start-ephemeral.sgml doc/ja/lxc-start.sgml doc/ja/lxc-stop.sgml doc/ja/lxc-top.sgml @@ -880,7 +876,6 @@ AC_CONFIG_FILES([ doc/ko/lxc-cgroup.sgml doc/ko/lxc-checkconfig.sgml doc/ko/lxc-checkpoint.sgml - doc/ko/lxc-clone.sgml doc/ko/lxc-config.sgml doc/ko/lxc-console.sgml doc/ko/lxc-copy.sgml @@ -893,7 +888,6 @@ AC_CONFIG_FILES([ doc/ko/lxc-ls.sgml doc/ko/lxc-monitor.sgml doc/ko/lxc-snapshot.sgml - doc/ko/lxc-start-ephemeral.sgml doc/ko/lxc-start.sgml doc/ko/lxc-stop.sgml doc/ko/lxc-top.sgml @@ -946,7 +940,6 @@ AC_CONFIG_FILES([ src/lxc/lxc.functions src/lxc/cmd/lxc-checkconfig src/lxc/cmd/lxc-update-config - src/lxc/tools/lxc-start-ephemeral src/lxc/version.h src/python-lxc/Makefile diff --git a/doc/ja/Makefile.am b/doc/ja/Makefile.am index f30346d3a..89eae5ad5 100644 --- a/doc/ja/Makefile.am +++ b/doc/ja/Makefile.am @@ -42,13 +42,6 @@ man_MANS = \ \ lxc.7 -if ENABLE_DEPRECATED - man_MANS += lxc-clone.1 -if ENABLE_PYTHON - man_MANS += lxc-start-ephemeral.1 -endif -endif - %.1 : %.sgml $(db2xman) --encoding=UTF-8 $< test "$(shell basename $@)" != "$@" && mv $(shell basename $@) $@ || true diff --git a/doc/ja/lxc-clone.sgml.in b/doc/ja/lxc-clone.sgml.in deleted file mode 100644 index 9e68910f7..000000000 --- a/doc/ja/lxc-clone.sgml.in +++ /dev/null @@ -1,386 +0,0 @@ - - - - -]> - - - - @LXC_GENERATE_DATE@ - - - lxc-clone - 1 - - - - lxc-clone - - - - 既存のコンテナからの新しいコンテナのクローン - - - - - - lxc-clone - -s - -K - -M - -H - -B backingstore - -L fssize - -p lxcpath - -P newlxcpath - -R - -o orig - -n new - -- hook arguments - - - lxc-clone - -s - -K - -M - -H - -B backingstore - -L fssize - -p lxcpath - -P newlxcpath - -R - orig - new - -- hook arguments - - - - - <!-- Description -->説明 - - - - lxc-clone は、新しいコンテナを既に存在するコンテナのクローンとして作製します。 - クローンは 2 つのタイプをサポートします: コピーとスナップショットです。 - コピータイプのクローンは元のコンテナから新しいコンテナへ root ファイルシステムをコピーします。 - スナップショットファイルシステムは、バッキングストアのスナップショット機能を使い、元のコンテナの非常に小さな copy-on-write でのスナップショットを作製します。 - スナップショットでのクローンは、新しいコンテナのバッキングストアとしてスナップショット機能のサポートが必要になります。 - 現時点では、このようなバッキングストアとしては aufs, btrfs, lvm, overlayfs, zfs のみをサポートします。 - LVM デバイスはスナップショットのスナップショットはサポートしていません。 - - - - - 新しいコンテナのバッキングストアは、オーバーレイタイプのコンテナを除いては元のコンテナのタイプと同じになります。 - ディレクトリバックエンドのコンテナのスナップショットを aufs もしくは overlayfs で作成することは可能です。 - 例えば、overlayfs の場合は -B overlayfs という引数を使って指定することが可能です。 - - - - - 元のコンテナと新しいコンテナの名前は、全てのオプションの後に順番に与えることも、-o-n オプションを使ってそれぞれ指定することも可能です。 - - - - - - - <!-- Options -->オプション - - - - - - - - - - - 新しいコンテナの rootfs はオリジナルのスナップショットとなります。 - このオプションはバッキングストアが LVM か btrfs か zfs の時に使用できます。 - また、スナップショットを aufs か overlayfs で取得したい場合は指定する必要があります。 - - - - - - - - - - - - (root ファイルシステム内では) コンテナのホスト名を変更しません。 - - - - - - - - - - - - 新しい MAC アドレスをランダムに生成せずに、元のコンテナと同じ MAC アドレスを使用します。 - - - - - - - - - - - - 全てのマウントフックを新しいコンテナのディレクトリにコピーします。 - そして、lxcpath とコンテナ名を必要に応じて更新します。 - - - - - - - - - - - - ブロックデバイスのバックエンドのコンテナの場合、新しいブロックデバイスのサイズ。 - デフォルトでは、新しいデバイスは元のデバイスと同じサイズとなります。 - - - - - - - - - - - - オリジナルのコンテナの lxcpath。デフォルトでは、システム全体で設定された lxcpath が使われます。 - - - - - - - - - - - - 新しいコンテナの lxcpath。 - デフォルトでは、オリジナルの lxcpath と同じものが使われます。 - btrfs のスナップショットの場合は注意が必要で、lxcpath の変更はできない可能性があります。 - これは subvolume のスナップショットが、同じ btrfs ファイルシステム上に存在しなければならないからです。 - - - - - - - - - - - - 新しいコンテナで元のコンテナと違うバッキングストアを使う場合のバッキングストアを選択します。 - デフォルトでは元のコンテナと同じものが使われます。 - 現時点では、バッキングストアの変更は、ディレクトリバックエンドのコンテナに対する aufs と overlayfs のスナップショットに対してのみサポートされます。 - 有効なバッキングストアは dir(directory), aufs, btrfs, lvm, zfs, loop, overlayfs です。 - - - - - - - - - - - - コンテナの名前を変更します。orignew という名前に変更します。 - - - - - - - - - - - - クローンしたい元のコンテナの名前。 - - - - - - - - - - - - 作製する新しいコンテナの名前。 - - - - - - - - - - - Clone hook - - - クローンされるコンテナに 1 つ以上の lxc.hook.clone の指定が存在する場合、指定されたフックは新しいコンテナに対して呼ばれます。 - クローンフックに渡される最初の 3 つの引数は、コンテナ名、セクション ('lxc')、フックタイプ ('clone') となります。 - lxc-clone に渡される追加の引数は、フックプログラムに渡される引数の 4 番目以降となります。 - LXC_ROOTFS_MOUNT 環境変数には、コンテナの root ファイルシステムがマウントされるパスが与えられます。 - 設定ファイルのパス名は LXC_CONFIG_FILE に、新しいコンテナ名は LXC_NAME、古いコンテナ名は LXC_SRC_NAME に、rootfs のあるパスまたはデバイスは LXC_ROOTFS_PATH に保存されます。 - - - - - <!-- Notes -->注意 - - - lxc-clonelxc-copy に置き換えられ、廃止される予定です。 - - - - &seealso; - - - <!-- Author -->作者 - Serge Hallyn serge.hallyn@ubuntu.com - - - - - diff --git a/doc/ja/lxc-start-ephemeral.sgml.in b/doc/ja/lxc-start-ephemeral.sgml.in deleted file mode 100644 index 0124f4895..000000000 --- a/doc/ja/lxc-start-ephemeral.sgml.in +++ /dev/null @@ -1,316 +0,0 @@ - - - - -]> - - - - @LXC_GENERATE_DATE@ - - - lxc-start-ephemeral - 1 - - - - lxc-start-ephemeral - - - - 存在するコンテナの一時的なコピーを起動 - - - - - - lxc-start-ephemeral - -o - -n - -d - --bdir - --user - --key - --storage-type - --union-type - --keep-data - COMMAND - - - - - <!-- Description -->説明 - - - lxc-start-ephemeral は、存在するコンテナの一時的なコピーからコンテナを起動します。 - - - - - <!-- Options -->オプション - - - - - - - - - コピー元のコンテナ名 - - - - - - - - - - - - 一時的なコンテナの名前 (デフォルトではランダムなサフィックスが付与されます) - - - - - - - - - - - - コンテナをバックグラウンドで実行し、名前と IP アドレスを表示します。 - このオプションはコマンドを実行させたいときには使用することはできません。 - - - - - - - - - - - - コンテナ内にバインドマウントするためのディレクトリ。 - 複数回指定できます。 - - - - - - - - - - - - コンテナに接続するためのユーザ。 - lxc-start-ephemeral にコマンドを指定するときに使います。 - - - - - - - - - - - - コンテナ内にコピーする既存の SSH 公開鍵。 - - - - - - - - - - - - コンテナが使うストレージのタイプ。tmpfs か dir を指定できます。 - - - - - - - - - - - - 指定した union ファイルシステムを使用します。 - overlayfs か aufs のどちらかが使用できます。 - - - - - - - - - - - - tmpfs の代わりに永続的なバックエンドを使用します。このオプションを使うことにより、もはや一時的なコンテナではないので、lxc-stop や lxc-start を使用することができます (オーバーレイな状態ですが、永続的です)。 - - - - - - - - - - - - 即座に指定したコマンドをコンテナ内で実行します。 - コマンドを実行する際、カーネルがサポートしている場合は lxc-start-ephemeral は attach を使います。 - カーネルがサポートしていない場合は ssh を使います。 - - - - - - - - See Also - - - - lxc-start - 1 - , - - - - - <!-- Examples -->例 - - - lxc-start-ephemeral -o p1 - - - - 単に一時的なコンテナを開始させ、コンソールにアタッチします。 - このコンテナは "p1" という既存のコンテナを基にします。 - - - - - - lxc-start-ephemeral -o p1 -n p1-ephemeral -d - - - - p1 を基にした一時的なコンテナを開始し、コンソールにアタッチする代わりに IP アドレスと名前を表示します。 - - - - - - - - <!-- Notes -->注意 - - - lxc-start-ephemerallxc-copy に置き換えられ、廃止される予定です。 - - - - &seealso; - - - <!-- Author -->作者 - Stéphane Graber stgraber@ubuntu.com - - - - diff --git a/doc/ko/lxc-clone.sgml.in b/doc/ko/lxc-clone.sgml.in deleted file mode 100644 index b610119d7..000000000 --- a/doc/ko/lxc-clone.sgml.in +++ /dev/null @@ -1,377 +0,0 @@ - - - - -]> - - - - @LXC_GENERATE_DATE@ - - - lxc-clone - 1 - - - - lxc-clone - - - - 존재하는 컨테이너를 새로운 컨테이너로 복제 - - - - - - lxc-clone - -s - -K - -M - -H - -B backingstore - -L fssize - -p lxcpath - -P newlxcpath - -R - -o orig - -n new - -- hook arguments - - - lxc-clone - -s - -K - -M - -H - -B backingstore - -L fssize - -p lxcpath - -P newlxcpath - -R - orig - new - -- hook arguments - - - - - <!-- Description -->설명 - - - - lxc-clone는 존재하는 컨테이너를 복제하여 새로운 컨테이너를 생성한다. 복사, 스냅샷의 두가지 형태의 복제가 지원된다. - 복사는 원본 컨테이너의 루트 파일시스템을 그대로 새 컨테이너로 복사한다.. - 스냅샷은 저장소의 스냅샷 기능을 이용하여 원본 컨테이너의 copy-on-write 형태로 매우 작은 스냅샷을 생성한다. 스냅샷을 사용하기 위해서는 새 컨테이너의 저장소가 스냅샷 기능을 지원하여야 한다. 현재 스냅샷 기능을 지원하는 것은 aufs, btrfs, lvm, overlayfs, zfs 정도이다. lvm은 스냅샷의 스냅샷은 지원하지 않는다. - - - - - 오버레이 컨테이너들을 제외하면, 새 컨테이너의 저장소는 원본과 같은 종류를 사용한다. - aufs와 overlayfs의 스냅샷은 디렉토리로 구성된 컨테이너로 생성할 수 있다. overlayfs의 경우 -B overlayfs 인수를 통해 이를 지정할 수 있다. - - - - - 원본 컨테이너와 새 컨테이너의 이름은 모든 옵션 뒤에 원본, 새 컨테이너 순으로 지정할 수 있다. 또는 -o-n 옵션을 사용하여 지정할 수 있다. - - - - - - - <!-- Options -->옵션 - - - - - - - - - - - 새로 생성하는 컨테이너의 루트 파일시스템은 원본의 스냅샷으로 한다. 이 옵션은 저장소가 lvm, btrfs, zfs 일때 지정할 수 있다. 또한 aufs나 overlayfs를 이용한 스냅샷을 원할때만 지정해야 한다. - - - - - - - - - - - - (루트 파일시스템에서) 컨테이너의 호스트 이름을 변경하지 않는다. - - - - - - - - - - - - 새로 무작위한 주소를 만들지 않고, 원본과 같은 MAC 주소를 사용한다. - - - - - - - - - - - - 모든 마운트 훅들을 새 컨테이너의 디렉토리로 복사한다. 그리고 lxcpath와 컨테이너 이름을 필요에 따라 갱신한다. - - - - - - - - - - - - 블록장치로 구성된 컨테이너의 경우, 새로운 블록 장치의 크기. - 기본으로 새 디바이스는 원본과 같은 크기로 만들어진다. - - - - - - - - - - - - 원본 컨테이너의 lxcpath. 기본값은 시스템 전역으로 설정되어 잇는 lxcpath를 사용한다. - - - - - - - - - - - - 새로 생성될 컨테이너의 lxcpath. - 기본값은 원본 컨테이너의 lxcpath와 같다. - btrfs의 스냅샷의 경우 lxcpath 변경이 불가능 할 수 있음을 주의해야 한다. 왜냐하면 서브볼륨 스냅샷이 같은 btrfs 파일시스템 내에 있어야 하기 때문이다. - - - - - - - - - - - - 새 컨테이너의 저장소를 선택한다. - 기본 값은 원본 컨테이너가 쓰던 것과 같은 것으로 되어 있다. - 현재 저장소를 다른 것으로 변경하는 것은 디렉토리로 구성된 컨테이너의 aufs와 overlayfs 스냅샷에서만 지원된다. - 가능한 값은 dir(디렉토리), aufs, btrfs, lvm zfs, loop 그리고 ovelayfs 이다. - - - - - - - - - - - - 컨테이너의 이름을 변경한다. orignew로 이름을 바꾼다. - - - - - - - - - - - - - 복제할 원본 컨테이너의 이름. - - - - - - - - - - - - 생성할 새 컨테이너의 이름. - - - - - - - - - - - Clone hook - - - 만약 복제되는 컨테이너가 1개 이상의 lxc.hook.clone을 지정했다면, 지정된 훅은 새 컨테이너가 생성될 때 실행될 것이다. - 먼저 컨테이너 이름, 섹션('lxc'), 훅 종류('clone') 3개의 인수가 복제 훅에 전달 된다. 그리고 4번째 인수 부터는 lxc-clone로 넘겨줄 수 있다. - LXC_ROOTFS_MOUNT 환경변수는 컨테이너의 루트 파일시스템이 마운트되어 있는 경로를 넘겨준다. - 새 컨테이너의 이름은 LXC_NAME 변수에, 이전 컨테이너의 이름은 LXC_SRC_NAME 환경변수에 담겨 있다. 그리고 루트 파일시스템이 위치하고 있는 곳은 LXC_ROOTFS_PATH로 넘겨준다. - - - - - <!-- Notes -->주의 - - - lxc-clonelxc-copy로 대체되었으며, 제거될 예정이다. - - - - &seealso; - - - <!-- Author -->저자 - Serge Hallyn serge.hallyn@ubuntu.com - - - - - diff --git a/doc/ko/lxc-start-ephemeral.sgml.in b/doc/ko/lxc-start-ephemeral.sgml.in deleted file mode 100644 index 48947f646..000000000 --- a/doc/ko/lxc-start-ephemeral.sgml.in +++ /dev/null @@ -1,318 +0,0 @@ - - - - -]> - - - - @LXC_GENERATE_DATE@ - - - lxc-start-ephemeral - 1 - - - - lxc-start-ephemeral - - - - 존재하는 컨테이너를 임시 복사본으로 시작 - - - - - - lxc-start-ephemeral - -o - -n - -d - --bdir - --user - --key - --storage-type - --union-type - --keep-data - COMMAND - - - - - <!-- Description -->설명 - - - lxc-start-ephemeral는 존재하는 컨테이너를 임시 복사본으로 시작시킨다. - - - - - <!-- Options -->옵션 - - - - - - - - - 원본 컨테이너 이름 - - - - - - - - - - - - 임시 컨테이너의 이름 (기본값은 무작위한 접미사를 붙이는 것) - - - - - - - - - - - - 컨테이너를 백그라운드로 시작한다. 그리고 이름과 IP를 표시한다. - 옵션으로 명령어를 넘길 경우, 이 옵션은 사용하지 못한다. - - - - - - - - - - - - 컨테이너로 바인드 마운트할 디렉토리. - 여러번 인자로 넘겨줄 수 있다. - - - - - - - - - - - - 컨테이너에 연결할 사용자. - lxc-start-ephemeral로 명령어를 넘길때 사용한다. - - - - - - - - - - - - 컨테이너 안으로 지정한 SSH 공개키를 복사한다. - - - - - - - - - - - - 컨테이너가 사용하는 저장소 형태를 지정한다. 가능한 형태는 tmpfs, dir이다. - - - - - - - - - - - - 지정한 union 파일시스템을 사용한다. - 가능한 파일시스템은 overlayfs, aufs이다. - - - - - - - - - - - - tmpfs 대신 영구적인 백엔드를 사용한다. - 이 옵션을 사용하면, 더이상 임시 컨테이너가 아니기 때문에 lxc-stop이나 lxc-start를 사용할 수 있게 된다. (여전히 오버레이 상태이지만 영구적이다) - - - - - - - - - - - - 지정한 명령어를 컨테이너 안에서 바로 실행한다. - 커널이 attach를 지원하면 attach를 사용하고, 지원하지 않으면 ssh를 사용한다. - 이 옵션은 데몬 모드와 같이 사용할 수 없다. - - - - - - - - <!-- See Also -->참조 - - - - lxc-start - 1 - , - - - - - <!-- Examples -->예제 - - - lxc-start-ephemeral -o p1 - - - - 단순히 임시 복사본 컨테이너를 시작하고, console에 연결한다. - 임시 컨테이너는 컨테이너 p1을 기반으로 한다. - - - - - - lxc-start-ephemeral -o p1 -n p1-ephemeral -d - - - - 컨테이너 p1을 기반으로 임시 컨테이너 p1-ephemeral을 시작한다. - console에 연결하지 않고, 컨테이너의 IP와 이름을 출력한다. - - - - - - - - <!-- Notes -->주의 - - - lxc-start-ephemerallxc-copy로 대체되었으며, 제거될 예정이다. - - - - &seealso; - - - <!-- Author -->저자 - Stéphane Graber stgraber@ubuntu.com - - - - diff --git a/doc/lxc-clone.sgml.in b/doc/lxc-clone.sgml.in deleted file mode 100644 index f134b8000..000000000 --- a/doc/lxc-clone.sgml.in +++ /dev/null @@ -1,310 +0,0 @@ - - - - -]> - - - - @LXC_GENERATE_DATE@ - - - lxc-clone - 1 - - - - lxc-clone - - - clone a new container from an existing one. - - - - - - lxc-clone - -s - -K - -M - -H - -B backingstore - -L fssize - -p lxcpath - -P newlxcpath - -R - -o orig - -n new - -- hook arguments - - - lxc-clone - -s - -K - -M - -H - -B backingstore - -L fssize - -p lxcpath - -P newlxcpath - -R - orig - new - -- hook arguments - - - - - Description - - - lxc-clone Creates a new container as a clone of an existing - container. Two types of clones are supported: copy and snapshot. A copy - clone copies the root filessytem from the original container to the new. A - snapshot filesystem uses the backing store's snapshot functionality to create - a very small copy-on-write snapshot of the original container. Snapshot - clones require the new container backing store to support snapshotting. Currently - this includes only aufs, btrfs, lvm, overlayfs and zfs. LVM devices do not support - snapshots of snapshots. - - - - The backing store of the new container will be the same type as the - original container, with one exception, overlay containers. - aufs and overlayfs snapshots can be created of directory backed - containers. This can be requested by using (for overlayfs) the - -B overlayfs arguments. - - - - The names of the original and new container can be given (in that order) - after all options, or can be specified with the - -o and -n options, - respectively. - - - - - - - Options - - - - - - - - - - The new container's rootfs will be a snapshot of the original. This option can be specified when the backing store is LVM, btrfs or zfs, and must be specified when you want to snapshot using aufs or overlayfs. - - - - - - - - - - - Do not change the hostname of the container (in the root - filesystem). - - - - - - - - - - - Use the same MAC address as the original container, rather than - generating a new random one. - - - - - - - - - - - Copy all mount hooks into the new container's directory, and - update any lxcpaths and container names as needed. - - - - - - - - - - - In the case of a block device backed container, a size for the new - block device. By default, the new device will be made the - same size as the original. - - - - - - - - - - - The lxcpath of the original container. By default, the system - wide configured lxcpath will be used. - - - - - - - - - - - The lxcpath for the new container. By default the same lxcpath - as the original will be used. Note that with btrfs snapshots, - changing lxcpaths may not be possible, as subvolume snapshots - must be in the same btrfs filesystem. - - - - - - - - - - - Select a different backing store for the new container. By - default the same as the original container's is used. Note that - currently changing the backingstore is only supported for - aufs and overlayfs snapshots of directory backed containers. Valid - backing stores include dir (directory), aufs, btrfs, lvm, zfs, loop - and overlayfs. - - - - - - - - - - - Rename an existing container. - orig is renamed new. - - - - - - - - - - - The name of the original container to clone. - - - - - - - - - - - The name of the new container to create. - - - - - - - - - - - Clone hook - - If the container being cloned has one or more lxc.hook.clone - specified, then the specified hooks will be called for the new container. The - first 3 arguments passed to the clone hook will be the container name, a section - ('lxc'), and the hook type ('clone'). Extra arguments passed - lxc-clone will be passed to the hook program starting at - argument 4. The LXC_ROOTFS_MOUNT environment variable gives - the path under which the container's root filesystem is mounted. The - configuration file pathname is stored in LXC_CONFIG_FILE, the - new container name in LXC_NAME, the old container name in - LXC_SRC_NAME, and the path or device on which - the rootfs is located is in LXC_ROOTFS_PATH. - - - - - Notes - - lxc-clone is deprecated in favor of - lxc-copy. - - - - &seealso; - - - Author - Serge Hallyn serge.hallyn@ubuntu.com - - - - - diff --git a/doc/lxc-copy.sgml.in b/doc/lxc-copy.sgml.in index 475feb05b..467af116a 100644 --- a/doc/lxc-copy.sgml.in +++ b/doc/lxc-copy.sgml.in @@ -105,8 +105,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA lxc-copy creates and optionally starts (ephemeral or - non-ephemeral) copies of existing containers. It replaces - lxc-clone and lxc-start-ephemeral. + non-ephemeral) copies of existing containers. lxc-copy creates copies of existing containers. Copies diff --git a/doc/lxc-start-ephemeral.sgml.in b/doc/lxc-start-ephemeral.sgml.in deleted file mode 100644 index 683157871..000000000 --- a/doc/lxc-start-ephemeral.sgml.in +++ /dev/null @@ -1,261 +0,0 @@ - - - - -]> - - - - @LXC_GENERATE_DATE@ - - - lxc-start-ephemeral - 1 - - - - lxc-start-ephemeral - - - start an ephemeral copy of an existing container - - - - - - lxc-start-ephemeral - -o - -n - -d - --bdir - --user - --key - --storage-type - --union-type - --keep-data - COMMAND - - - - - Description - - lxc-start-ephemeral start an ephemeral copy of an - existing container. - - - - - Options - - - - - - - - Original container name - - - - - - - - - - - Name of the ephemeral container (defaults to a random suffix). - - - - - - - - - - - Start the container in background and print the name and IP. - This option can't be used if a command is passed. - - - - - - - - - - - Directory to bind mount into container. - Can be passed multiple times. - - - - - - - - - - - The user to connect to the container as. - Used when passing a command to lxc-start-ephemeral. - - - - - - - - - - - Copy the provided SSH public key into the container. - - - - - - - - - - - Specify the type of storage used by the container. Valid types are tmpfs or dir. - - - - - - - - - - - Force a specific union file system. - Can be one of: overlayfs aufs - - - - - - - - - - - Use a persistent backend instead of tmpfs. - With this option, you can lxc-stop and lxc-start the no longer so - ephemeral container (it's still an overlay, but a persistent one). - - - - - - - - - - - Immediately run the provided command in the container. - This uses attach if the kernel supports it, otherwise uses ssh. - This is incompatible with daemon mode. - - - - - - - - See Also - - - - lxc-start - 1 - , - - - - - Examples - - - lxc-start-ephemeral -o p1 - - - Simply start an ephemeral container and attach to the console. - This container will be based on existing container "p1". - - - - - - lxc-start-ephemeral -o p1 -n p1-ephemeral -d - - - Start an ephemeral container based on p1 called p1-ephemeral and - print its IP and name to the console instead of attaching. - - - - - - - - Notes - - lxc-start-ephemeral is deprecated in favor of - lxc-copy. - - - - &seealso; - - - Author - Stéphane Graber stgraber@ubuntu.com - - - - diff --git a/doc/lxc.container.conf.sgml.in b/doc/lxc.container.conf.sgml.in index 43227d8df..665d67ef9 100644 --- a/doc/lxc.container.conf.sgml.in +++ b/doc/lxc.container.conf.sgml.in @@ -1897,11 +1897,10 @@ dev/null proc/kcore none bind,relative 0 0 Section (always 'lxc'). The hook type (i.e. 'clone' or 'pre-mount'). Additional arguments. In the - case of the clone hook, any extra arguments passed to - lxc-clone will appear as further arguments to the hook. - In the case of the stop hook, paths to filedescriptors - for each of the container's namespaces along with their types - are passed. + case of the clone hook, any extra arguments passed will appear as + further arguments to the hook. In the case of the stop hook, paths to + filedescriptors for each of the container's namespaces along with + their types are passed. The following environment variables are set: diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am index b7c4dfccc..e56784bb9 100644 --- a/src/lxc/Makefile.am +++ b/src/lxc/Makefile.am @@ -207,17 +207,6 @@ bin_SCRIPTS += cmd/lxc-checkconfig \ cmd/lxc-update-config endif -if ENABLE_TOOLS -EXTRA_DIST = \ - tools/lxc-top.lua - -if ENABLE_DEPRECATED -if ENABLE_PYTHON -bin_SCRIPTS += tools/lxc-start-ephemeral -endif -endif -endif - if ENABLE_TOOLS bin_PROGRAMS = \ lxc-attach \ @@ -243,10 +232,6 @@ bin_PROGRAMS = \ lxc-unshare \ lxc-usernsexec \ lxc-wait - -if ENABLE_DEPRECATED -bin_PROGRAMS += lxc-clone -endif endif if ENABLE_COMMANDS @@ -297,10 +282,6 @@ endif if ENABLE_TOOLS -if ENABLE_DEPRECATED -lxc_clone_SOURCES = tools/lxc_clone.c tools/arguments.c -endif - if !HAVE_GETSUBOPT lxc_copy_SOURCES += tools/include/getsubopt.c tools/include/getsubopt.h endif diff --git a/src/lxc/tools/lxc-start-ephemeral.in b/src/lxc/tools/lxc-start-ephemeral.in deleted file mode 100644 index 90d5f6f02..000000000 --- a/src/lxc/tools/lxc-start-ephemeral.in +++ /dev/null @@ -1,418 +0,0 @@ -#!/usr/bin/env python3 -# -# lxc-start-ephemeral: Start a copy of a container using an overlay -# -# This python implementation is based on the work done in the original -# shell implementation done by Serge Hallyn in Ubuntu (and other contributors) -# -# (C) Copyright Canonical Ltd. 2012 -# -# Authors: -# Stéphane Graber -# -# 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 -# - -import argparse -import gettext -import lxc -import locale -import os -import sys -import subprocess -import tempfile - -_ = gettext.gettext -gettext.textdomain("lxc-start-ephemeral") - -# Other functions - - -def printstderr(*args): - print("lxc-start-ephemeral is deprecated in favor of lxc-copy\n", - *args, file=sys.stderr) - - -def randomMAC(): - import random - - mac = [0x00, 0x16, 0x3e, - random.randint(0x00, 0x7f), - random.randint(0x00, 0xff), - random.randint(0x00, 0xff)] - return ':'.join(map(lambda x: "%02x" % x, mac)) - - -def get_rundir(): - if os.geteuid() == 0: - return "@RUNTIME_PATH@" - - if "XDG_RUNTIME_DIR" in os.environ: - return os.environ["XDG_RUNTIME_DIR"] - - if "HOME" in os.environ: - return "%s/.cache/lxc/run/" % os.environ["HOME"] - - raise Exception("Unable to find a runtime directory") - - -# Inform that lxc-start-ephemeral is deprecated -printstderr() - -# Begin parsing the command line -parser = argparse.ArgumentParser(description=_( - "LXC: Start an ephemeral container"), - formatter_class=argparse.RawTextHelpFormatter, - epilog=_("If a COMMAND is given, then the " - """container will run only as long -as the command runs. -If no COMMAND is given, this command will attach to tty1 and stop the -container when exiting (with ctrl-a-q). - -If no COMMAND is given and -d is used, the name and IP addresses of the -container will be printed to the console.""")) - -parser.add_argument("--lxcpath", "-P", dest="lxcpath", metavar="PATH", - help=_("Use specified container path"), default=None) - -parser.add_argument("--orig", "-o", type=str, required=True, - help=_("name of the original container")) - -parser.add_argument("--name", "-n", type=str, - help=_("name of the target container")) - -parser.add_argument("--bdir", "-b", type=str, action="append", default=[], - help=_("directory to bind mount into container, " - "either --bdir=/src-path or --bdir=/src-path:/dst-path")) - -parser.add_argument("--cdir", "-c", type=str, action="append", default=[], - help=_("directory to cow mount into container")) - -parser.add_argument("--user", "-u", type=str, - help=_("the user to run the command as")) - -parser.add_argument("--key", "-S", type=str, - help=_("the path to the key to use to connect " - "(when using ssh)")) - -parser.add_argument("--daemon", "-d", action="store_true", - help=_("run in the background")) - -parser.add_argument("--storage-type", "-s", type=str, default=None, - choices=("tmpfs", "dir"), - help=("type of storage use by the container")) - -parser.add_argument("--union-type", "-U", type=str, default="overlayfs", - choices=("overlayfs", "aufs"), - help=_("type of union (overlayfs or aufs), " - "defaults to overlayfs.")) - -parser.add_argument("--keep-data", "-k", action="store_true", - help=_("don't wipe everything clean at the end")) - -parser.add_argument("command", metavar='CMD', type=str, nargs="*", - help=_("Run specific command in container " - "(command as argument)")) - -parser.add_argument("--version", action="version", version=lxc.version) - -args = parser.parse_args() - -# Check that -d and CMD aren't used at the same time -if args.command and args.daemon: - parser.error(_("You can't use -d and a command at the same time.")) - -# Check that -k isn't used with -s tmpfs -if not args.storage_type: - if args.keep_data: - args.storage_type = "dir" - else: - args.storage_type = "tmpfs" - -if args.keep_data and args.storage_type == "tmpfs": - parser.error(_("You can't use -k with the tmpfs storage type.")) - -# Load the orig container -orig = lxc.Container(args.orig, args.lxcpath) -if not orig.defined: - parser.error(_("Source container '%s' doesn't exist." % args.orig)) - -# Create the new container paths -if not args.lxcpath: - lxc_path = lxc.default_config_path -else: - lxc_path = args.lxcpath - -if args.name: - if os.path.exists("%s/%s" % (lxc_path, args.name)): - parser.error(_("A container named '%s' already exists." % args.name)) - dest_path = "%s/%s" % (lxc_path, args.name) - os.mkdir(dest_path) -else: - dest_path = tempfile.mkdtemp(prefix="%s-" % args.orig, dir=lxc_path) -os.mkdir(os.path.join(dest_path, "rootfs")) -os.chmod(dest_path, 0o770) - -# Setup the new container's configuration -dest = lxc.Container(os.path.basename(dest_path), args.lxcpath) -dest.load_config(orig.config_file_name) -dest.set_config_item("lxc.utsname", dest.name) -dest.set_config_item("lxc.rootfs", os.path.join(dest_path, "rootfs")) -print("setting rootfs to .%s.", os.path.join(dest_path, "rootfs")) -for nic in dest.network: - if hasattr(nic, 'hwaddr'): - nic.hwaddr = randomMAC() - -overlay_dirs = [(orig.get_config_item("lxc.rootfs"), "%s/rootfs/" % dest_path)] - -# Generate a new fstab -if orig.get_config_item("lxc.mount"): - dest.set_config_item("lxc.mount", os.path.join(dest_path, "fstab")) - with open(orig.get_config_item("lxc.mount"), "r") as orig_fd: - with open(dest.get_config_item("lxc.mount"), "w+") as dest_fd: - for line in orig_fd.read().split("\n"): - # Start by replacing any reference to the container rootfs - line.replace(orig.get_config_item("lxc.rootfs"), - dest.get_config_item("lxc.rootfs")) - - fields = line.split() - - # Skip invalid entries - if len(fields) < 4: - continue - - # Non-bind mounts are kept as-is - if "bind" not in fields[3]: - dest_fd.write("%s\n" % line) - continue - - # Bind mounts of virtual filesystems are also kept as-is - src_path = fields[0].split("/") - if len(src_path) > 1 and src_path[1] in ("proc", "sys"): - dest_fd.write("%s\n" % line) - continue - - # Skip invalid mount points - dest_mount = os.path.abspath(os.path.join("%s/rootfs/" % ( - dest_path), fields[1])) - - if "%s/rootfs/" % dest_path not in dest_mount: - print(_("Skipping mount entry '%s' as it's outside " - "of the container rootfs.") % line) - - # Setup an overlay for anything remaining - overlay_dirs += [(fields[0], dest_mount)] - -for entry in args.cdir: - if not os.path.exists(entry): - print(_("Path '%s' doesn't exist, won't be cow-mounted.") % - entry) - else: - src_path = os.path.abspath(entry) - dst_path = "%s/rootfs/%s" % (dest_path, src_path) - overlay_dirs += [(src_path, dst_path)] - -# do we have the new overlay fs which requires workdir, or the older -# overlayfs which does not? -have_new_overlay = False -with open("/proc/filesystems", "r") as fd: - for line in fd: - if line == "nodev\toverlay\n": - have_new_overlay = True - -# Generate pre-mount script -with open(os.path.join(dest_path, "pre-mount"), "w+") as fd: - os.fchmod(fd.fileno(), 0o755) - fd.write("""#!/bin/sh -LXC_DIR="%s" -LXC_BASE="%s" -LXC_NAME="%s" -""" % (dest_path, orig.name, dest.name)) - - count = 0 - for entry in overlay_dirs: - tmpdir = "%s/tmpfs" % dest_path - fd.write("mkdir -p %s\n" % (tmpdir)) - if args.storage_type == "tmpfs": - fd.write("mount -n -t tmpfs -o mode=0755 none %s\n" % (tmpdir)) - deltdir = "%s/delta%s" % (tmpdir, count) - workdir = "%s/work%s" % (tmpdir, count) - fd.write("mkdir -p %s %s\n" % (deltdir, entry[1])) - if have_new_overlay: - fd.write("mkdir -p %s\n" % workdir) - - fd.write("getfacl -a %s | setfacl --set-file=- %s || true\n" % - (entry[0], deltdir)) - fd.write("getfacl -a %s | setfacl --set-file=- %s || true\n" % - (entry[0], entry[1])) - - if args.union_type == "overlayfs": - if have_new_overlay: - fd.write("mount -n -t overlay" - " -oupperdir=%s,lowerdir=%s,workdir=%s none %s\n" % ( - deltdir, - entry[0], - workdir, - entry[1])) - else: - fd.write("mount -n -t overlayfs" - " -oupperdir=%s,lowerdir=%s none %s\n" % ( - deltdir, - entry[0], - entry[1])) - elif args.union_type == "aufs": - xino_path = "/dev/shm/aufs.xino" - if not os.path.exists(os.path.basename(xino_path)): - os.makedirs(os.path.basename(xino_path)) - - fd.write("mount -n -t aufs " - "-o br=%s=rw:%s=ro,noplink,xino=%s none %s\n" % ( - deltdir, - entry[0], - xino_path, - entry[1])) - count += 1 - - for entry in args.bdir: - if ':' in entry: - src_path, dst_path = entry.split(":") - else: - src_path = entry - dst_path = os.path.abspath(entry) - - if not os.path.exists(src_path): - print(_("Path '%s' doesn't exist, won't be bind-mounted.") % - src_path) - else: - src_path = os.path.abspath(src_path) - dst_path = "%s/rootfs/%s" % (dest_path, dst_path) - fd.write("mkdir -p %s\nmount -n --bind %s %s\n" % ( - dst_path, src_path, dst_path)) - - fd.write(""" -[ -e $LXC_DIR/configured ] && exit 0 -for file in $LXC_DIR/rootfs/etc/hostname \\ - $LXC_DIR/rootfs/etc/hosts \\ - $LXC_DIR/rootfs/etc/sysconfig/network \\ - $LXC_DIR/rootfs/etc/sysconfig/network-scripts/ifcfg-eth0; do - [ -f "$file" ] && sed -i -e "s/$LXC_BASE/$LXC_NAME/" $file -done -touch $LXC_DIR/configured -""") - -dest.set_config_item("lxc.hook.pre-mount", - os.path.join(dest_path, "pre-mount")) - -if not args.keep_data: - dest.set_config_item("lxc.ephemeral", "1") - -dest.save_config() - -# Start the container -if not dest.start() or not dest.wait("RUNNING", timeout=5): - print(_("The container '%s' failed to start.") % dest.name) - dest.stop() - if dest.defined: - dest.destroy() - sys.exit(1) - -# Deal with the case where we just attach to the container's console -if not args.command and not args.daemon: - dest.console() - if not dest.shutdown(timeout=5): - dest.stop() - sys.exit(0) - -# Try to get the IP addresses -ips = dest.get_ips(timeout=10) - -# Deal with the case where we just print info about the container -if args.daemon: - print(_("""The ephemeral container is now started. - -You can enter it from the command line with: lxc-console -n %s -The following IP addresses have be found in the container: -%s""") % (dest.name, - "\n".join([" - %s" % entry for entry in ips] - or [" - %s" % _("No address could be found")]))) - sys.exit(0) - -# Now deal with the case where we want to run a command in the container -if not ips: - print(_("Failed to get an IP for container '%s'.") % dest.name) - dest.stop() - if dest.defined: - dest.destroy() - sys.exit(1) - -if os.path.exists("/proc/self/ns/pid"): - def attach_as_user(command): - try: - username = "root" - if args.user: - username = args.user - - # This should really just use universal_newlines=True, but we do - # the decoding by hand instead for compatibility with Python - # 3.2; that used locale.getpreferredencoding() internally rather - # than locale.getpreferredencoding(False), and the former breaks - # here because we can't reload codecs at this point unless the - # container has the same version of Python installed. - line = subprocess.check_output(["getent", "passwd", username]) - line = line.decode(locale.getpreferredencoding(False)).rstrip("\n") - _, _, pw_uid, pw_gid, _, pw_dir, _ = line.split(":", 6) - pw_uid = int(pw_uid) - pw_gid = int(pw_gid) - os.setgid(pw_gid) - os.initgroups(username, pw_gid) - os.setuid(pw_uid) - os.chdir(pw_dir) - os.environ['HOME'] = pw_dir - except: - print(_("Unable to switch to user: %s" % username)) - sys.exit(1) - - return lxc.attach_run_command(command) - - retval = dest.attach_wait(attach_as_user, args.command, - env_policy=lxc.LXC_ATTACH_CLEAR_ENV) - -else: - cmd = ["ssh", - "-o", "StrictHostKeyChecking=no", - "-o", "UserKnownHostsFile=/dev/null"] - - if args.user: - cmd += ["-l", args.user] - - if args.key: - cmd += ["-i", args.key] - - for ip in ips: - ssh_cmd = cmd + [ip] + args.command - retval = subprocess.call(ssh_cmd, universal_newlines=True) - if retval == 255: - print(_("SSH failed to connect, trying next IP address.")) - continue - - if retval != 0: - print(_("Command returned with non-zero return code: %s") % retval) - break - -# Shutdown the container -if not dest.shutdown(timeout=5): - dest.stop() - -sys.exit(retval) diff --git a/src/lxc/tools/lxc-top.lua b/src/lxc/tools/lxc-top.lua deleted file mode 100755 index b5b3a695f..000000000 --- a/src/lxc/tools/lxc-top.lua +++ /dev/null @@ -1,243 +0,0 @@ -#!/usr/bin/env lua --- --- top(1) like monitor for lxc containers --- --- Copyright © 2012 Oracle. --- --- Authors: --- Dwight Engen --- --- This library is free software; you can redistribute it and/or modify --- it under the terms of the GNU General Public License version 2, as --- published by the Free Software Foundation. --- --- This program 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 General Public License for more details. --- --- You should have received a copy of the GNU General Public License along --- with this program; if not, write to the Free Software Foundation, Inc., --- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. --- - -local lxc = require("lxc") -local core = require("lxc.core") -local getopt = require("alt_getopt") - -local USER_HZ = 100 -local ESC = string.format("%c", 27) -local TERMCLEAR = ESC.."[H"..ESC.."[J" -local TERMNORM = ESC.."[0m" -local TERMBOLD = ESC.."[1m" -local TERMRVRS = ESC.."[7m" - -local containers = {} -local stats = {} -local stats_total = {} -local max_containers - -function printf(...) - local function wrapper(...) io.write(string.format(...)) end - local status, result = pcall(wrapper, ...) - if not status then - error(result, 2) - end -end - -function string:split(delim, max_cols) - local cols = {} - local start = 1 - local nextc - repeat - nextc = string.find(self, delim, start) - if (nextc and #cols ~= max_cols - 1) then - table.insert(cols, string.sub(self, start, nextc-1)) - start = nextc + #delim - else - table.insert(cols, string.sub(self, start, string.len(self))) - nextc = nil - end - until nextc == nil or start > #self - return cols -end - -function strsisize(size, width) - local KiB = 1024 - local MiB = 1048576 - local GiB = 1073741824 - local TiB = 1099511627776 - local PiB = 1125899906842624 - local EiB = 1152921504606846976 - local ZiB = 1180591620717411303424 - - if (size >= ZiB) then - return string.format("%d.%2.2d ZB", size / ZiB, (math.floor(size % ZiB) * 100) / ZiB) - end - if (size >= EiB) then - return string.format("%d.%2.2d EB", size / EiB, (math.floor(size % EiB) * 100) / EiB) - end - if (size >= PiB) then - return string.format("%d.%2.2d PB", size / PiB, (math.floor(size % PiB) * 100) / PiB) - end - if (size >= TiB) then - return string.format("%d.%2.2d TB", size / TiB, (math.floor(size % TiB) * 100) / TiB) - end - if (size >= GiB) then - return string.format("%d.%2.2d GB", size / GiB, (math.floor(size % GiB) * 100) / GiB) - end - if (size >= MiB) then - return string.format("%d.%2.2d MB", size / MiB, (math.floor(size % MiB) * 1000) / (MiB * 10)) - end - if (size >= KiB) then - return string.format("%d.%2.2d KB", size / KiB, (math.floor(size % KiB) * 1000) / (KiB * 10)) - end - return string.format("%3d.00 ", size) -end - -function tty_lines() - local rows = 25 - local f = assert(io.popen("stty -a | head -n 1")) - for line in f:lines() do - local stty_rows - _,_,stty_rows = string.find(line, "rows (%d+)") - if (stty_rows ~= nil) then - rows = stty_rows - break - end - end - f:close() - return rows -end - -function container_sort(a, b) - if (optarg["r"]) then - if (optarg["s"] == "n") then return (a > b) - elseif (optarg["s"] == "c") then return (stats[a].cpu_use_nanos < stats[b].cpu_use_nanos) - elseif (optarg["s"] == "d") then return (stats[a].blkio < stats[b].blkio) - elseif (optarg["s"] == "m") then return (stats[a].mem_used < stats[b].mem_used) - elseif (optarg["s"] == "k") then return (stats[a].kmem_used < stats[b].kmem_used) - end - else - if (optarg["s"] == "n") then return (a < b) - elseif (optarg["s"] == "c") then return (stats[a].cpu_use_nanos > stats[b].cpu_use_nanos) - elseif (optarg["s"] == "d") then return (stats[a].blkio > stats[b].blkio) - elseif (optarg["s"] == "m") then return (stats[a].mem_used > stats[b].mem_used) - elseif (optarg["s"] == "k") then return (stats[a].kmem_used > stats[b].kmem_used) - end - end -end - -function container_list_update() - local now_running - - now_running = lxc.containers_running(true) - - -- check for newly started containers - for _,v in ipairs(now_running) do - if (containers[v] == nil) then - local ct = lxc.container:new(v) - -- note, this is a "mixed" table, ie both dictionary and list - containers[v] = ct - table.insert(containers, v) - end - end - - -- check for newly stopped containers - local indx = 1 - while (indx <= #containers) do - local ctname = containers[indx] - if (now_running[ctname] == nil) then - containers[ctname] = nil - stats[ctname] = nil - table.remove(containers, indx) - else - indx = indx + 1 - end - end - - -- get stats for all current containers and resort the list - lxc.stats_clear(stats_total) - for _,ctname in ipairs(containers) do - stats[ctname] = containers[ctname]:stats_get(stats_total) - end - table.sort(containers, container_sort) -end - -function stats_print_header(stats_total) - printf(TERMRVRS .. TERMBOLD) - printf("%-15s %8s %8s %8s %10s %10s", "Container", "CPU", "CPU", "CPU", "BlkIO", "Mem") - if (stats_total.kmem_used > 0) then printf(" %10s", "KMem") end - printf("\n") - - printf("%-15s %8s %8s %8s %10s %10s", "Name", "Used", "Sys", "User", "Total", "Used") - if (stats_total.kmem_used > 0) then printf(" %10s", "Used") end - printf("\n") - printf(TERMNORM) -end - -function stats_print(name, stats, stats_total) - printf("%-15s %8.2f %8.2f %8.2f %10s %10s", - name, - stats.cpu_use_nanos / 1000000000, - stats.cpu_use_sys / USER_HZ, - stats.cpu_use_user / USER_HZ, - strsisize(stats.blkio), - strsisize(stats.mem_used)) - if (stats_total.kmem_used > 0) then - printf(" %10s", strsisize(stats.kmem_used)) - end -end - -function usage() - printf("Usage: lxc-top [options]\n" .. - " -h|--help print this help message\n" .. - " -m|--max display maximum number of containers\n" .. - " -d|--delay delay in seconds between refreshes (default: 3.0)\n" .. - " -s|--sort sort by [n,c,d,m] (default: n) where\n" .. - " n = Name\n" .. - " c = CPU use\n" .. - " d = Disk I/O use\n" .. - " m = Memory use\n" .. - " k = Kernel memory use\n" .. - " -r|--reverse sort in reverse (descending) order\n" - ) - os.exit(1) -end - -local long_opts = { - help = "h", - delay = "d", - max = "m", - reverse = "r", - sort = "s", -} - -optarg,optind = alt_getopt.get_opts (arg, "hd:m:rs:", long_opts) -optarg["d"] = tonumber(optarg["d"]) or 3.0 -optarg["m"] = tonumber(optarg["m"]) or tonumber(tty_lines() - 3) -optarg["r"] = optarg["r"] or false -optarg["s"] = optarg["s"] or "n" -if (optarg["h"] ~= nil) then - usage() -end - -while true -do - container_list_update() - -- if some terminal we care about doesn't support the simple escapes, we - -- may fall back to this, or ncurses. ug. - --os.execute("tput clear") - printf(TERMCLEAR) - stats_print_header(stats_total) - for index,ctname in ipairs(containers) do - stats_print(ctname, stats[ctname], stats_total) - printf("\n") - if (index >= optarg["m"]) then - break - end - end - stats_print(string.format("TOTAL (%-2d)", #containers), stats_total, stats_total) - io.flush() - core.usleep(optarg["d"] * 1000000) -end diff --git a/src/lxc/tools/lxc_clone.c b/src/lxc/tools/lxc_clone.c deleted file mode 100644 index b76d8669f..000000000 --- a/src/lxc/tools/lxc_clone.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * - * Copyright © 2013 Serge Hallyn . - * Copyright © 2013 Canonical Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* we pass fssize in bytes */ -static uint64_t get_fssize(char *s) -{ - uint64_t ret; - char *end; - - ret = strtoull(s, &end, 0); - if (end == s) { - fprintf(stderr, - "Invalid blockdev size '%s', using default size\n", s); - return 0; - } - - while (isblank(*end)) - end++; - if (*end == '\0') { - ret *= 1024ULL * 1024ULL; /* MB by default */ - } else if (*end == 'b' || *end == 'B') { - ret *= 1ULL; - } else if (*end == 'k' || *end == 'K') { - ret *= 1024ULL; - } else if (*end == 'm' || *end == 'M') { - ret *= 1024ULL * 1024ULL; - } else if (*end == 'g' || *end == 'G') { - ret *= 1024ULL * 1024ULL * 1024ULL; - } else if (*end == 't' || *end == 'T') { - ret *= 1024ULL * 1024ULL * 1024ULL * 1024ULL; - } else { - fprintf(stderr, "Invalid blockdev unit size '%c' in '%s', " - "using default size\n", - *end, s); - return 0; - } - - return ret; -} - -static void usage(const char *me) -{ - printf("Usage: %s [-s] [-B backingstore] [-L size[unit]] [-K] [-M] [-H]\n", me); - printf(" [-p lxcpath] [-P newlxcpath] orig new\n"); - printf("\n"); - printf(" -s: snapshot rather than copy\n"); - printf(" -B: use specified new backingstore. Default is the same as\n"); - printf(" the original. Options include aufs, btrfs, lvm, overlayfs, \n"); - printf(" dir and loop\n"); - printf(" -L: for blockdev-backed backingstore, use specified size * specified\n"); - printf(" unit. Default size is the size of the source blockdev, default\n"); - printf(" unit is MB\n"); - printf(" -K: Keep name - do not change the container name\n"); - printf(" -M: Keep macaddr - do not choose a random new mac address\n"); - printf(" -p: use container orig from custom lxcpath\n"); - printf(" -P: create container new in custom lxcpath\n"); - printf(" -R: rename existing container\n"); - exit(EXIT_SUCCESS); -} - -static struct option options[] = { - { "snapshot", no_argument, 0, 's'}, - { "backingstore", required_argument, 0, 'B'}, - { "size", required_argument, 0, 'L'}, - { "orig", required_argument, 0, 'o'}, - { "new", required_argument, 0, 'n'}, - { "vgname", required_argument, 0, 'v'}, - { "rename", no_argument, 0, 'R'}, - { "keepname", no_argument, 0, 'K'}, - { "keepmac", no_argument, 0, 'M'}, - { "lxcpath", required_argument, 0, 'p'}, - { "newpath", required_argument, 0, 'P'}, - { "fstype", required_argument, 0, 't'}, - { "help", no_argument, 0, 'h'}, - { 0, 0, 0, 0 }, -}; - -int main(int argc, char *argv[]) -{ - struct lxc_container *c1 = NULL, *c2 = NULL; - int snapshot = 0, keepname = 0, keepmac = 0, rename = 0; - int flags = 0, option_index; - uint64_t newsize = 0; - char *bdevtype = NULL, *lxcpath = NULL, *newpath = NULL, *fstype = NULL; - char *orig = NULL, *new = NULL, *vgname = NULL; - char **args = NULL; - int c; - bool ret; - - fprintf(stderr, "lxc-clone is deprecated in favor of lxc-copy.\n\n"); - - if (argc < 3) - usage(argv[0]); - - while (true) { - c = getopt_long(argc, argv, "sB:L:o:n:v:KMHp:P:Rt:h", options, - &option_index); - if (c == -1) - break; - switch (c) { - case 's': - snapshot = 1; - break; - case 'B': - bdevtype = optarg; - break; - case 'L': - newsize = get_fssize(optarg); - break; - case 'o': - orig = optarg; - break; - case 'n': - new = optarg; - break; - case 'v': - vgname = optarg; - break; - case 'K': - keepname = 1; - break; - case 'M': - keepmac = 1; - break; - case 'p': - lxcpath = optarg; - break; - case 'P': - newpath = optarg; - break; - case 'R': - rename = 1; - break; - case 't': - fstype = optarg; - break; - case 'h': - usage(argv[0]); - default: - break; - } - } - - if (optind < argc && !orig) - orig = argv[optind++]; - - if (optind < argc && !new) - new = argv[optind++]; - - /* arguments for the clone hook */ - if (optind < argc) - args = &argv[optind]; - - if (!new || !orig) { - printf("Error: you must provide orig and new names\n"); - usage(argv[0]); - } - - if (snapshot) - flags |= LXC_CLONE_SNAPSHOT; - if (keepname) - flags |= LXC_CLONE_KEEPNAME; - if (keepmac) - flags |= LXC_CLONE_KEEPMACADDR; - - /* vgname and fstype could be supported by sending them through the - * bdevdata. However, they currently are not yet. I'm not convinced - * they are worthwhile. - */ - if (vgname) { - printf("Error: vgname not supported\n"); - usage(argv[0]); - } - if (fstype) { - printf("Error: fstype not supported\n"); - usage(argv[0]); - } - - c1 = lxc_container_new(orig, lxcpath); - if (!c1) - exit(EXIT_FAILURE); - - if (!c1->may_control(c1)) { - fprintf(stderr, "Insufficent privileges to control %s\n", orig); - lxc_container_put(c1); - exit(EXIT_FAILURE); - } - - if (!c1->is_defined(c1)) { - fprintf(stderr, "Error: container %s is not defined\n", orig); - lxc_container_put(c1); - exit(EXIT_FAILURE); - } - if (rename) { - ret = c1->rename(c1, new); - if (!ret) { - fprintf(stderr, - "Error: Renaming container %s to %s failed\n", - c1->name, new); - lxc_container_put(c1); - exit(EXIT_FAILURE); - } - } else { - c2 = c1->clone(c1, new, newpath, flags, bdevtype, NULL, newsize, args); - if (c2 == NULL) { - lxc_container_put(c1); - fprintf(stderr, "clone failed\n"); - exit(EXIT_FAILURE); - } - printf("Created container %s as %s of %s\n", new, - snapshot ? "snapshot" : "copy", orig); - lxc_container_put(c2); - } - lxc_container_put(c1); - - exit(EXIT_SUCCESS); -} diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am index a2afd9a93..f39c3e047 100644 --- a/src/tests/Makefile.am +++ b/src/tests/Makefile.am @@ -65,7 +65,9 @@ bin_PROGRAMS = lxc-test-containertests lxc-test-locktests lxc-test-startone \ lxc-test-api-reboot lxc-test-state-server lxc-test-share-ns \ lxc-test-criu-check-feature lxc-test-raw-clone -bin_SCRIPTS = lxc-test-automount \ +bin_SCRIPTS = +if ENABLE_TOOLS +bin_SCRIPTS += lxc-test-automount \ lxc-test-autostart \ lxc-test-cloneconfig \ lxc-test-createconfig \ @@ -82,6 +84,7 @@ bin_SCRIPTS += \ lxc-test-unpriv \ lxc-test-usernic endif +endif endif From b52a5bef6fa56481a6d817f4c73cb91ed012fe2c Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Wed, 14 Feb 2018 11:48:20 +0100 Subject: [PATCH 03/12] tree-wide: remove lua bindings Signed-off-by: Christian Brauner --- .travis.yml | 2 +- Makefile.am | 4 - configure.ac | 50 --- lxc.spec.in | 21 -- src/Makefile.am | 2 +- src/lua-lxc/Makefile.am | 38 --- src/lua-lxc/core.c | 614 ----------------------------------- src/lua-lxc/lxc.lua | 421 ------------------------ src/lua-lxc/test/apitest.lua | 353 -------------------- 9 files changed, 2 insertions(+), 1503 deletions(-) delete mode 100644 src/lua-lxc/Makefile.am delete mode 100644 src/lua-lxc/core.c delete mode 100755 src/lua-lxc/lxc.lua delete mode 100755 src/lua-lxc/test/apitest.lua diff --git a/.travis.yml b/.travis.yml index d078b0222..ca354ccc0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,7 @@ before_install: - echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- - sudo add-apt-repository ppa:ubuntu-lxc/daily -y - sudo apt-get update -qq - - sudo apt-get install -qq libapparmor-dev libcap-dev libseccomp-dev python3-dev python3-setuptools docbook2x libgnutls-dev liblua5.2-dev libselinux1-dev + - sudo apt-get install -qq libapparmor-dev libcap-dev libseccomp-dev python3-dev python3-setuptools docbook2x libgnutls-dev libselinux1-dev script: - ./autogen.sh - rm -Rf build diff --git a/Makefile.am b/Makefile.am index 4071ec929..14712bc43 100644 --- a/Makefile.am +++ b/Makefile.am @@ -13,10 +13,6 @@ EXTRA_DIST = \ RPMARGS = -if ENABLE_LUA -RPMARGS += --with lua -endif - if ENABLE_PYTHON RPMARGS += --with python endif diff --git a/configure.ac b/configure.ac index 6da315952..8c1f806aa 100644 --- a/configure.ac +++ b/configure.ac @@ -416,53 +416,6 @@ m4_ifdef([PKG_CHECK_VAR], [], ])# PKG_CHECK_VAR ]) -# Lua module and scripts -AC_ARG_ENABLE([lua], - [AC_HELP_STRING([--enable-lua], [enable lua binding [default=auto]])], - [], [enable_lua=auto]) - -AC_ARG_WITH([lua-pc], - [AS_HELP_STRING( - [--with-lua-pc=PKG], - [Specify pkg-config package name for lua] - )], [], [with_lua_pc=no]) - -if test "x$enable_lua" = "xyes" -a "x$with_lua_pc" != "xno"; then - # exit with error if not found - PKG_CHECK_MODULES([LUA], [$with_lua_pc], [LUAPKGCONFIG=$with_lua_pc]) -fi - -if test "x$enable_lua" = "xauto" -a "x$with_lua_pc" != "xno"; then - PKG_CHECK_MODULES([LUA], [$with_lua_pc], - [LUAPKGCONFIG=$with_lua_pc - enable_lua=yes], - [enable_lua=no]) -fi - -if test "x$enable_lua" != "xno"; then - PKG_CHECK_MODULES([LUA], [lua], [LUAPKGCONFIG=lua], - [PKG_CHECK_MODULES([LUA], [lua5.2], [LUAPKGCONFIG=lua5.2], - [PKG_CHECK_MODULES([LUA], [lua5.1], [LUAPKGCONFIG=lua5.1], - [AS_IF([test "x$enable_lua" = "xyes"], - [AC_MSG_ERROR([Lua not found. Please use --with-lua-pc=PKG])], - [enable_lua=no])] - )] - )]) - AS_IF([test "x$LUAPKGCONFIG" != "x"], [enable_lua=yes]) -fi - -AM_CONDITIONAL([ENABLE_LUA], - [test "x$enable_lua" = "xyes"]) - -AM_COND_IF([ENABLE_LUA], - [AC_MSG_CHECKING([Lua version]) - PKG_CHECK_VAR([LUA_VERSION], [$LUAPKGCONFIG], [V],, - [PKG_CHECK_VAR([LUA_VERSION], [$LUAPKGCONFIG], [major_version])]) - AC_MSG_RESULT([$LUA_VERSION]) - AC_SUBST([LUA_LIBDIR], [$libdir/lua/$LUA_VERSION]) - AC_SUBST([LUA_SHAREDIR], [$datadir/lua/$LUA_VERSION]) - ]) - # Optional bash integration AC_ARG_ENABLE([bash], [AC_HELP_STRING([--enable-bash], [build bash integration [default=yes]])], @@ -943,8 +896,6 @@ AC_CONFIG_FILES([ src/lxc/version.h src/python-lxc/Makefile - src/lua-lxc/Makefile - src/tests/Makefile src/tests/lxc-test-usernic ]) @@ -1007,7 +958,6 @@ PAM: - cgroup PAM module: $pamdir Bindings: - - lua: $enable_lua - python3: $enable_python Documentation: diff --git a/lxc.spec.in b/lxc.spec.in index 9aa7dd4c8..f750b1e18 100644 --- a/lxc.spec.in +++ b/lxc.spec.in @@ -21,7 +21,6 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA %global with_python %{?_with_python: 1} %{?!_with_python: 0} -%global with_lua %{?_with_lua: 1} %{?!_with_lua: 0} # Set with_systemd on distros that use it, so we can install the service # file, otherwise the sysvinit script will be installed @@ -124,23 +123,10 @@ Requires: %{name} = %{version}-%{release}, pkgconfig The %{name}-devel package contains header files and library needed for development of the Linux containers. -%if %{with_lua} -%package lua -Summary: Lua bindings for %{name} -Group: System Environment/Libraries -Requires: lua-filesystem lua-alt-getopt -BuildRequires: lua-devel -%description lua -The %{name}-lua package contains %{name} bindings for lua. -%endif - %prep %setup -q -n %{name}-%{version}%{?beta_dot} %build PATH=$PATH:/usr/sbin:/sbin %configure $args \ -%if %{with_lua} - --enable-lua \ -%endif %if %{with_python} --enable-python \ %endif @@ -284,13 +270,6 @@ fi %{python3_sitearch}/* %endif -%if %{with_lua} -%files lua -%defattr(-,root,root) -%{_datadir}/lua -%{_libdir}/lua -%endif - %files devel %defattr(-,root,root) %{_includedir}/%{name}/* diff --git a/src/Makefile.am b/src/Makefile.am index c96cbe79f..4e4d66b5e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1 +1 @@ -SUBDIRS = lxc tests python-lxc lua-lxc +SUBDIRS = lxc tests python-lxc diff --git a/src/lua-lxc/Makefile.am b/src/lua-lxc/Makefile.am deleted file mode 100644 index 348de8d38..000000000 --- a/src/lua-lxc/Makefile.am +++ /dev/null @@ -1,38 +0,0 @@ -if ENABLE_LUA - -luasharedir=$(LUA_SHAREDIR) -lualibdir=$(LUA_LIBDIR) -luadir=$(luasharedir) -sodir=$(lualibdir)/lxc - -lua_DATA=lxc.lua - -lib_LTLIBRARIES = libcore.la -libcore_la_SOURCES = core.c - -AM_CFLAGS=-I$(top_builddir)/src -I$(top_srcdir)/src $(LUA_CFLAGS) -DVERSION=\"$(VERSION)\" -DLXCPATH=\"$(LXCPATH)\" - -libcore_la_CFLAGS = -fPIC -DPIC $(AM_CFLAGS) - -libcore_la_LDFLAGS = \ - -shared \ - -L$(top_builddir)/src/lxc \ - -Wl,-soname,core.so.$(firstword $(subst ., ,$(VERSION))) - -libcore_la_LIBADD = -llxc - -install-exec-local: install-libLTLIBRARIES - mkdir -p $(DESTDIR)$(lualibdir)/lxc/ - mv $(DESTDIR)$(libdir)/libcore.so.0.0.0 $(DESTDIR)$(lualibdir)/lxc/core.so - rm $(DESTDIR)$(libdir)/libcore.* - -uninstall-local: - $(RM) $(DESTDIR)$(lualibdir)/lxc/core.so* - -lxc.lua: - -endif - -EXTRA_DIST= \ - lxc.lua \ - test/apitest.lua diff --git a/src/lua-lxc/core.c b/src/lua-lxc/core.c deleted file mode 100644 index 3fb915ba4..000000000 --- a/src/lua-lxc/core.c +++ /dev/null @@ -1,614 +0,0 @@ -/* - * lua-lxc: lua bindings for lxc - * - * Copyright © 2012 Oracle. - * - * Authors: - * Dwight Engen - * - * 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 - */ - -#define LUA_LIB -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include "lxc/commands.h" - -#if LUA_VERSION_NUM < 502 -#define luaL_newlib(L,l) (lua_newtable(L), luaL_register(L,NULL,l)) -#define luaL_setfuncs(L,l,n) (assert(n==0), luaL_register(L,NULL,l)) -#define luaL_checkunsigned(L,n) luaL_checknumber(L,n) -#endif - -#if LUA_VERSION_NUM >= 503 -#ifndef luaL_checkunsigned -#define luaL_checkunsigned(L,n) ((lua_Unsigned)luaL_checkinteger(L,n)) -#endif -#endif - -#ifdef NO_CHECK_UDATA -#define checkudata(L,i,tname) lua_touserdata(L, i) -#else -#define checkudata(L,i,tname) luaL_checkudata(L, i, tname) -#endif - -#define lua_boxpointer(L,u) \ - (*(void **) (lua_newuserdata(L, sizeof(void *))) = (u)) - -#define lua_unboxpointer(L,i,tname) \ - (*(void **) (checkudata(L, i, tname))) - -#define CONTAINER_TYPENAME "lxc.container" - -/* Max Lua arguments for function */ -#define MAXVARS 200 - -static int container_new(lua_State *L) -{ - struct lxc_container *c; - const char *name = luaL_checkstring(L, 1); - const char *configpath = NULL; - int argc = lua_gettop(L); - - if (argc > 1) - configpath = luaL_checkstring(L, 2); - - c = lxc_container_new(name, configpath); - if (c) { - lua_boxpointer(L, c); - luaL_getmetatable(L, CONTAINER_TYPENAME); - lua_setmetatable(L, -2); - } else { - lua_pushnil(L); - } - return 1; -} - -static int container_gc(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - - /* XXX what to do if this fails? */ - lxc_container_put(c); - return 0; -} - -static int container_config_file_name(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - char *config_file_name; - - config_file_name = c->config_file_name(c); - lua_pushstring(L, config_file_name); - free(config_file_name); - return 1; -} - -static int container_defined(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - - lua_pushboolean(L, !!c->is_defined(c)); - return 1; -} - -static int container_name(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - - lua_pushstring(L, c->name); - return 1; -} - -static int container_create(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - char *template_name = strdupa(luaL_checkstring(L, 2)); - int argc = lua_gettop(L); - char **argv; - int i; - - argv = alloca((argc+1) * sizeof(char *)); - for (i = 0; i < argc-2; i++) - argv[i] = strdupa(luaL_checkstring(L, i+3)); - argv[i] = NULL; - - lua_pushboolean(L, !!c->create(c, template_name, NULL, NULL, 0, argv)); - return 1; -} - -static int container_destroy(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - - lua_pushboolean(L, !!c->destroy(c)); - return 1; -} - -/* container state */ -static int container_start(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - int argc = lua_gettop(L); - char **argv = NULL; - int i,j; - int useinit = 0; - - if (argc > 1) { - argv = alloca((argc+1) * sizeof(char *)); - for (i = 0, j = 0; i < argc-1; i++) { - const char *arg = luaL_checkstring(L, i+2); - - if (!strcmp(arg, "useinit")) - useinit = 1; - else - argv[j++] = strdupa(arg); - } - argv[j] = NULL; - } - - c->want_daemonize(c, true); - lua_pushboolean(L, !!c->start(c, useinit, argv)); - return 1; -} - -static int container_stop(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - - lua_pushboolean(L, !!c->stop(c)); - return 1; -} - -static int container_shutdown(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - int timeout = luaL_checkinteger(L, 2); - - lua_pushboolean(L, !!c->shutdown(c, timeout)); - return 1; -} - -static int container_wait(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - const char *state = luaL_checkstring(L, 2); - int timeout = luaL_checkinteger(L, 3); - - lua_pushboolean(L, !!c->wait(c, state, timeout)); - return 1; -} - -static int container_rename(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - const char *new_name; - int argc = lua_gettop(L); - - if (argc > 1) { - new_name = luaL_checkstring(L, 2); - lua_pushboolean(L, !!c->rename(c, new_name)); - } else - lua_pushnil(L); - return 1; -} - -static int container_freeze(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - - lua_pushboolean(L, !!c->freeze(c)); - return 1; -} - -static int container_unfreeze(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - - lua_pushboolean(L, !!c->unfreeze(c)); - return 1; -} - -static int container_running(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - - lua_pushboolean(L, !!c->is_running(c)); - return 1; -} - -static int container_state(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - - lua_pushstring(L, c->state(c)); - return 1; -} - -static int container_init_pid(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - - lua_pushinteger(L, c->init_pid(c)); - return 1; -} - -/* configuration file methods */ -static int container_load_config(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - int arg_cnt = lua_gettop(L); - const char *alt_path = NULL; - - if (arg_cnt > 1) - alt_path = luaL_checkstring(L, 2); - - lua_pushboolean(L, !!c->load_config(c, alt_path)); - return 1; -} - -static int container_save_config(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - int arg_cnt = lua_gettop(L); - const char *alt_path = NULL; - - if (arg_cnt > 1) - alt_path = luaL_checkstring(L, 2); - - lua_pushboolean(L, !!c->save_config(c, alt_path)); - return 1; -} - -static int container_get_config_path(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - const char *config_path; - - config_path = c->get_config_path(c); - lua_pushstring(L, config_path); - return 1; -} - -static int container_set_config_path(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - const char *config_path = luaL_checkstring(L, 2); - - lua_pushboolean(L, !!c->set_config_path(c, config_path)); - return 1; -} - -static int container_clear_config_item(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - const char *key = luaL_checkstring(L, 2); - - lua_pushboolean(L, !!c->clear_config_item(c, key)); - return 1; -} - -static int container_get_cgroup_item(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - const char *key = luaL_checkstring(L, 2); - int len; - char *value; - - len = c->get_cgroup_item(c, key, NULL, 0); - if (len <= 0) - goto not_found; - - value = alloca(sizeof(char)*len + 1); - if (c->get_cgroup_item(c, key, value, len + 1) != len) - goto not_found; - - lua_pushstring(L, value); - return 1; - -not_found: - lua_pushnil(L); - return 1; -} - -static int container_get_config_item(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - const char *key = luaL_checkstring(L, 2); - int len; - char *value; - - len = c->get_config_item(c, key, NULL, 0); - if (len <= 0) - goto not_found; - - value = alloca(sizeof(char)*len + 1); - if (c->get_config_item(c, key, value, len + 1) != len) - goto not_found; - - lua_pushstring(L, value); - return 1; - -not_found: - lua_pushnil(L); - return 1; -} - -static int container_set_cgroup_item(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - const char *key = luaL_checkstring(L, 2); - const char *value = luaL_checkstring(L, 3); - - lua_pushboolean(L, !!c->set_cgroup_item(c, key, value)); - return 1; -} - -static int container_set_config_item(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - const char *key = luaL_checkstring(L, 2); - const char *value = luaL_checkstring(L, 3); - - lua_pushboolean(L, !!c->set_config_item(c, key, value)); - return 1; -} - -static int container_get_keys(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - const char *key = NULL; - int len; - char *value; - int arg_cnt = lua_gettop(L); - - if (arg_cnt > 1) - key = luaL_checkstring(L, 2); - - len = c->get_keys(c, key, NULL, 0); - if (len <= 0) - goto not_found; - - value = alloca(sizeof(char)*len + 1); - if (c->get_keys(c, key, value, len + 1) != len) - goto not_found; - - lua_pushstring(L, value); - return 1; - -not_found: - lua_pushnil(L); - return 1; -} - -static int container_attach(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - int argc = lua_gettop(L); - char **argv = NULL; - int i; - - if (argc > 1) { - argv = alloca((argc+1) * sizeof(char *)); - for (i = 0; i < argc-1; i++) { - const char *arg = luaL_checkstring(L, i+2); - argv[i] = strdupa(arg); - } - argv[i] = NULL; - } - else - { - lua_pushnil(L); - return 1; - } - - lua_pushboolean(L, !(c->attach_run_wait(c, NULL, argv[0], (const char**)argv))); - return 1; -} - -static int container_get_interfaces(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - char **ifaces; - int i; - - ifaces = c->get_interfaces(c); - - if (!ifaces){ - lua_pushnil(L); - return 1; - } - - for (i = 0; ifaces[i]; i++); - - /* protect LUA stack form overflow */ - if (i > MAXVARS || !lua_checkstack(L, i)){ - for (i = 0; ifaces[i]; i++) - free(ifaces[i]); - lua_pushnil(L); - return 1; - } - for (i = 0; ifaces[i]; i++){ - lua_pushstring(L, ifaces[i]); - free(ifaces[i]); - } - return i; -} - -static int container_get_ips(lua_State *L) -{ - struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); - int argc = lua_gettop(L); - char **addresses; - char *iface = NULL, *family = NULL; - int i, scope = 0; - - if (argc > 1) - iface = (char *)luaL_checkstring(L, 2); - if (argc > 2) - family = (char *)luaL_checkstring(L, 3); - if (argc > 3) - scope = luaL_checkinteger(L, 4); - - addresses = c->get_ips(c, iface, family, scope); - - if (!addresses){ - lua_pushnil(L); - return 1; - } - - for (i = 0; addresses[i]; i++); - - /* protect LUA stack form overflow */ - if (i > MAXVARS || !lua_checkstack(L, i)){ - for (i = 0; addresses[i]; i++) - free(addresses[i]); - lua_pushnil(L); - return 1; - } - for (i = 0; addresses[i]; i++){ - lua_pushstring(L, addresses[i]); - free(addresses[i]); - } - return i; -} - -static luaL_Reg lxc_container_methods[] = -{ - {"attach", container_attach}, - {"create", container_create}, - {"defined", container_defined}, - {"destroy", container_destroy}, - {"init_pid", container_init_pid}, - {"name", container_name}, - {"running", container_running}, - {"state", container_state}, - {"freeze", container_freeze}, - {"unfreeze", container_unfreeze}, - {"start", container_start}, - {"stop", container_stop}, - {"shutdown", container_shutdown}, - {"wait", container_wait}, - {"rename", container_rename}, - - {"config_file_name", container_config_file_name}, - {"load_config", container_load_config}, - {"save_config", container_save_config}, - {"get_cgroup_item", container_get_cgroup_item}, - {"set_cgroup_item", container_set_cgroup_item}, - {"get_config_path", container_get_config_path}, - {"set_config_path", container_set_config_path}, - {"get_config_item", container_get_config_item}, - {"set_config_item", container_set_config_item}, - {"clear_config_item", container_clear_config_item}, - {"get_keys", container_get_keys}, - {"get_interfaces", container_get_interfaces}, - {"get_ips", container_get_ips}, - {NULL, NULL} -}; - -static int lxc_version_get(lua_State *L) { - lua_pushstring(L, VERSION); - return 1; -} - -static int lxc_default_config_path_get(lua_State *L) { - const char *lxcpath = lxc_get_global_config_item("lxc.lxcpath"); - - lua_pushstring(L, lxcpath); - return 1; -} - -static int cmd_get_config_item(lua_State *L) -{ - int arg_cnt = lua_gettop(L); - const char *name = luaL_checkstring(L, 1); - const char *key = luaL_checkstring(L, 2); - const char *lxcpath = NULL; - char *value; - - if (arg_cnt > 2) - lxcpath = luaL_checkstring(L, 3); - - value = lxc_cmd_get_config_item(name, key, lxcpath); - if (!value) - goto not_found; - - lua_pushstring(L, value); - return 1; - -not_found: - lua_pushnil(L); - return 1; -} - -/* utility functions */ -static int lxc_util_usleep(lua_State *L) { - usleep((useconds_t)luaL_checkunsigned(L, 1)); - return 0; -} - -static int lxc_util_dirname(lua_State *L) { - char *path = strdupa(luaL_checkstring(L, 1)); - lua_pushstring(L, dirname(path)); - return 1; -} - -static luaL_Reg lxc_lib_methods[] = { - {"version_get", lxc_version_get}, - {"default_config_path_get", lxc_default_config_path_get}, - {"cmd_get_config_item", cmd_get_config_item}, - {"container_new", container_new}, - {"usleep", lxc_util_usleep}, - {"dirname", lxc_util_dirname}, - {NULL, NULL} -}; - -static int lxc_lib_uninit(lua_State *L) { - (void) L; - /* this is where we would fini liblxc.so if we needed to */ - return 0; -} - -LUALIB_API int luaopen_lxc_core(lua_State *L) { - /* this is where we would initialize liblxc.so if we needed to */ - - luaL_newlib(L, lxc_lib_methods); - - lua_newuserdata(L, 0); - lua_newtable(L); /* metatable */ - lua_pushvalue(L, -1); - lua_pushliteral(L, "__gc"); - lua_pushcfunction(L, lxc_lib_uninit); - lua_rawset(L, -3); - lua_setmetatable(L, -3); - lua_rawset(L, -3); - - luaL_newmetatable(L, CONTAINER_TYPENAME); - luaL_setfuncs(L, lxc_container_methods, 0); - lua_pushvalue(L, -1); /* push metatable */ - lua_pushstring(L, "__gc"); - lua_pushcfunction(L, container_gc); - lua_settable(L, -3); - lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ - lua_pop(L, 1); - return 1; -} diff --git a/src/lua-lxc/lxc.lua b/src/lua-lxc/lxc.lua deleted file mode 100755 index 3d1de1014..000000000 --- a/src/lua-lxc/lxc.lua +++ /dev/null @@ -1,421 +0,0 @@ --- --- lua lxc module --- --- Copyright © 2012 Oracle. --- --- Authors: --- Dwight Engen --- --- 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 --- - -local core = require("lxc.core") -local lfs = require("lfs") -local table = require("table") -local string = require("string") -local io = require("io") -module("lxc", package.seeall) - -local lxc_path -local log_level = 3 - --- lua 5.1 compat -if table.unpack == nil then - table.unpack = unpack -end - --- the following two functions can be useful for debugging -function printf(...) - local function wrapper(...) io.write(string.format(...)) end - local status, result = pcall(wrapper, ...) - if not status then - error(result, 2) - end -end - -function log(level, ...) - if (log_level >= level) then - printf(os.date("%Y-%m-%d %T ")) - printf(...) - end -end - -function string:split(delim, max_cols) - local cols = {} - local start = 1 - local nextc - repeat - nextc = string.find(self, delim, start) - if (nextc and #cols ~= max_cols - 1) then - table.insert(cols, string.sub(self, start, nextc-1)) - start = nextc + #delim - else - table.insert(cols, string.sub(self, start, string.len(self))) - nextc = nil - end - until nextc == nil or start > #self - return cols -end - --- container class -container = {} -container_mt = {} -container_mt.__index = container - -function container:new(lname, config) - local lcore - local lnetcfg = {} - local lstats = {} - - if lname then - if config then - lcore = core.container_new(lname, config) - else - lcore = core.container_new(lname) - end - end - - return setmetatable({ctname = lname, core = lcore, netcfg = lnetcfg, stats = lstats}, container_mt) -end - --- methods interfacing to core functionality -function container:attach(what, ...) - return self.core:attach(what, ...) -end - -function container:config_file_name() - return self.core:config_file_name() -end - -function container:defined() - return self.core:defined() -end - -function container:init_pid() - return self.core:init_pid() -end - -function container:name() - return self.core:name() -end - -function container:start() - return self.core:start() -end - -function container:stop() - return self.core:stop() -end - -function container:shutdown(timeout) - return self.core:shutdown(timeout) -end - -function container:wait(state, timeout) - return self.core:wait(state, timeout) -end - -function container:freeze() - return self.core:freeze() -end - -function container:unfreeze() - return self.core:unfreeze() -end - -function container:running() - return self.core:running() -end - -function container:state() - return self.core:state() -end - -function container:create(template, ...) - return self.core:create(template, ...) -end - -function container:destroy() - return self.core:destroy() -end - --- return nil if name missing -function container:rename(name) - return self.core:rename(name) -end - -function container:get_config_path() - return self.core:get_config_path() -end - -function container:set_config_path(path) - return self.core:set_config_path(path) -end - -function container:append_config_item(key, value) - return self.core:set_config_item(key, value) -end - -function container:clear_config_item(key) - return self.core:clear_config_item(key) -end - -function container:get_cgroup_item(key) - return self.core:get_cgroup_item(key) -end - -function container:get_config_item(key) - local value - local vals = {} - - value = self.core:get_config_item(key) - - -- check if it is a single item - if (not value or not string.find(value, "\n")) then - return value - end - - -- it must be a list type item, make a table of it - vals = value:split("\n", 1000) - -- make it a "mixed" table, ie both dictionary and list for ease of use - for _,v in ipairs(vals) do - vals[v] = true - end - return vals -end - -function container:set_cgroup_item(key, value) - return self.core:set_cgroup_item(key, value) -end - -function container:set_config_item(key, value) - return self.core:set_config_item(key, value) -end - -function container:get_keys(base) - local ktab = {} - local keys - - if (base) then - keys = self.core:get_keys(base) - base = base .. "." - else - keys = self.core:get_keys() - base = "" - end - if (keys == nil) then - return nil - end - keys = keys:split("\n", 1000) - for _,v in ipairs(keys) do - local config_item = base .. v - ktab[v] = self.core:get_config_item(config_item) - end - return ktab -end - --- return nil or more args -function container:get_interfaces() - return self.core:get_interfaces() -end - --- return nil or more args -function container:get_ips(...) - return self.core:get_ips(...) -end - -function container:load_config(alt_path) - if (alt_path) then - return self.core:load_config(alt_path) - else - return self.core:load_config() - end -end - -function container:save_config(alt_path) - if (alt_path) then - return self.core:save_config(alt_path) - else - return self.core:save_config() - end -end - --- methods for stats collection from various cgroup files --- read integers at given coordinates from a cgroup file -function container:stat_get_ints(item, coords) - local lines = {} - local result = {} - local flines = self:get_cgroup_item(item) - - if (flines == nil) then - for k,c in ipairs(coords) do - table.insert(result, 0) - end - else - for line in flines:gmatch("[^\r\n]+") do - table.insert(lines, line) - end - for k,c in ipairs(coords) do - local col - - col = lines[c[1]]:split(" ", 80) - local val = tonumber(col[c[2]]) - table.insert(result, val) - end - end - return table.unpack(result) -end - --- read an integer from a cgroup file -function container:stat_get_int(item) - local line = self:get_cgroup_item(item) - -- if line is nil (on an error like Operation not supported because - -- CONFIG_MEMCG_SWAP_ENABLED isn't enabled) return 0 - return tonumber(line) or 0 -end - -function container:stat_match_get_int(item, match, column) - local val - local lines = self:get_cgroup_item(item) - - if (lines == nil) then - return 0 - end - - for line in lines:gmatch("[^\r\n]+") do - if (string.find(line, match)) then - local col - - col = line:split(" ", 80) - val = tonumber(col[column]) or 0 - end - end - - return val -end - -function container:stats_get(total) - local stat = {} - stat.mem_used = self:stat_get_int("memory.usage_in_bytes") - stat.mem_limit = self:stat_get_int("memory.limit_in_bytes") - stat.memsw_used = self:stat_get_int("memory.memsw.usage_in_bytes") - stat.memsw_limit = self:stat_get_int("memory.memsw.limit_in_bytes") - stat.kmem_used = self:stat_get_int("memory.kmem.usage_in_bytes") - stat.kmem_limit = self:stat_get_int("memory.kmem.limit_in_bytes") - stat.cpu_use_nanos = self:stat_get_int("cpuacct.usage") - stat.cpu_use_user, - stat.cpu_use_sys = self:stat_get_ints("cpuacct.stat", {{1, 2}, {2, 2}}) - stat.blkio = self:stat_match_get_int("blkio.throttle.io_service_bytes", "Total", 2) - - if (total) then - total.mem_used = total.mem_used + stat.mem_used - total.mem_limit = total.mem_limit + stat.mem_limit - total.memsw_used = total.memsw_used + stat.memsw_used - total.memsw_limit = total.memsw_limit + stat.memsw_limit - total.kmem_used = total.kmem_used + stat.kmem_used - total.kmem_limit = total.kmem_limit + stat.kmem_limit - total.cpu_use_nanos = total.cpu_use_nanos + stat.cpu_use_nanos - total.cpu_use_user = total.cpu_use_user + stat.cpu_use_user - total.cpu_use_sys = total.cpu_use_sys + stat.cpu_use_sys - total.blkio = total.blkio + stat.blkio - end - return stat -end - -local M = { container = container } - -function M.stats_clear(stat) - stat.mem_used = 0 - stat.mem_limit = 0 - stat.memsw_used = 0 - stat.memsw_limit = 0 - stat.kmem_used = 0 - stat.kmem_limit = 0 - stat.cpu_use_nanos = 0 - stat.cpu_use_user = 0 - stat.cpu_use_sys = 0 - stat.blkio = 0 -end - --- return configured containers found in LXC_PATH directory -function M.containers_configured(names_only) - local containers = {} - - for dir in lfs.dir(lxc_path) do - if (dir ~= "." and dir ~= "..") - then - local cfgfile = lxc_path .. "/" .. dir .. "/config" - local cfgattr = lfs.attributes(cfgfile) - - if (cfgattr and cfgattr.mode == "file") then - if (names_only) then - -- note, this is a "mixed" table, ie both dictionary and list - containers[dir] = true - table.insert(containers, dir) - else - local ct = container:new(dir) - -- note, this is a "mixed" table, ie both dictionary and list - containers[dir] = ct - table.insert(containers, dir) - end - end - end - end - table.sort(containers, function (a,b) return (a < b) end) - return containers -end - --- return running containers found in cgroup fs -function M.containers_running(names_only) - local containers = {} - local names = M.containers_configured(true) - - for _,name in ipairs(names) do - local ct = container:new(name) - if ct:running() then - -- note, this is a "mixed" table, ie both dictionary and list - table.insert(containers, name) - if (names_only) then - containers[name] = true - ct = nil - else - containers[name] = ct - end - end - end - - table.sort(containers, function (a,b) return (a < b) end) - return containers -end - -function M.version_get() - return core.version_get() -end - -function M.default_config_path_get() - return core.default_config_path_get() -end - -function M.cmd_get_config_item(name, item, lxcpath) - if (lxcpath) then - return core.cmd_get_config_item(name, item, lxcpath) - else - return core.cmd_get_config_item(name, item) - end -end - -lxc_path = core.default_config_path_get() - -return M diff --git a/src/lua-lxc/test/apitest.lua b/src/lua-lxc/test/apitest.lua deleted file mode 100755 index 99cded75b..000000000 --- a/src/lua-lxc/test/apitest.lua +++ /dev/null @@ -1,353 +0,0 @@ -#!/usr/bin/env lua --- --- test the lxc lua api --- --- Copyright © 2012 Oracle. --- --- Authors: --- Dwight Engen --- --- This library is free software; you can redistribute it and/or modify --- it under the terms of the GNU General Public License version 2, as --- published by the Free Software Foundation. --- --- This program 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 General Public License for more details. --- --- You should have received a copy of the GNU General Public License along --- with this program; if not, write to the Free Software Foundation, Inc., --- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. --- - -local lxc = require("lxc") -local lfs = require("lfs") -local getopt = require("alt_getopt") - -local LXC_PATH = lxc.default_config_path_get() - -local container -local cfg_containers = {} -local optarg = {} -local optind = {} - -function printf(...) - local function wrapper(...) io.write(string.format(...)) end - local status, result = pcall(wrapper, ...) - if not status then - error(result, 2) - end -end - -function log(level, ...) - if (optarg["v"] >= level) then - printf(os.date("%Y-%m-%d %T ")) - printf(...) - printf("\n") - end -end - -function die(...) - printf(...) - os.exit(1) -end - -function test_global_info() - local cfg_containers - local run_containers - - log(0, "%-20s %s", "LXC version:", lxc.version_get()) - log(0, "%-20s %s", "Container name:", optarg["n"]) - if (optarg["c"]) then - log(0, "%-20s %s", "Creating container:", "yes") - log(0, "%-20s %s", "With template:", optarg["t"]) - end - log(0, "%-20s %s", "Containers path:", LXC_PATH) - - cfg_containers = lxc.containers_configured() - log(0, "%-20s", "Containers configured:") - for _,v in ipairs(cfg_containers) do - log(0, " %s", v) - end - - run_containers = lxc.containers_running(true) - log(0, "%-20s", "Containers running:") - for _,v in ipairs(run_containers) do - log(0, " %s", v) - end -end - -function test_container_new() - container = lxc.container:new(optarg["n"]) - assert(container ~= nil) - assert(container:config_file_name() == string.format("%s/%s/config", LXC_PATH, optarg["n"])) -end - -function test_container_config_path() - local cfgcontainer - local cfgpath = "/tmp/" .. optarg["n"] - local cfgname = cfgpath .. "/config" - - log(0, "Test container config path...") - - -- create a config file in the new location from container's config - assert(lfs.mkdir(cfgpath)) - assert(container:save_config(cfgname)) - cfgcontainer = lxc.container:new(optarg["n"], "/tmp") - assert(cfgcontainer ~= nil) - log(0, "cfgname:%s cfgpath:%s", cfgcontainer:config_file_name(), cfgcontainer:get_config_path()) - assert(cfgcontainer:config_file_name() == cfgname) - assert(cfgcontainer:get_config_path() == "/tmp") - assert(cfgcontainer:set_config_path(LXC_PATH)) - assert(cfgcontainer:get_config_path() == LXC_PATH) - - assert(os.remove(cfgname)) - assert(lfs.rmdir(cfgpath)) -end - -function test_container_create() - if (optarg["c"]) then - log(0, "%-20s %s", "Destroy existing container:", optarg["n"]) - container:destroy() - assert(container:defined() == false) - else - local cfg_containers = lxc.containers_configured() - if (cfg_containers[optarg["n"]]) then - log(0, "%-20s %s", "Use existing container:", optarg["n"]) - return - end - end - log(0, "%-20s %s", "Creating rootfs using:", optarg["t"]) - assert(container:create(optarg["t"]) == true) - assert(container:defined() == true) - assert(container:name() == optarg["n"]) -end - -function test_container_started() - local now_running - log(2, "state:%s pid:%d\n", container:state(), container:init_pid()) - assert(container:init_pid() > 1) - assert(container:running() == true) - assert(container:state() == "RUNNING") - now_running = lxc.containers_running(true) - assert(now_running[optarg["n"]] ~= nil) - log(1, "%-20s %s", "Running, init pid:", container:init_pid()) -end - -function test_container_stopped() - local now_running - assert(container:init_pid() == -1) - assert(container:running() == false) - assert(container:state() == "STOPPED") - now_running = lxc.containers_running(true) - assert(now_running[optarg["n"]] == nil) -end - -function test_container_frozen() - local now_running - assert(container:init_pid() > 1) - assert(container:running() == true) - assert(container:state() == "FROZEN") - now_running = lxc.containers_running(true) - assert(now_running[optarg["n"]] ~= nil) -end - -function test_container_start() - log(0, "Starting...") - if (not container:start()) then - log(1, "Start returned failure, waiting another 10 seconds...") - container:wait("RUNNING", 10) - end - container:wait("RUNNING", 1) -end - -function test_container_stop() - log(0, "Stopping...") - if (not container:stop()) then - log(1, "Stop returned failure, waiting another 10 seconds...") - container:wait("STOPPED", 10) - end - container:wait("STOPPED", 1) -end - -function test_container_freeze() - log(0, "Freezing...") - if (not container:freeze()) then - log(1, "Freeze returned failure, waiting another 10 seconds...") - container:wait("FROZEN", 10) - end -end - -function test_container_unfreeze() - log(0, "Unfreezing...") - if (not container:unfreeze()) then - log(1, "Unfreeze returned failure, waiting another 10 seconds...") - container:wait("RUNNING", 10) - end -end - -function test_container_shutdown() - log(0, "Shutting down...") - container:shutdown(5) - - if (container:running()) then - test_container_stop() - end -end - -function test_container_in_cfglist(should_find) - local cfg_containers = lxc.containers_configured() - - if (should_find) then - assert(cfg_containers[container:name()] ~= nil) - else - assert(cfg_containers[container:name()] == nil) - end -end - -function test_container_attach() - log(0, "Test attach...") - assert(container:running() == true) - assert(container:attach("/bin/ps") == true) -end - -function test_container_cgroup() - log(0, "Test get/set cgroup items...") - - max_mem = container:get_cgroup_item("memory.max_usage_in_bytes") - saved_limit = container:get_cgroup_item("memory.limit_in_bytes") - assert(saved_limit ~= max_mem) - assert(container:set_cgroup_item("memory.limit_in_bytes", max_mem)) - assert(container:get_cgroup_item("memory.limit_in_bytes") ~= saved_limit) - assert(container:set_cgroup_item("memory.limit_in_bytes", "-1")) -end - -function test_container_cmd() - log(0, "Test get config from running container...") - veth_pair = lxc.cmd_get_config_item(optarg["n"], "lxc.net.0.veth.pair") - log(0, " veth.pair:%s", veth_pair) -end - -function test_config_items() - log(0, "Test set/clear configuration items...") - - -- test setting a 'single type' item - assert(container:get_config_item("lxc.uts.name") == optarg["n"]) - container:set_config_item("lxc.uts.name", "foobar") - assert(container:get_config_item("lxc.uts.name") == "foobar") - container:set_config_item("lxc.uts.name", optarg["n"]) - assert(container:get_config_item("lxc.uts.name") == optarg["n"]) - - -- test clearing/setting a 'list type' item - container:clear_config_item("lxc.cap.drop") - container:set_config_item("lxc.cap.drop", "new_cap1") - container:set_config_item("lxc.cap.drop", "new_cap2") - local cap_drop = container:get_config_item("lxc.cap.drop") - assert(cap_drop["new_cap1"] ~= nil) - assert(cap_drop["new_cap2"] ~= nil) - -- note: clear_config_item only works on list type items - container:clear_config_item("lxc.cap.drop") - assert(container:get_config_item("lxc.cap.drop") == nil) - - local altname = "/tmp/" .. optarg["n"] .. ".altconfig" - log(0, "Test saving to an alternate (%s) config file...", altname) - assert(container:save_config(altname)) - assert(os.remove(altname)) -end - -function test_config_mount_entries() - local mntents - - -- mount entries are a list type item - mntents = container:get_config_item("lxc.mount.entry") - log(0, "Mount entries:") - for _,v in ipairs(mntents) do - log(0, " %s", v) - end -end - -function test_config_keys() - local keys - - keys = container:get_keys() - log(0, "Top level keys:") - for k,v in pairs(keys) do - log(0, " %s = %s", k, v or "") - end -end - -function test_config_network(net_nr) - log(0, "Test network %d config...", net_nr) - local netcfg - - netcfg = container:get_keys("lxc.net." .. net_nr) - if (netcfg == nil) then - return - end - for k,v in pairs(netcfg) do - log(0, " %s = %s", k, v or "") - end - assert(netcfg["flags"] == "up") - assert(container:get_config_item("lxc.net."..net_nr..".type") == "veth") -end - - -function usage() - die("Usage: apitest \n" .. - " -v|--verbose increase verbosity with each -v\n" .. - " -h|--help print help message\n" .. - " -n|--name name of container to use for testing\n" .. - " -c|--create create the test container anew\n" .. - " -l|--login do interactive login test\n" .. - " -t|--template template to use when creating test container\n" - ) -end - -local long_opts = { - verbose = "v", - help = "h", - name = "n", - create = "c", - template = "t", -} - -optarg,optind = alt_getopt.get_opts (arg, "hvn:ct:", long_opts) -optarg["v"] = tonumber(optarg["v"]) or 0 -optarg["n"] = optarg["n"] or "lua-apitest" -optarg["c"] = optarg["c"] or nil -optarg["t"] = optarg["t"] or "busybox" -if (optarg["h"] ~= nil) then - usage() -end - -test_global_info() -test_container_new() -test_container_create() -test_container_stopped() -test_container_in_cfglist(true) -test_container_config_path() - -test_config_items() -test_config_keys() -test_config_mount_entries() -test_config_network(0) - -test_container_start() -test_container_started() - -test_container_attach() -test_container_cgroup() -test_container_cmd() - -test_container_freeze() -test_container_frozen() -test_container_unfreeze() -test_container_started() - -test_container_shutdown() -test_container_stopped() -container:destroy() -test_container_in_cfglist(false) - -log(0, "All tests passed") From e144a06bd792f99c96395a9d4c16cf7c656fb99d Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Wed, 14 Feb 2018 11:53:18 +0100 Subject: [PATCH 04/12] tree-wide: remove python3 bindings Signed-off-by: Christian Brauner --- .gitignore | 4 - Makefile.am | 4 - configure.ac | 27 - doc/ko/Makefile.am | 7 - lxc.spec.in | 15 - src/Makefile.am | 2 +- src/python-lxc/Makefile.am | 35 - src/python-lxc/examples/api_test.py | 207 --- src/python-lxc/examples/pyconsole-vte.py | 79 - src/python-lxc/examples/pyconsole.py | 53 - src/python-lxc/lxc.c | 2031 ---------------------- src/python-lxc/lxc/__init__.py | 510 ------ src/python-lxc/setup.py | 89 - 13 files changed, 1 insertion(+), 3062 deletions(-) delete mode 100644 src/python-lxc/Makefile.am delete mode 100755 src/python-lxc/examples/api_test.py delete mode 100755 src/python-lxc/examples/pyconsole-vte.py delete mode 100755 src/python-lxc/examples/pyconsole.py delete mode 100644 src/python-lxc/lxc.c delete mode 100644 src/python-lxc/lxc/__init__.py delete mode 100644 src/python-lxc/setup.py diff --git a/.gitignore b/.gitignore index d48daf2cc..0d266c200 100644 --- a/.gitignore +++ b/.gitignore @@ -67,10 +67,6 @@ src/lxc/version.h src/lxc/cmd/lxc-checkconfig src/lxc/cmd/lxc-update-config -src/python-lxc/build/ -src/python-lxc/lxc/__pycache__/ -src/python-lxc/lxc.egg-info/ - src/tests/lxc-test-device-add-remove src/tests/lxc-test-attach src/tests/lxc-test-apparmor diff --git a/Makefile.am b/Makefile.am index 14712bc43..dd892c820 100644 --- a/Makefile.am +++ b/Makefile.am @@ -13,10 +13,6 @@ EXTRA_DIST = \ RPMARGS = -if ENABLE_PYTHON -RPMARGS += --with python -endif - pcdatadir = $(libdir)/pkgconfig pcdata_DATA = lxc.pc diff --git a/configure.ac b/configure.ac index 8c1f806aa..1cf1a4ba9 100644 --- a/configure.ac +++ b/configure.ac @@ -363,29 +363,6 @@ AC_ARG_ENABLE([examples], [], [enable_examples=yes]) AM_CONDITIONAL([ENABLE_EXAMPLES], [test "x$enable_examples" = "xyes"]) -# Python3 module and scripts -AC_ARG_ENABLE([python], - [AC_HELP_STRING([--enable-python], [enable python binding [default=auto]])], - [], [enable_python=auto]) - -if test "x$enable_python" = "xauto"; then - PKG_CHECK_MODULES([PYTHONDEV], [python3 >= 3.2],[enable_python=yes],[enable_python=no]) - if test "$CC" = "clang"; then - enable_python=no - fi -fi - -if test "x$enable_python" = "xyes" && test "$CC" = "clang"; then - AC_MSG_ERROR([Python3 is incompatible with the clang compiler]) -fi - -AM_CONDITIONAL([ENABLE_PYTHON], [test "x$enable_python" = "xyes"]) - -AM_COND_IF([ENABLE_PYTHON], - [AM_PATH_PYTHON([3.2], [], [AC_MSG_ERROR([You must install python3])]) - PKG_CHECK_MODULES([PYTHONDEV], [python3 >= 3.2],[],[AC_MSG_ERROR([You must install python3-dev])]) - AC_DEFINE_UNQUOTED([ENABLE_PYTHON], 1, [Python3 is available])]) - # Enable dumping stack traces AC_ARG_ENABLE([mutex-debugging], [AC_HELP_STRING([--enable-mutex-debugging], [Makes mutexes to report error and provide stack trace [default=no]])], @@ -894,7 +871,6 @@ AC_CONFIG_FILES([ src/lxc/cmd/lxc-checkconfig src/lxc/cmd/lxc-update-config src/lxc/version.h - src/python-lxc/Makefile src/tests/Makefile src/tests/lxc-test-usernic @@ -957,9 +933,6 @@ PAM: - PAM module: $enable_pam - cgroup PAM module: $pamdir -Bindings: - - python3: $enable_python - Documentation: - examples: $enable_examples - API documentation: $enable_api_docs diff --git a/doc/ko/Makefile.am b/doc/ko/Makefile.am index b4ae2c57b..2b196830a 100644 --- a/doc/ko/Makefile.am +++ b/doc/ko/Makefile.am @@ -41,13 +41,6 @@ man_MANS = \ \ lxc.7 -if ENABLE_DEPRECATED - man_MANS += lxc-clone.1 -if ENABLE_PYTHON - man_MANS += lxc-start-ephemeral.1 -endif -endif - %.1 : %.sgml $(db2xman) --encoding=UTF-8 $< test "$(shell basename $@)" != "$@" && mv $(shell basename $@) $@ || true diff --git a/lxc.spec.in b/lxc.spec.in index f750b1e18..004ced268 100644 --- a/lxc.spec.in +++ b/lxc.spec.in @@ -20,8 +20,6 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -%global with_python %{?_with_python: 1} %{?!_with_python: 0} - # Set with_systemd on distros that use it, so we can install the service # file, otherwise the sysvinit script will be installed %if 0%{?fedora} >= 14 || 0%{?rhel} >= 7 || 0%{?suse_version} >= 1210 @@ -93,12 +91,6 @@ BuildRequires: libseccomp-devel %endif %endif -%if %{with_python} -Requires: python3 -BuildRequires: python3-devel -BuildRequires: python3-setuptools -%endif - %description Containers are insulated areas inside a system, which have their own namespace for filesystem, network, PID, IPC, CPU and memory allocation and which can be @@ -127,9 +119,6 @@ development of the Linux containers. %setup -q -n %{name}-%{version}%{?beta_dot} %build PATH=$PATH:/usr/sbin:/sbin %configure $args \ -%if %{with_python} - --enable-python \ -%endif %if "x%{_unitdir}" != "x" --with-systemdsystemunitdir=%{_unitdir} \ %endif @@ -266,10 +255,6 @@ fi %attr(555,root,root) %{_libexecdir}/%{name}/lxc-containers %endif -%if %{with_python} -%{python3_sitearch}/* -%endif - %files devel %defattr(-,root,root) %{_includedir}/%{name}/* diff --git a/src/Makefile.am b/src/Makefile.am index 4e4d66b5e..ca3b09203 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1 +1 @@ -SUBDIRS = lxc tests python-lxc +SUBDIRS = lxc tests diff --git a/src/python-lxc/Makefile.am b/src/python-lxc/Makefile.am deleted file mode 100644 index 38b1d62f7..000000000 --- a/src/python-lxc/Makefile.am +++ /dev/null @@ -1,35 +0,0 @@ -if ENABLE_PYTHON - -if HAVE_DEBIAN - DISTSETUPOPTS=--install-layout=deb -else - DISTSETUPOPTS= -endif - -if ENABLE_RPATH - RPATHOPTS=-R $(libdir) -else - RPATHOPTS= -endif - -CALL_SETUP_PY := cd @srcdir@ && $(PYTHON) setup.py build -b @abs_builddir@/build egg_info -e @abs_builddir@ - -all: - $(CALL_SETUP_PY) build_ext -I @abs_top_srcdir@/src -L @abs_top_builddir@/src/lxc/.libs/ $(RPATHOPTS) --no-pkg-config - -DESTDIR = / # default - -install: - $(CALL_SETUP_PY) install --prefix=$(prefix) --no-compile $(DISTSETUPOPTS) --root=$(DESTDIR) - -clean-local: - rm -rf @builddir@/build - -endif -EXTRA_DIST = \ - setup.py \ - lxc.c \ - lxc/__init__.py \ - examples/api_test.py \ - examples/pyconsole.py \ - examples/pyconsole-vte.py diff --git a/src/python-lxc/examples/api_test.py b/src/python-lxc/examples/api_test.py deleted file mode 100755 index 1934a238c..000000000 --- a/src/python-lxc/examples/api_test.py +++ /dev/null @@ -1,207 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# api_test.py: Test/demo of the python3-lxc API -# -# (C) Copyright Canonical Ltd. 2012 -# -# Authors: -# Stéphane Graber -# -# 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 -# - -import lxc -import uuid -import os -import subprocess -import sys -import time - -# Let's pick a random name, avoiding clashes -CONTAINER_NAME = str(uuid.uuid1()) -CLONE_NAME = str(uuid.uuid1()) -RENAME_NAME = str(uuid.uuid1()) - -## Instantiate the container instance -print("Getting instance for '%s'" % CONTAINER_NAME) -container = lxc.Container(CONTAINER_NAME) - -# A few basic checks of the current state -assert(container.config_file_name == "%s/%s/config" % - (lxc.default_config_path, CONTAINER_NAME)) -assert(not container.defined) -assert(container.init_pid == -1) -assert(container.name == CONTAINER_NAME) -assert(not container.running) -assert(container.state == "STOPPED") - -# Try to get the host architecture for dpkg systems -arch = "i386" -try: - with open(os.path.devnull, "w") as devnull: - dpkg = subprocess.Popen(['dpkg', '--print-architecture'], - stderr=devnull, stdout=subprocess.PIPE, - universal_newlines=True) - - if dpkg.wait() == 0: - arch = dpkg.stdout.read().strip() -except: - pass - -## Create a rootfs -print("Creating rootfs using 'download', arch=%s" % arch) -container.create("download", 0, - {"dist": "ubuntu", - "release": "xenial", - "arch": arch}) - -assert(container.defined) -assert(container.name == CONTAINER_NAME - == container.get_config_item("lxc.uts.name")) -assert(container.name in lxc.list_containers()) - -## Test the config -print("Testing the configuration") -capdrop = container.get_config_item("lxc.cap.drop") -container.clear_config_item("lxc.cap.drop") -container.set_config_item("lxc.cap.drop", capdrop[:-1]) -container.append_config_item("lxc.cap.drop", capdrop[-1]) -container.save_config() - -# A few basic checks of the current state -assert(isinstance(capdrop, list)) -assert(capdrop == container.get_config_item("lxc.cap.drop")) - -## Test the networking -print("Testing the networking") - -# A few basic checks of the current state -assert("name" in container.get_keys("lxc.net.0")) -assert(len(container.network) == 1) - -## Starting the container -print("Starting the container") -container.start() -container.wait("RUNNING", 3) - -# A few basic checks of the current state -assert(container.init_pid > 1) -assert(container.running) -assert(container.state == "RUNNING") - - -## Checking IP address -print("Getting the interface names") -assert(set(container.get_interfaces()) == set(('lo', 'eth0'))) - -## Checking IP address -print("Getting the IP addresses") - -count = 0 -ips = [] -while not ips or count == 10: - ips = container.get_ips() - time.sleep(1) - count += 1 - -if os.geteuid(): - container.attach_wait(lxc.attach_run_command, ["ifconfig", "eth0"], - namespaces=(lxc.CLONE_NEWUSER + lxc.CLONE_NEWNET - + lxc.CLONE_NEWUTS)) -else: - container.attach_wait(lxc.attach_run_command, ["ifconfig", "eth0"], - namespaces=(lxc.CLONE_NEWNET + lxc.CLONE_NEWUTS)) - -# A few basic checks of the current state -assert(len(ips) > 0) - -## Test running config -assert(container.name == CONTAINER_NAME - == container.get_config_item("lxc.uts.name") - == container.get_running_config_item("lxc.uts.name")) - -## Testing cgroups a bit -print("Testing cgroup API") -max_mem = container.get_cgroup_item("memory.max_usage_in_bytes") -current_limit = container.get_cgroup_item("memory.limit_in_bytes") -assert(container.set_cgroup_item("memory.limit_in_bytes", max_mem)) -assert(container.get_cgroup_item("memory.limit_in_bytes") != current_limit) - -## Freezing the container -print("Freezing the container") -container.freeze() -container.wait("FROZEN", 3) - -# A few basic checks of the current state -assert(container.init_pid > 1) -assert(container.running) -assert(container.state == "FROZEN") - -## Unfreezing the container -print("Unfreezing the container") -container.unfreeze() -container.wait("RUNNING", 3) - -# A few basic checks of the current state -assert(container.init_pid > 1) -assert(container.running) -assert(container.state == "RUNNING") - -if len(sys.argv) > 1 and sys.argv[1] == "--with-console": - ## Attaching to tty1 - print("Attaching to tty1") - container.console(tty=1) - -## Shutting down the container -print("Shutting down the container") -if not container.shutdown(3): - container.stop() - -if container.running: - print("Stopping the container") - container.stop() - container.wait("STOPPED", 3) - -# A few basic checks of the current state -assert(container.init_pid == -1) -assert(not container.running) -assert(container.state == "STOPPED") - -## Snapshotting the container -print("Snapshotting the container") -assert(not container.snapshot_list()) -assert(container.snapshot() == "snap0") -assert(len(container.snapshot_list()) == 1) -assert(container.snapshot_restore("snap0") is True) -assert(container.snapshot_destroy("snap0") is True) - -## Cloning the container -print("Cloning the container as '%s'" % CLONE_NAME) -clone = container.clone(CLONE_NAME) -assert(clone is not False) - -print ("Renaming the clone to '%s'" % RENAME_NAME) -rename = clone.rename(RENAME_NAME) -rename.start() -rename.stop() -rename.destroy() - -## Destroy the container -print("Destroying the container") -container.destroy() - -assert(not container.defined) diff --git a/src/python-lxc/examples/pyconsole-vte.py b/src/python-lxc/examples/pyconsole-vte.py deleted file mode 100755 index 8a98359af..000000000 --- a/src/python-lxc/examples/pyconsole-vte.py +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# pyconsole-vte: Example program showing use of console functions -# in the lxc python binding -# -# (C) Copyright Oracle. 2013 -# -# Authors: -# Dwight Engen -# -# 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 -# - -import gtk -import vte -import lxc -import sys - - -def gtk_exit_cb(terminal): - gtk.main_quit() - - -def vte_con(ct, ttynum): - print("Doing console in a VTE widget...") - masterfd = ct.console_getfd(ttynum) - term = vte.Terminal() - term.set_cursor_blinks(True) - term.set_scrollback_lines(1000) - term.connect('eof', gtk_exit_cb) - - term.set_pty(masterfd) - term.feed_child('\n') - #term.feed_child('ps aux\n') - - vscrollbar = gtk.VScrollbar() - vscrollbar.set_adjustment(term.get_adjustment()) - - hbox = gtk.HBox() - hbox.pack_start(term) - hbox.pack_start(vscrollbar) - - window = gtk.Window() - window.add(hbox) - window.connect('delete-event', lambda window, event: gtk.main_quit()) - window.show_all() - gtk.main() - print("Console done") - -if __name__ == '__main__': - ttynum = -1 - if len(sys.argv) < 2: - sys.exit("Usage: %s container-name [ttynum]" % sys.argv[0]) - if len(sys.argv) > 2: - ttynum = int(sys.argv[2]) - - ct = lxc.Container(sys.argv[1]) - - print("Container:%s tty:%d" % (ct.name, ttynum)) - if not ct.defined: - sys.exit("Container %s not defined" % ct.name) - if not ct.running: - sys.exit("Container %s not running" % ct.name) - - vte_con(ct, ttynum) diff --git a/src/python-lxc/examples/pyconsole.py b/src/python-lxc/examples/pyconsole.py deleted file mode 100755 index 2b0cd14ab..000000000 --- a/src/python-lxc/examples/pyconsole.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# pyconsole: Example program showing use of console functions -# in the lxc python binding -# -# (C) Copyright Oracle. 2013 -# -# Authors: -# Dwight Engen -# -# 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 -# - -import lxc -import sys -import time - -if __name__ == '__main__': - ttynum = -1 - escape = 1 - if len(sys.argv) < 2: - sys.exit("Usage: %s container-name [ttynum [escape]]" % sys.argv[0]) - if len(sys.argv) > 2: - ttynum = int(sys.argv[2]) - if len(sys.argv) > 3: - escape = ord(sys.argv[3]) - ord('a') + 1 - - ct = lxc.Container(sys.argv[1]) - - print("Container:%s tty:%d Ctrl-%c q to quit" % - (ct.name, ttynum, ord('a') + escape-1)) - time.sleep(1) - if not ct.defined: - sys.exit("Container %s not defined" % ct.name) - if not ct.running: - sys.exit("Container %s not running" % ct.name) - - ct.console(ttynum, 0, 1, 2, escape) - print("Console done") diff --git a/src/python-lxc/lxc.c b/src/python-lxc/lxc.c deleted file mode 100644 index 70176cdc6..000000000 --- a/src/python-lxc/lxc.c +++ /dev/null @@ -1,2031 +0,0 @@ -/* - * python-lxc: Python bindings for LXC - * - * (C) Copyright Canonical Ltd. 2012-2013 - * - * Authors: - * Stéphane Graber - * - * 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 - */ - -#include -#include "structmember.h" -#include -#include -#include -#include - -/* - * CLONE_* definitions copied from lxc/namespace.h - */ -#ifndef CLONE_FS -# define CLONE_FS 0x00000200 -#endif -#ifndef CLONE_NEWNS -# define CLONE_NEWNS 0x00020000 -#endif -#ifndef CLONE_NEWCGROUP -# define CLONE_NEWCGROUP 0x02000000 -#endif -#ifndef CLONE_NEWUTS -# define CLONE_NEWUTS 0x04000000 -#endif -#ifndef CLONE_NEWIPC -# define CLONE_NEWIPC 0x08000000 -#endif -#ifndef CLONE_NEWUSER -# define CLONE_NEWUSER 0x10000000 -#endif -#ifndef CLONE_NEWPID -# define CLONE_NEWPID 0x20000000 -#endif -#ifndef CLONE_NEWNET -# define CLONE_NEWNET 0x40000000 -#endif - -/* From sys/personality.h */ -#define PER_LINUX 0x0000 -#define PER_LINUX32 0x0008 - -/* Helper functions */ - -/* Copied from lxc/utils.c */ -static int lxc_wait_for_pid_status(pid_t pid) -{ - int status, ret; - -again: - ret = waitpid(pid, &status, 0); - if (ret == -1) { - if (errno == EINTR) - goto again; - return -1; - } - if (ret != pid) - goto again; - return status; -} - -/* Copied from lxc/confile.c, with HAVE_SYS_PERSONALITY_H check removed */ -signed long lxc_config_parse_arch(const char *arch) -{ - struct per_name { - char *name; - unsigned long per; - } pername[] = { - { "x86", PER_LINUX32 }, - { "linux32", PER_LINUX32 }, - { "i386", PER_LINUX32 }, - { "i486", PER_LINUX32 }, - { "i586", PER_LINUX32 }, - { "i686", PER_LINUX32 }, - { "athlon", PER_LINUX32 }, - { "linux64", PER_LINUX }, - { "x86_64", PER_LINUX }, - { "amd64", PER_LINUX }, - }; - size_t len = sizeof(pername) / sizeof(pername[0]); - - size_t i; - - for (i = 0; i < len; i++) { - if (!strcmp(pername[i].name, arch)) - return pername[i].per; - } - - return -1; -} - -char** -convert_tuple_to_char_pointer_array(PyObject *argv) { - int argc; - int i, j; - char **result; - - /* not a list or tuple */ - if (!PyList_Check(argv) && !PyTuple_Check(argv)) { - PyErr_SetString(PyExc_TypeError, "Expected list or tuple."); - return NULL; - } - - argc = PySequence_Fast_GET_SIZE(argv); - - result = (char**) calloc(argc + 1, sizeof(char*)); - - if (result == NULL) { - PyErr_SetNone(PyExc_MemoryError); - return NULL; - } - - for (i = 0; i < argc; i++) { - char *str = NULL; - PyObject *pystr = NULL; - PyObject *pyobj = PySequence_Fast_GET_ITEM(argv, i); - assert(pyobj != NULL); - - if (!PyUnicode_Check(pyobj)) { - PyErr_SetString(PyExc_ValueError, "Expected a string"); - goto error; - } - - pystr = PyUnicode_AsUTF8String(pyobj); - if (!pystr) { - /* Maybe it wasn't UTF-8 encoded. An exception is already set. */ - goto error; - } - - str = PyBytes_AsString(pystr); - if (!str) { - /* Maybe pystr wasn't a valid object. An exception is already set. - */ - Py_DECREF(pystr); - goto error; - } - - /* We must make a copy of str, because it points into internal memory - * which we do not own. Assume it's NULL terminated, otherwise we'd - * have to use PyUnicode_AsUTF8AndSize() and be explicit about copying - * the memory. - */ - result[i] = strdup(str); - - /* Do not decref pyobj since we stole a reference by using - * PyTuple_GET_ITEM(). - */ - Py_DECREF(pystr); - if (result[i] == NULL) { - PyErr_SetNone(PyExc_MemoryError); - goto error; - } - } - - result[argc] = NULL; - return result; - -error: - /* We can only iterate up to but not including i because malloc() does not - * initialize its memory. Thus if we got here, i points to the index - * after the last strdup'd entry in result. - */ - for (j = 0; j < i; j++) - free(result[j]); - free(result); - return NULL; -} - -struct lxc_attach_python_payload { - PyObject *fn; - PyObject *arg; -}; - -static int lxc_attach_python_exec(void* _payload) -{ - /* This function is the first one to be called after attaching to a - * container. As lxc_attach() calls fork() PyOS_AfterFork should be called - * in the new process if the Python interpreter will continue to be used. - */ - PyOS_AfterFork(); - - struct lxc_attach_python_payload *payload = - (struct lxc_attach_python_payload *)_payload; - PyObject *result = PyObject_CallFunctionObjArgs(payload->fn, - payload->arg, NULL); - - if (!result) { - PyErr_Print(); - return -1; - } - if (PyLong_Check(result)) - return (int)PyLong_AsLong(result); - else - return -1; -} - -static void lxc_attach_free_options(lxc_attach_options_t *options); - -static lxc_attach_options_t *lxc_attach_parse_options(PyObject *kwds) -{ - static char *kwlist[] = {"attach_flags", "namespaces", "personality", - "initial_cwd", "uid", "gid", "env_policy", - "extra_env_vars", "extra_keep_env", "stdin", - "stdout", "stderr", NULL}; - long temp_uid, temp_gid; - int temp_env_policy; - PyObject *extra_env_vars_obj = NULL; - PyObject *extra_keep_env_obj = NULL; - PyObject *stdin_obj = NULL; - PyObject *stdout_obj = NULL; - PyObject *stderr_obj = NULL; - PyObject *initial_cwd_obj = NULL; - PyObject *dummy = NULL; - bool parse_result; - - lxc_attach_options_t default_options = LXC_ATTACH_OPTIONS_DEFAULT; - lxc_attach_options_t *options = malloc(sizeof(*options)); - - if (!options) { - PyErr_SetNone(PyExc_MemoryError); - return NULL; - } - memcpy(options, &default_options, sizeof(*options)); - - /* we need some dummy variables because we can't be sure - * the data types match completely */ - temp_uid = -1; - temp_gid = -1; - temp_env_policy = options->env_policy; - - /* we need a dummy tuple */ - dummy = PyTuple_New(0); - - parse_result = PyArg_ParseTupleAndKeywords(dummy, kwds, "|iilO&lliOOOOO", - kwlist, &options->attach_flags, - &options->namespaces, - &options->personality, - PyUnicode_FSConverter, - &initial_cwd_obj, &temp_uid, - &temp_gid, &temp_env_policy, - &extra_env_vars_obj, - &extra_keep_env_obj, - &stdin_obj, &stdout_obj, - &stderr_obj); - - /* immediately get rid of the dummy tuple */ - Py_DECREF(dummy); - - if (!parse_result) { - lxc_attach_free_options(options); - return NULL; - } - - /* duplicate the string, so we don't depend on some random Python object */ - if (initial_cwd_obj != NULL) { - options->initial_cwd = strndup(PyBytes_AsString(initial_cwd_obj), - PyBytes_Size(initial_cwd_obj)); - Py_DECREF(initial_cwd_obj); - } - - /* do the type conversion from the types that match the parse string */ - if (temp_uid != -1) options->uid = (uid_t)temp_uid; - if (temp_gid != -1) options->gid = (gid_t)temp_gid; - options->env_policy = (lxc_attach_env_policy_t)temp_env_policy; - - if (extra_env_vars_obj) - options->extra_env_vars = - convert_tuple_to_char_pointer_array(extra_env_vars_obj); - if (extra_keep_env_obj) - options->extra_keep_env = - convert_tuple_to_char_pointer_array(extra_keep_env_obj); - if (stdin_obj) { - options->stdin_fd = PyObject_AsFileDescriptor(stdin_obj); - if (options->stdin_fd < 0) { - lxc_attach_free_options(options); - return NULL; - } - } - if (stdout_obj) { - options->stdout_fd = PyObject_AsFileDescriptor(stdout_obj); - if (options->stdout_fd < 0) { - lxc_attach_free_options(options); - return NULL; - } - } - if (stderr_obj) { - options->stderr_fd = PyObject_AsFileDescriptor(stderr_obj); - if (options->stderr_fd < 0) { - lxc_attach_free_options(options); - return NULL; - } - } - - return options; -} - -void lxc_attach_free_options(lxc_attach_options_t *options) -{ - int i; - if (!options) - return; - free(options->initial_cwd); - if (options->extra_env_vars) { - for (i = 0; options->extra_env_vars[i]; i++) - free(options->extra_env_vars[i]); - free(options->extra_env_vars); - } - if (options->extra_keep_env) { - for (i = 0; options->extra_keep_env[i]; i++) - free(options->extra_keep_env[i]); - free(options->extra_keep_env); - } - free(options); -} - -/* Module functions */ -static PyObject * -LXC_arch_to_personality(PyObject *self, PyObject *arg) -{ - long rv = -1; - PyObject *pystr = NULL; - char *str; - - if (!PyUnicode_Check(arg)) { - PyErr_SetString(PyExc_ValueError, "Expected a string"); - return NULL; - } - - pystr = PyUnicode_AsUTF8String(arg); - if (!pystr) - return NULL; - - str = PyBytes_AsString(pystr); - if (!str) - goto out; - - rv = lxc_config_parse_arch(str); - if (rv == -1) - PyErr_SetString(PyExc_KeyError, "Failed to lookup architecture."); - -out: - Py_DECREF(pystr); - return rv == -1 ? NULL : PyLong_FromLong(rv); -} - -static PyObject * -LXC_attach_run_command(PyObject *self, PyObject *arg) -{ - PyObject *args_obj = NULL; - int i, rv; - lxc_attach_command_t cmd = { - NULL, /* program */ - NULL /* argv[] */ - }; - - if (!PyArg_ParseTuple(arg, "sO", (const char**)&cmd.program, &args_obj)) - return NULL; - if (args_obj && PyList_Check(args_obj)) { - cmd.argv = convert_tuple_to_char_pointer_array(args_obj); - } else { - PyErr_Format(PyExc_TypeError, "Second part of tuple passed to " - "attach_run_command must be a list."); - return NULL; - } - - if (!cmd.argv) - return NULL; - - rv = lxc_attach_run_command(&cmd); - - for (i = 0; cmd.argv[i]; i++) - free(cmd.argv[i]); - free(cmd.argv); - - return PyLong_FromLong(rv); -} - -static PyObject * -LXC_attach_run_shell(PyObject *self, PyObject *arg) -{ - int rv; - - rv = lxc_attach_run_shell(NULL); - - return PyLong_FromLong(rv); -} - -static PyObject * -LXC_get_global_config_item(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"key", NULL}; - char* key = NULL; - const char* value = NULL; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "s|", kwlist, - &key)) - return NULL; - - value = lxc_get_global_config_item(key); - - if (!value) { - PyErr_SetString(PyExc_KeyError, "Invalid configuration key"); - return NULL; - } - - return PyUnicode_FromString(value); -} - -static PyObject * -LXC_get_version(PyObject *self, PyObject *args) -{ - const char *rv = NULL; - - rv = lxc_get_version(); - if (!rv) { - return PyUnicode_FromString(""); - } - - return PyUnicode_FromString(rv); -} - -static PyObject * -LXC_list_containers(PyObject *self, PyObject *args, PyObject *kwds) -{ - char **names = NULL; - PyObject *list = NULL; - int list_count = 0; - - int list_active = 1; - int list_defined = 1; - - PyObject *py_list_active = NULL; - PyObject *py_list_defined = NULL; - - char* config_path = NULL; - - int i = 0; - PyObject *vargs = NULL; - static char *kwlist[] = {"active", "defined", "config_path", NULL}; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOs", kwlist, - &py_list_active, - &py_list_defined, - &config_path, &vargs)) - return NULL; - - /* We default to listing everything */ - if (py_list_active && py_list_active != Py_True) { - list_active = 0; - } - - if (py_list_defined && py_list_defined != Py_True) { - list_defined = 0; - } - - /* Call the right API function based on filters */ - if (list_active == 1 && list_defined == 1) - list_count = list_all_containers(config_path, &names, NULL); - else if (list_active == 1) - list_count = list_active_containers(config_path, &names, NULL); - else if (list_defined == 1) - list_count = list_defined_containers(config_path, &names, NULL); - - /* Handle failure */ - if (list_count < 0) { - PyErr_SetString(PyExc_ValueError, "failure to list containers"); - return NULL; - } - - /* Generate the tuple */ - list = PyTuple_New(list_count); - for (i = 0; i < list_count; i++) { - if (!names[i]) { - continue; - } - - PyTuple_SET_ITEM(list, i, PyUnicode_FromString(names[i])); - free(names[i]); - } - free(names); - - return list; -} - -/* Base type and functions for Container */ -typedef struct { - PyObject_HEAD - struct lxc_container *container; -} Container; - -static void -Container_dealloc(Container* self) -{ - lxc_container_put(self->container); - Py_TYPE(self)->tp_free((PyObject*)self); -} - -static int -Container_init(Container *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"name", "config_path", NULL}; - char *name = NULL; - PyObject *fs_config_path = NULL; - char *config_path = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|O&", kwlist, - &name, - PyUnicode_FSConverter, &fs_config_path)) - return -1; - - if (fs_config_path != NULL) { - config_path = PyBytes_AS_STRING(fs_config_path); - assert(config_path != NULL); - } - - self->container = lxc_container_new(name, config_path); - if (!self->container) { - Py_XDECREF(fs_config_path); - - PyErr_Format(PyExc_RuntimeError, "%s:%s:%d: error during init for container '%s'.", - __FUNCTION__, __FILE__, __LINE__, name); - return -1; - } - - Py_XDECREF(fs_config_path); - return 0; -} - -static PyObject * -Container_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - Container *self; - - self = (Container *)type->tp_alloc(type, 0); - - return (PyObject *)self; -} - -/* Container properties */ -static PyObject * -Container_config_file_name(Container *self, void *closure) -{ - char *rv = NULL; - - rv = self->container->config_file_name(self->container); - if (!rv) { - return PyUnicode_FromString(""); - } - - return PyUnicode_FromString(rv); -} - -static PyObject * -Container_controllable(Container *self, void *closure) -{ - if (self->container->may_control(self->container)) { - Py_RETURN_TRUE; - } - - Py_RETURN_FALSE; -} - -static PyObject * -Container_defined(Container *self, void *closure) -{ - if (self->container->is_defined(self->container)) { - Py_RETURN_TRUE; - } - - Py_RETURN_FALSE; -} - -static PyObject * -Container_init_pid(Container *self, void *closure) -{ - return PyLong_FromLong(self->container->init_pid(self->container)); -} - -static PyObject * -Container_name(Container *self, void *closure) -{ - if (!self->container->name) { - return PyUnicode_FromString(""); - } - - return PyUnicode_FromString(self->container->name); -} - -static PyObject * -Container_running(Container *self, void *closure) -{ - if (self->container->is_running(self->container)) { - Py_RETURN_TRUE; - } - - Py_RETURN_FALSE; -} - -static PyObject * -Container_state(Container *self, void *closure) -{ - const char *rv = NULL; - - rv = self->container->state(self->container); - - if (!rv) { - return PyUnicode_FromString(""); - } - - return PyUnicode_FromString(rv); -} - -/* Container Functions */ -static PyObject * -Container_attach_interface(Container *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"src_ifname", "dst_ifname", NULL}; - char *src_name = NULL; - char *dst_name = NULL; - PyObject *py_src_name = NULL; - PyObject *py_dst_name = NULL; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "O&|O&", kwlist, - PyUnicode_FSConverter, &py_src_name, - PyUnicode_FSConverter, &py_dst_name)) - return NULL; - - if (py_src_name != NULL) { - src_name = PyBytes_AS_STRING(py_src_name); - assert(src_name != NULL); - } - - if (py_dst_name != NULL) { - dst_name = PyBytes_AS_STRING(py_dst_name); - assert(dst_name != NULL); - } - - if (self->container->attach_interface(self->container, src_name, dst_name)) { - Py_XDECREF(py_src_name); - Py_XDECREF(py_dst_name); - Py_RETURN_TRUE; - } - - Py_XDECREF(py_src_name); - Py_XDECREF(py_dst_name); - Py_RETURN_FALSE; -} - -static PyObject * -Container_detach_interface(Container *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"ifname", NULL}; - char *ifname = NULL; - PyObject *py_ifname = NULL; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "O&", kwlist, - PyUnicode_FSConverter, &py_ifname)) - return NULL; - - if (py_ifname != NULL) { - ifname = PyBytes_AS_STRING(py_ifname); - assert(ifname != NULL); - } - - if (self->container->detach_interface(self->container, ifname, NULL)) { - Py_XDECREF(py_ifname); - Py_RETURN_TRUE; - } - - Py_XDECREF(py_ifname); - Py_RETURN_FALSE; -} - -static PyObject * -Container_add_device_node(Container *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"src_path", "dest_path", NULL}; - char *src_path = NULL; - char *dst_path = NULL; - PyObject *py_src_path = NULL; - PyObject *py_dst_path = NULL; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "O&|O&", kwlist, - PyUnicode_FSConverter, &py_src_path, - PyUnicode_FSConverter, &py_dst_path)) - return NULL; - - if (py_src_path != NULL) { - src_path = PyBytes_AS_STRING(py_src_path); - assert(src_path != NULL); - } - - if (py_dst_path != NULL) { - dst_path = PyBytes_AS_STRING(py_dst_path); - assert(dst_path != NULL); - } - - if (self->container->add_device_node(self->container, src_path, - dst_path)) { - Py_XDECREF(py_src_path); - Py_XDECREF(py_dst_path); - Py_RETURN_TRUE; - } - - Py_XDECREF(py_src_path); - Py_XDECREF(py_dst_path); - Py_RETURN_FALSE; -} - -static PyObject * -Container_attach_and_possibly_wait(Container *self, PyObject *args, - PyObject *kwds, int wait) -{ - struct lxc_attach_python_payload payload = { NULL, NULL }; - lxc_attach_options_t *options = NULL; - long ret; - pid_t pid; - - if (!PyArg_ParseTuple(args, "O|O", &payload.fn, &payload.arg)) - return NULL; - if (!PyCallable_Check(payload.fn)) { - PyErr_Format(PyExc_TypeError, "attach: object not callable"); - return NULL; - } - - options = lxc_attach_parse_options(kwds); - if (!options) - return NULL; - - ret = self->container->attach(self->container, lxc_attach_python_exec, - &payload, options, &pid); - if (ret < 0) - goto out; - - if (wait) { - Py_BEGIN_ALLOW_THREADS - ret = lxc_wait_for_pid_status(pid); - Py_END_ALLOW_THREADS - /* handle case where attach fails */ - if (WIFEXITED(ret) && WEXITSTATUS(ret) == 255) - ret = -1; - } else { - ret = (long)pid; - } - -out: - lxc_attach_free_options(options); - return PyLong_FromLong(ret); -} - -static PyObject * -Container_attach(Container *self, PyObject *args, PyObject *kwds) -{ - return Container_attach_and_possibly_wait(self, args, kwds, 0); -} - -static PyObject * -Container_attach_wait(Container *self, PyObject *args, PyObject *kwds) -{ - return Container_attach_and_possibly_wait(self, args, kwds, 1); -} - -static PyObject * -Container_clear_config(Container *self, PyObject *args, PyObject *kwds) -{ - self->container->clear_config(self->container); - - Py_RETURN_NONE; -} - -static PyObject * -Container_clear_config_item(Container *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"key", NULL}; - char *key = NULL; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &key)) - return NULL; - - if (self->container->clear_config_item(self->container, key)) { - Py_RETURN_TRUE; - } - - Py_RETURN_FALSE; -} - -static PyObject * -Container_clone(Container *self, PyObject *args, PyObject *kwds) -{ - char *newname = NULL; - char *config_path = NULL; - int flags = 0; - char *bdevtype = NULL; - char *bdevdata = NULL; - unsigned long newsize = 0; - char **hookargs = NULL; - - PyObject *py_hookargs = NULL; - PyObject *py_config_path = NULL; - struct lxc_container *new_container = NULL; - int i = 0; - - static char *kwlist[] = {"newname", "config_path", "flags", "bdevtype", - "bdevdata", "newsize", "hookargs", NULL}; - if (! PyArg_ParseTupleAndKeywords(args, kwds, "s|O&isskO", kwlist, - &newname, - PyUnicode_FSConverter, &py_config_path, - &flags, &bdevtype, &bdevdata, &newsize, - &py_hookargs)) - return NULL; - - if (py_hookargs) { - if (PyTuple_Check(py_hookargs)) { - hookargs = convert_tuple_to_char_pointer_array(py_hookargs); - if (!hookargs) { - return NULL; - } - } - else { - PyErr_SetString(PyExc_ValueError, "hookargs needs to be a tuple"); - return NULL; - } - } - - if (py_config_path != NULL) { - config_path = PyBytes_AS_STRING(py_config_path); - assert(config_path != NULL); - } - - new_container = self->container->clone(self->container, newname, - config_path, flags, bdevtype, - bdevdata, newsize, hookargs); - - Py_XDECREF(py_config_path); - - if (hookargs) { - for (i = 0; i < PyTuple_GET_SIZE(py_hookargs); i++) - free(hookargs[i]); - free(hookargs); - } - - if (new_container == NULL) { - Py_RETURN_FALSE; - } - - lxc_container_put(new_container); - - Py_RETURN_TRUE; -} - -static PyObject * -Container_console(Container *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"ttynum", "stdinfd", "stdoutfd", "stderrfd", - "escape", NULL}; - int ttynum = -1, stdinfd = 0, stdoutfd = 1, stderrfd = 2, escape = 1; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "|iiiii", kwlist, - &ttynum, &stdinfd, &stdoutfd, &stderrfd, - &escape)) - return NULL; - - if (self->container->console(self->container, ttynum, - stdinfd, stdoutfd, stderrfd, escape) == 0) { - Py_RETURN_TRUE; - } - Py_RETURN_FALSE; -} - -static PyObject * -Container_console_getfd(Container *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"ttynum", NULL}; - int ttynum = -1, masterfd; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &ttynum)) - return NULL; - - if (self->container->console_getfd(self->container, &ttynum, - &masterfd) < 0) { - PyErr_SetString(PyExc_ValueError, "Unable to allocate tty"); - return NULL; - } - return PyLong_FromLong(masterfd); -} - -static PyObject * -Container_create(Container *self, PyObject *args, PyObject *kwds) -{ - char* template_name = NULL; - int flags = 0; - char** create_args = {NULL}; - PyObject *retval = NULL; - PyObject *vargs = NULL; - char *bdevtype = NULL; - int i = 0; - static char *kwlist[] = {"template", "flags", "bdevtype", "args", NULL}; - if (! PyArg_ParseTupleAndKeywords(args, kwds, "|sisO", kwlist, - &template_name, &flags, &bdevtype, &vargs)) - return NULL; - - if (vargs) { - if (PyTuple_Check(vargs)) { - create_args = convert_tuple_to_char_pointer_array(vargs); - if (!create_args) { - return NULL; - } - } - else { - PyErr_SetString(PyExc_ValueError, "args needs to be a tuple"); - return NULL; - } - } - - if (self->container->create(self->container, template_name, bdevtype, NULL, - flags, create_args)) - retval = Py_True; - else - retval = Py_False; - - if (vargs) { - /* We cannot have gotten here unless vargs was given and create_args - * was successfully allocated. - */ - for (i = 0; i < PyTuple_GET_SIZE(vargs); i++) - free(create_args[i]); - free(create_args); - } - - Py_INCREF(retval); - return retval; -} - -static PyObject * -Container_destroy(Container *self, PyObject *args, PyObject *kwds) -{ - if (self->container->destroy(self->container)) { - Py_RETURN_TRUE; - } - - Py_RETURN_FALSE; -} - -static PyObject * -Container_freeze(Container *self, PyObject *args, PyObject *kwds) -{ - if (self->container->freeze(self->container)) { - Py_RETURN_TRUE; - } - - Py_RETURN_FALSE; -} - -static PyObject * -Container_get_cgroup_item(Container *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"key", NULL}; - char* key = NULL; - int len = 0; - char* value; - PyObject *ret = NULL; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &key)) - return NULL; - - len = self->container->get_cgroup_item(self->container, key, NULL, 0); - - if (len < 0) { - PyErr_SetString(PyExc_KeyError, "Invalid cgroup entry"); - return NULL; - } - - value = (char*) malloc(sizeof(char)*len + 1); - if (value == NULL) - return PyErr_NoMemory(); - - if (self->container->get_cgroup_item(self->container, - key, value, len + 1) != len) { - PyErr_SetString(PyExc_ValueError, "Unable to read config value"); - free(value); - return NULL; - } - - ret = PyUnicode_FromString(value); - free(value); - return ret; -} - -static PyObject * -Container_get_config_item(Container *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"key", NULL}; - char* key = NULL; - int len = 0; - char* value; - PyObject *ret = NULL; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "s|", kwlist, - &key)) - return NULL; - - len = self->container->get_config_item(self->container, key, NULL, 0); - - if (len < 0) { - PyErr_SetString(PyExc_KeyError, "Invalid configuration key"); - return NULL; - } - - if (len == 0) { - return PyUnicode_FromString(""); - } - - value = (char*) malloc(sizeof(char)*len + 1); - if (value == NULL) - return PyErr_NoMemory(); - - if (self->container->get_config_item(self->container, - key, value, len + 1) != len) { - PyErr_SetString(PyExc_ValueError, "Unable to read config value"); - free(value); - return NULL; - } - - ret = PyUnicode_FromString(value); - free(value); - return ret; -} - -static PyObject * -Container_get_config_path(Container *self, PyObject *args, PyObject *kwds) -{ - const char *rv = NULL; - - rv = self->container->get_config_path(self->container); - - if (!rv) { - return PyUnicode_FromString(""); - } - - return PyUnicode_FromString(rv); -} - -static PyObject * -Container_get_keys(Container *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"key", NULL}; - char* key = NULL; - int len = 0; - char* value; - PyObject *ret = NULL; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "|s", kwlist, - &key)) - return NULL; - - len = self->container->get_keys(self->container, key, NULL, 0); - - if (len < 0) { - PyErr_SetString(PyExc_KeyError, "Invalid configuration key"); - return NULL; - } - - value = (char*) malloc(sizeof(char)*len + 1); - if (value == NULL) - return PyErr_NoMemory(); - - if (self->container->get_keys(self->container, - key, value, len + 1) != len) { - PyErr_SetString(PyExc_ValueError, "Unable to read config keys"); - free(value); - return NULL; - } - - ret = PyUnicode_FromString(value); - free(value); - return ret; -} - -static PyObject * -Container_get_interfaces(Container *self) -{ - int i = 0; - char** interfaces = NULL; - - PyObject* ret; - - /* Get the interfaces */ - interfaces = self->container->get_interfaces(self->container); - if (!interfaces) - return PyTuple_New(0); - - /* Count the entries */ - while (interfaces[i]) - i++; - - /* Create the new tuple */ - ret = PyTuple_New(i); - if (!ret) - return NULL; - - /* Add the entries to the tuple and free the memory */ - i = 0; - while (interfaces[i]) { - if (!interfaces[i]) { - i++; - continue; - } - - PyObject *unicode = PyUnicode_FromString(interfaces[i]); - if (!unicode) { - Py_DECREF(ret); - ret = NULL; - break; - } - PyTuple_SET_ITEM(ret, i, unicode); - i++; - } - - /* Free the list of IPs */ - i = 0; - while (interfaces[i]) { - free(interfaces[i]); - i++; - } - free(interfaces); - - return ret; -} - -static PyObject * -Container_get_ips(Container *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"interface", "family", "scope", NULL}; - char* interface = NULL; - char* family = NULL; - int scope = 0; - - int i = 0; - char** ips = NULL; - - PyObject* ret; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "|ssi", kwlist, - &interface, &family, &scope)) - return NULL; - - /* Get the IPs */ - ips = self->container->get_ips(self->container, interface, family, scope); - if (!ips) - return PyTuple_New(0); - - /* Count the entries */ - while (ips[i]) - i++; - - /* Create the new tuple */ - ret = PyTuple_New(i); - if (!ret) - return NULL; - - /* Add the entries to the tuple and free the memory */ - i = 0; - while (ips[i]) { - if (!ips[i]) { - i++; - continue; - } - - PyObject *unicode = PyUnicode_FromString(ips[i]); - if (!unicode) { - Py_DECREF(ret); - ret = NULL; - break; - } - PyTuple_SET_ITEM(ret, i, unicode); - i++; - } - - /* Free the list of IPs */ - i = 0; - while (ips[i]) { - free(ips[i]); - i++; - } - free(ips); - - return ret; -} - -static PyObject * -Container_get_running_config_item(Container *self, PyObject *args, - PyObject *kwds) -{ - static char *kwlist[] = {"key", NULL}; - char* key = NULL; - char* value = NULL; - PyObject *ret = NULL; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "s|", kwlist, - &key)) - return NULL; - - value = self->container->get_running_config_item(self->container, key); - - if (!value) - Py_RETURN_NONE; - - ret = PyUnicode_FromString(value); - free(value); - return ret; -} - - -static PyObject * -Container_load_config(Container *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"path", NULL}; - PyObject *fs_path = NULL; - char* path = NULL; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "|O&", kwlist, - PyUnicode_FSConverter, &fs_path)) - return NULL; - - if (fs_path != NULL) { - path = PyBytes_AS_STRING(fs_path); - assert(path != NULL); - } - - if (self->container->load_config(self->container, path)) { - Py_XDECREF(fs_path); - Py_RETURN_TRUE; - } - - Py_XDECREF(fs_path); - Py_RETURN_FALSE; -} - -static PyObject * -Container_reboot(Container *self, PyObject *args, PyObject *kwds) -{ - if (self->container->reboot(self->container)) { - Py_RETURN_TRUE; - } - - Py_RETURN_FALSE; -} - -static PyObject * -Container_rename(Container *self, PyObject *args, PyObject *kwds) -{ - char *new_name = NULL; - static char *kwlist[] = {"new_name", NULL}; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "s|", kwlist, - &new_name)) - return NULL; - - if (self->container->rename(self->container, new_name)) { - Py_RETURN_TRUE; - } - - Py_RETURN_FALSE; -} - -static PyObject * -Container_remove_device_node(Container *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"src_path", "dest_path", NULL}; - char *src_path = NULL; - char *dst_path = NULL; - PyObject *py_src_path = NULL; - PyObject *py_dst_path = NULL; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "O&|O&", kwlist, - PyUnicode_FSConverter, &py_src_path, - PyUnicode_FSConverter, &py_dst_path)) - return NULL; - - if (py_src_path != NULL) { - src_path = PyBytes_AS_STRING(py_src_path); - assert(src_path != NULL); - } - - if (py_dst_path != NULL) { - dst_path = PyBytes_AS_STRING(py_dst_path); - assert(dst_path != NULL); - } - - if (self->container->remove_device_node(self->container, src_path, - dst_path)) { - Py_XDECREF(py_src_path); - Py_XDECREF(py_dst_path); - Py_RETURN_TRUE; - } - - Py_XDECREF(py_src_path); - Py_XDECREF(py_dst_path); - Py_RETURN_FALSE; -} - -static PyObject * -Container_save_config(Container *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"path", NULL}; - PyObject *fs_path = NULL; - char* path = NULL; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "|O&", kwlist, - PyUnicode_FSConverter, &fs_path)) - return NULL; - - if (fs_path != NULL) { - path = PyBytes_AS_STRING(fs_path); - assert(path != NULL); - } - - if (self->container->save_config(self->container, path)) { - Py_XDECREF(fs_path); - Py_RETURN_TRUE; - } - - Py_XDECREF(fs_path); - Py_RETURN_FALSE; -} - -static PyObject * -Container_set_cgroup_item(Container *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"key", "value", NULL}; - char *key = NULL; - char *value = NULL; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwlist, - &key, &value)) - return NULL; - - if (self->container->set_cgroup_item(self->container, key, value)) { - Py_RETURN_TRUE; - } - - Py_RETURN_FALSE; -} - -static PyObject * -Container_set_config_item(Container *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"key", "value", NULL}; - char *key = NULL; - char *value = NULL; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwlist, - &key, &value)) - return NULL; - - if (self->container->set_config_item(self->container, key, value)) { - Py_RETURN_TRUE; - } - - Py_RETURN_FALSE; -} - -static PyObject * -Container_set_config_path(Container *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"path", NULL}; - char *path = NULL; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, - &path)) - return NULL; - - if (self->container->set_config_path(self->container, path)) { - Py_RETURN_TRUE; - } - - Py_RETURN_FALSE; -} - -static PyObject * -Container_shutdown(Container *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"timeout", NULL}; - int timeout = -1; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, - &timeout)) - return NULL; - - if (self->container->shutdown(self->container, timeout)) { - Py_RETURN_TRUE; - } - - Py_RETURN_FALSE; -} - -static PyObject * -Container_snapshot(Container *self, PyObject *args, PyObject *kwds) -{ - char *comment_path = NULL; - static char *kwlist[] = {"comment_path", NULL}; - int retval = 0; - int ret = 0; - char newname[20]; - PyObject *py_comment_path = NULL; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "|O&", kwlist, - PyUnicode_FSConverter, &py_comment_path)) - return NULL; - - if (py_comment_path != NULL) { - comment_path = PyBytes_AS_STRING(py_comment_path); - assert(comment_path != NULL); - } - - retval = self->container->snapshot(self->container, comment_path); - - Py_XDECREF(py_comment_path); - - if (retval < 0) { - Py_RETURN_FALSE; - } - - ret = snprintf(newname, 20, "snap%d", retval); - if (ret < 0 || ret >= 20) - return NULL; - - - return PyUnicode_FromString(newname); -} - -static PyObject * -Container_snapshot_destroy(Container *self, PyObject *args, PyObject *kwds) -{ - char *name = NULL; - static char *kwlist[] = {"name", NULL}; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "s|", kwlist, - &name)) - return NULL; - - if (self->container->snapshot_destroy(self->container, name)) { - Py_RETURN_TRUE; - } - - Py_RETURN_FALSE; -} - -static PyObject * -Container_snapshot_list(Container *self, PyObject *args, PyObject *kwds) -{ - struct lxc_snapshot *snap; - int snap_count = 0; - PyObject *list = NULL; - int i = 0; - - snap_count = self->container->snapshot_list(self->container, &snap); - - if (snap_count < 0) { - PyErr_SetString(PyExc_KeyError, "Unable to list snapshots"); - return NULL; - } - - list = PyTuple_New(snap_count); - for (i = 0; i < snap_count; i++) { - PyObject *list_entry = NULL; - - list_entry = PyTuple_New(4); - PyTuple_SET_ITEM(list_entry, 0, - PyUnicode_FromString(snap[i].name)); - PyTuple_SET_ITEM(list_entry, 1, - PyUnicode_FromString(snap[i].comment_pathname)); - PyTuple_SET_ITEM(list_entry, 2, - PyUnicode_FromString(snap[i].timestamp)); - PyTuple_SET_ITEM(list_entry, 3, - PyUnicode_FromString(snap[i].lxcpath)); - - snap[i].free(&snap[i]); - - PyTuple_SET_ITEM(list, i, list_entry); - } - - return list; -} - - -static PyObject * -Container_snapshot_restore(Container *self, PyObject *args, PyObject *kwds) -{ - char *name = NULL; - char *newname = NULL; - static char *kwlist[] = {"name", "newname", NULL}; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "s|s", kwlist, - &name, &newname)) - return NULL; - - if (self->container->snapshot_restore(self->container, name, newname)) { - Py_RETURN_TRUE; - } - - Py_RETURN_FALSE; -} - -static PyObject * -Container_start(Container *self, PyObject *args, PyObject *kwds) -{ - PyObject *useinit = NULL; - PyObject *daemonize = NULL; - PyObject *close_fds = NULL; - - PyObject *vargs = NULL; - char** init_args = {NULL}; - - PyObject *retval = NULL; - int init_useinit = 0, i = 0; - static char *kwlist[] = {"useinit", "daemonize", "close_fds", - "cmd", NULL}; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, - &useinit, &daemonize, &close_fds, - &vargs)) - return NULL; - - if (useinit && useinit == Py_True) { - init_useinit = 1; - } - - if (vargs && PyTuple_Check(vargs)) { - init_args = convert_tuple_to_char_pointer_array(vargs); - if (!init_args) { - return NULL; - } - } - - if (close_fds && close_fds == Py_True) { - self->container->want_close_all_fds(self->container, true); - } - else { - self->container->want_close_all_fds(self->container, false); - } - - if (!daemonize || daemonize == Py_True) { - self->container->want_daemonize(self->container, true); - } - else { - self->container->want_daemonize(self->container, false); - } - - if (self->container->start(self->container, init_useinit, init_args)) - retval = Py_True; - else - retval = Py_False; - - if (vargs) { - /* We cannot have gotten here unless vargs was given and create_args - * was successfully allocated. - */ - for (i = 0; i < PyTuple_GET_SIZE(vargs); i++) - free(init_args[i]); - free(init_args); - } - - Py_INCREF(retval); - return retval; -} - -static PyObject * -Container_stop(Container *self, PyObject *args, PyObject *kwds) -{ - if (self->container->stop(self->container)) { - Py_RETURN_TRUE; - } - - Py_RETURN_FALSE; -} - -static PyObject * -Container_unfreeze(Container *self, PyObject *args, PyObject *kwds) -{ - if (self->container->unfreeze(self->container)) { - Py_RETURN_TRUE; - } - - Py_RETURN_FALSE; -} - -static PyObject * -Container_wait(Container *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"state", "timeout", NULL}; - char *state = NULL; - int timeout = -1; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, - &state, &timeout)) - return NULL; - - if (self->container->wait(self->container, state, timeout)) { - Py_RETURN_TRUE; - } - - Py_RETURN_FALSE; -} - -/* Function/Properties list */ -static PyGetSetDef Container_getseters[] = { - {"config_file_name", - (getter)Container_config_file_name, NULL, - "Path to the container configuration", - NULL}, - {"controllable", - (getter)Container_controllable, NULL, - "Boolean indicating whether the container may be controlled", - NULL}, - {"defined", - (getter)Container_defined, NULL, - "Boolean indicating whether the container configuration exists", - NULL}, - {"init_pid", - (getter)Container_init_pid, NULL, - "PID of the container's init process in the host's PID namespace", - NULL}, - {"name", - (getter)Container_name, NULL, - "Container name", - NULL}, - {"running", - (getter)Container_running, NULL, - "Boolean indicating whether the container is running or not", - NULL}, - {"state", - (getter)Container_state, NULL, - "Container state", - NULL}, - {NULL, NULL, NULL, NULL, NULL} -}; - -static PyMethodDef Container_methods[] = { - {"attach_interface", (PyCFunction)Container_attach_interface, - METH_VARARGS|METH_KEYWORDS, - "attach_interface(src_ifname, dest_ifname) -> boolean\n" - "\n" - "Pass a new network device to the container." - }, - {"detach_interface", (PyCFunction)Container_detach_interface, - METH_VARARGS|METH_KEYWORDS, - "detach_interface(ifname) -> boolean\n" - "\n" - "detach a network device from the container." - }, - {"add_device_node", (PyCFunction)Container_add_device_node, - METH_VARARGS|METH_KEYWORDS, - "add_device_node(src_path, dest_path) -> boolean\n" - "\n" - "Pass a new device to the container." - }, - {"attach", (PyCFunction)Container_attach, - METH_VARARGS|METH_KEYWORDS, - "attach(run, payload) -> int\n" - "\n" - "Attach to the container. Returns the pid of the attached process." - }, - {"attach_wait", (PyCFunction)Container_attach_wait, - METH_VARARGS|METH_KEYWORDS, - "attach(run, payload) -> int\n" - "\n" - "Attach to the container. Returns the exit code of the process." - }, - {"clear_config", (PyCFunction)Container_clear_config, - METH_NOARGS, - "clear_config()\n" - "\n" - "Clear any container configuration." - }, - {"clear_config_item", (PyCFunction)Container_clear_config_item, - METH_VARARGS|METH_KEYWORDS, - "clear_config_item(key) -> boolean\n" - "\n" - "Clear the current value of a config key." - }, - {"console", (PyCFunction)Container_console, - METH_VARARGS|METH_KEYWORDS, - "console(ttynum = -1, stdinfd = 0, stdoutfd = 1, stderrfd = 2, " - "escape = 0) -> boolean\n" - "\n" - "Attach to container's console." - }, - {"console_getfd", (PyCFunction)Container_console_getfd, - METH_VARARGS|METH_KEYWORDS, - "console(ttynum = -1) -> boolean\n" - "\n" - "Attach to container's console." - }, - {"clone", (PyCFunction)Container_clone, - METH_VARARGS|METH_KEYWORDS, - "clone(newname, config_path, flags, bdevtype, bdevdata, newsize, " - "hookargs) -> boolean\n" - "\n" - "Create a new container based on the current one." - }, - {"create", (PyCFunction)Container_create, - METH_VARARGS|METH_KEYWORDS, - "create(template, args = (,)) -> boolean\n" - "\n" - "Create a new rootfs for the container, using the given template " - "and passing some optional arguments to it." - }, - {"destroy", (PyCFunction)Container_destroy, - METH_NOARGS, - "destroy() -> boolean\n" - "\n" - "Destroys the container." - }, - {"freeze", (PyCFunction)Container_freeze, - METH_NOARGS, - "freeze() -> boolean\n" - "\n" - "Freezes the container and returns its return code." - }, - {"get_cgroup_item", (PyCFunction)Container_get_cgroup_item, - METH_VARARGS|METH_KEYWORDS, - "get_cgroup_item(key) -> string\n" - "\n" - "Get the current value of a cgroup entry." - }, - {"get_config_item", (PyCFunction)Container_get_config_item, - METH_VARARGS|METH_KEYWORDS, - "get_config_item(key) -> string\n" - "\n" - "Get the current value of a config key." - }, - {"get_config_path", (PyCFunction)Container_get_config_path, - METH_NOARGS, - "get_config_path() -> string\n" - "\n" - "Return the LXC config path (where the containers are stored)." - }, - {"get_keys", (PyCFunction)Container_get_keys, - METH_VARARGS|METH_KEYWORDS, - "get_keys(key) -> string\n" - "\n" - "Get a list of valid sub-keys for a key." - }, - {"get_interfaces", (PyCFunction)Container_get_interfaces, - METH_NOARGS, - "get_interface() -> tuple\n" - "\n" - "Get a tuple of interfaces for the container." - }, - {"get_ips", (PyCFunction)Container_get_ips, - METH_VARARGS|METH_KEYWORDS, - "get_ips(interface, family, scope) -> tuple\n" - "\n" - "Get a tuple of IPs for the container." - }, - {"get_running_config_item", (PyCFunction)Container_get_running_config_item, - METH_VARARGS|METH_KEYWORDS, - "get_running_config_item(key) -> string\n" - "\n" - "Get the runtime value of a config key." - }, - {"load_config", (PyCFunction)Container_load_config, - METH_VARARGS|METH_KEYWORDS, - "load_config(path = DEFAULT) -> boolean\n" - "\n" - "Read the container configuration from its default " - "location or from an alternative location if provided." - }, - {"reboot", (PyCFunction)Container_reboot, - METH_NOARGS, - "reboot() -> boolean\n" - "\n" - "Ask the container to reboot." - }, - {"rename", (PyCFunction)Container_rename, - METH_VARARGS|METH_KEYWORDS, - "rename(new_name) -> boolean\n" - "\n" - "Rename the container." - }, - {"remove_device_node", (PyCFunction)Container_remove_device_node, - METH_VARARGS|METH_KEYWORDS, - "remove_device_node(src_path, dest_path) -> boolean\n" - "\n" - "Remove a device from the container." - }, - {"save_config", (PyCFunction)Container_save_config, - METH_VARARGS|METH_KEYWORDS, - "save_config(path = DEFAULT) -> boolean\n" - "\n" - "Save the container configuration to its default " - "location or to an alternative location if provided." - }, - {"set_cgroup_item", (PyCFunction)Container_set_cgroup_item, - METH_VARARGS|METH_KEYWORDS, - "set_cgroup_item(key, value) -> boolean\n" - "\n" - "Set a cgroup entry to the provided value." - }, - {"set_config_item", (PyCFunction)Container_set_config_item, - METH_VARARGS|METH_KEYWORDS, - "set_config_item(key, value) -> boolean\n" - "\n" - "Set a config key to the provided value." - }, - {"set_config_path", (PyCFunction)Container_set_config_path, - METH_VARARGS|METH_KEYWORDS, - "set_config_path(path) -> boolean\n" - "\n" - "Set the LXC config path (where the containers are stored)." - }, - {"shutdown", (PyCFunction)Container_shutdown, - METH_VARARGS|METH_KEYWORDS, - "shutdown(timeout = -1) -> boolean\n" - "\n" - "Sends SIGPWR to the container and wait for it to shutdown." - "-1 means wait forever, 0 means skip waiting." - }, - {"snapshot", (PyCFunction)Container_snapshot, - METH_VARARGS|METH_KEYWORDS, - "snapshot(comment_path = None) -> string\n" - "\n" - "Snapshot the container and return the snapshot name " - "(or False on error)." - }, - {"snapshot_destroy", (PyCFunction)Container_snapshot_destroy, - METH_VARARGS|METH_KEYWORDS, - "snapshot_destroy(name) -> boolean\n" - "\n" - "Destroy a snapshot." - }, - {"snapshot_list", (PyCFunction)Container_snapshot_list, - METH_NOARGS, - "snapshot_list() -> tuple of snapshot tuples\n" - "\n" - "List all snapshots for a container." - }, - {"snapshot_restore", (PyCFunction)Container_snapshot_restore, - METH_VARARGS|METH_KEYWORDS, - "snapshot_restore(name, newname = None) -> boolean\n" - "\n" - "Restore a container snapshot. If newname is provided a new " - "container will be created from the snapshot, otherwise an in-place " - "restore will be attempted." - }, - {"start", (PyCFunction)Container_start, - METH_VARARGS|METH_KEYWORDS, - "start(useinit = False, daemonize=True, close_fds=False, " - "cmd = (,)) -> boolean\n" - "\n" - "Start the container, return True on success.\n" - "When set useinit will make LXC use lxc-init to start the container.\n" - "The container can be started in the foreground with daemonize=False.\n" - "All fds may also be closed by passing close_fds=True." - }, - {"stop", (PyCFunction)Container_stop, - METH_NOARGS, - "stop() -> boolean\n" - "\n" - "Stop the container and returns its return code." - }, - {"unfreeze", (PyCFunction)Container_unfreeze, - METH_NOARGS, - "unfreeze() -> boolean\n" - "\n" - "Unfreezes the container and returns its return code." - }, - {"wait", (PyCFunction)Container_wait, - METH_VARARGS|METH_KEYWORDS, - "wait(state, timeout = -1) -> boolean\n" - "\n" - "Wait for the container to reach a given state or timeout." - }, - {NULL, NULL, 0, NULL} -}; - -static PyTypeObject _lxc_ContainerType = { -PyVarObject_HEAD_INIT(NULL, 0) - "lxc.Container", /* tp_name */ - sizeof(Container), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)Container_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - "Container objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - Container_methods, /* tp_methods */ - 0, /* tp_members */ - Container_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)Container_init, /* tp_init */ - 0, /* tp_alloc */ - Container_new, /* tp_new */ -}; - -static PyMethodDef LXC_methods[] = { - {"arch_to_personality", (PyCFunction)LXC_arch_to_personality, METH_O, - "Returns the process personality of the corresponding architecture"}, - {"attach_run_command", (PyCFunction)LXC_attach_run_command, METH_O, - "Runs a command when attaching, to use as the run parameter for attach " - "or attach_wait"}, - {"attach_run_shell", (PyCFunction)LXC_attach_run_shell, METH_O, - "Starts up a shell when attaching, to use as the run parameter for " - "attach or attach_wait"}, - {"get_global_config_item", (PyCFunction)LXC_get_global_config_item, - METH_VARARGS|METH_KEYWORDS, - "Returns the current LXC config path"}, - {"get_version", (PyCFunction)LXC_get_version, METH_NOARGS, - "Returns the current LXC library version"}, - {"list_containers", (PyCFunction)LXC_list_containers, - METH_VARARGS|METH_KEYWORDS, - "Returns a list of container names or objects"}, - {NULL, NULL, 0, NULL} -}; - -static PyModuleDef _lxcmodule = { - PyModuleDef_HEAD_INIT, - "_lxc", - "Binding for liblxc in python", - -1, - LXC_methods -}; - -PyMODINIT_FUNC -PyInit__lxc(void) -{ - PyObject* m; - PyObject* d; - - if (PyType_Ready(&_lxc_ContainerType) < 0) - return NULL; - - m = PyModule_Create(&_lxcmodule); - if (m == NULL) - return NULL; - - Py_INCREF(&_lxc_ContainerType); - PyModule_AddObject(m, "Container", (PyObject *)&_lxc_ContainerType); - - /* add constants */ - d = PyModule_GetDict(m); - - #define PYLXC_EXPORT_CONST(c) \ - PyDict_SetItemString(d, #c, PyLong_FromLong(c)) - - /* namespace flags (no other python lib exports this) */ - PYLXC_EXPORT_CONST(CLONE_NEWUTS); - PYLXC_EXPORT_CONST(CLONE_NEWIPC); - PYLXC_EXPORT_CONST(CLONE_NEWUSER); - PYLXC_EXPORT_CONST(CLONE_NEWPID); - PYLXC_EXPORT_CONST(CLONE_NEWNET); - PYLXC_EXPORT_CONST(CLONE_NEWNS); - - /* attach: environment variable handling */ - PYLXC_EXPORT_CONST(LXC_ATTACH_CLEAR_ENV); - PYLXC_EXPORT_CONST(LXC_ATTACH_KEEP_ENV); - - /* attach: attach options */ - PYLXC_EXPORT_CONST(LXC_ATTACH_DEFAULT); - PYLXC_EXPORT_CONST(LXC_ATTACH_DROP_CAPABILITIES); - PYLXC_EXPORT_CONST(LXC_ATTACH_LSM_EXEC); - PYLXC_EXPORT_CONST(LXC_ATTACH_LSM_NOW); - PYLXC_EXPORT_CONST(LXC_ATTACH_MOVE_TO_CGROUP); - PYLXC_EXPORT_CONST(LXC_ATTACH_REMOUNT_PROC_SYS); - PYLXC_EXPORT_CONST(LXC_ATTACH_SET_PERSONALITY); - - /* clone: clone flags */ - PYLXC_EXPORT_CONST(LXC_CLONE_KEEPBDEVTYPE); - PYLXC_EXPORT_CONST(LXC_CLONE_KEEPMACADDR); - PYLXC_EXPORT_CONST(LXC_CLONE_KEEPNAME); - PYLXC_EXPORT_CONST(LXC_CLONE_MAYBE_SNAPSHOT); - PYLXC_EXPORT_CONST(LXC_CLONE_SNAPSHOT); - - /* create: create flags */ - PYLXC_EXPORT_CONST(LXC_CREATE_QUIET); - - #undef PYLXC_EXPORT_CONST - - return m; -} - -/* - * kate: space-indent on; indent-width 4; mixedindent off; indent-mode cstyle; - */ diff --git a/src/python-lxc/lxc/__init__.py b/src/python-lxc/lxc/__init__.py deleted file mode 100644 index ccc4d18bb..000000000 --- a/src/python-lxc/lxc/__init__.py +++ /dev/null @@ -1,510 +0,0 @@ -# -# -*- coding: utf-8 -*- -# python-lxc: Python bindings for LXC -# -# (C) Copyright Canonical Ltd. 2012 -# -# Authors: -# Stéphane Graber -# -# 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 -# - -import _lxc -import os -import subprocess -import time - -default_config_path = _lxc.get_global_config_item("lxc.lxcpath") -get_global_config_item = _lxc.get_global_config_item -version = _lxc.get_version() - - -class ContainerNetwork(object): - props = {} - - def __init__(self, container, index): - self.container = container - self.index = index - - for key in self.container.get_keys("lxc.net.%s" % self.index): - if "." in key: - self.props[key.replace(".", "_")] = key - else: - self.props[key] = key - - if not self.props: - return False - - def __delattr__(self, key): - if key in ["container", "index", "props"]: - return object.__delattr__(self, key) - - if key not in self.props: - raise AttributeError("'%s' network has no attribute '%s'" % ( - self.__get_network_item("type"), key)) - - return self.__clear_network_item(self.props[key]) - - def __dir__(self): - return sorted(self.props.keys()) - - def __getattr__(self, key): - if key in ["container", "index", "props"]: - return object.__getattribute__(self, key) - - if key not in self.props: - raise AttributeError("'%s' network has no attribute '%s'" % ( - self.__get_network_item("type"), key)) - - return self.__get_network_item(self.props[key]) - - def __hasattr__(self, key): - if key in ["container", "index", "props"]: - return object.__hasattr__(self, key) - - if key not in self.props: - raise AttributeError("'%s' network has no attribute '%s'" % ( - self.__get_network_item("type"), key)) - - return True - - def __repr__(self): - return "'%s' network at index '%s'" % ( - self.__get_network_item("type"), self.index) - - def __setattr__(self, key, value): - if key in ["container", "index", "props"]: - return object.__setattr__(self, key, value) - - if key not in self.props: - raise AttributeError("'%s' network has no attribute '%s'" % ( - self.__get_network_item("type"), key)) - - return self.__set_network_item(self.props[key], value) - - def __clear_network_item(self, key): - if key in ("ipv4", "ipv6"): - return self.container.clear_config_item("lxc.net.%s.%s" % ( - self.index, key)) - else: - return self.container.set_config_item("lxc.net.%s.%s" % ( - self.index, key), "") - - def __get_network_item(self, key): - return self.container.get_config_item("lxc.net.%s.%s" % ( - self.index, key)) - - def __set_network_item(self, key, value): - return self.container.set_config_item("lxc.net.%s.%s" % ( - self.index, key), value) - - -class ContainerNetworkList(): - def __init__(self, container): - self.container = container - - def __getitem__(self, index): - if index >= len(self): - raise IndexError("list index out of range") - - return ContainerNetwork(self.container, index) - - def __len__(self): - values = self.container.get_config_item("lxc.net") - - if values: - return len(values) - else: - return 0 - - def add(self, network_type): - index = len(self) - - return self.container.set_config_item("lxc.net.%s.type" % index, - network_type) - - def remove(self, index): - count = len(self) - if index >= count: - raise IndexError("list index out of range") - - return self.container.clear_config_item("lxc.net.%s" % index) - - -class Container(_lxc.Container): - def __init__(self, name, config_path=None): - """ - Creates a new Container instance. - """ - - if config_path: - _lxc.Container.__init__(self, name, config_path) - else: - _lxc.Container.__init__(self, name) - - self.network = ContainerNetworkList(self) - - def add_device_net(self, name, destname=None): - """ - Add network device to running container. - """ - - if not self.running: - return False - - if os.path.exists("/sys/class/net/%s/phy80211/name" % name): - with open("/sys/class/net/%s/phy80211/name" % name) as fd: - phy = fd.read().strip() - - if subprocess.call(['iw', 'phy', phy, 'set', 'netns', - str(self.init_pid)]) != 0: - return False - - if destname: - def rename_interface(args): - old, new = args - - return subprocess.call(['ip', 'link', 'set', - 'dev', old, 'name', new]) - - return self.attach_wait(rename_interface, (name, destname), - namespaces=(CLONE_NEWNET)) == 0 - - return True - - if not destname: - destname = name - - if not os.path.exists("/sys/class/net/%s/" % name): - return False - - return subprocess.call(['ip', 'link', 'set', - 'dev', name, - 'netns', str(self.init_pid), - 'name', destname]) == 0 - - def append_config_item(self, key, value): - """ - Append 'value' to 'key', assuming 'key' is a list. - If 'key' isn't a list, 'value' will be set as the value of 'key'. - """ - - return _lxc.Container.set_config_item(self, key, value) - - def create(self, template=None, flags=0, args=(), bdevtype=None): - """ - Create a new rootfs for the container. - - "template" if passed must be a valid template name. - - "flags" (optional) is an integer representing the optional - create flags to be passed. - - "args" (optional) is a tuple of arguments to pass to the - template. It can also be provided as a dict. - """ - if isinstance(args, dict): - tmp_args = [] - for item in args.items(): - tmp_args.append("--%s" % item[0]) - tmp_args.append("%s" % item[1]) - args = tmp_args - template_args = {} - if template: - template_args['template'] = template - template_args['flags'] = flags - template_args['args'] = tuple(args) - if bdevtype: - template_args['bdevtype'] = bdevtype - return _lxc.Container.create(self, **template_args) - - def clone(self, newname, config_path=None, flags=0, bdevtype=None, - bdevdata=None, newsize=0, hookargs=()): - """ - Clone the current container. - """ - - args = {} - args['newname'] = newname - args['flags'] = flags - args['newsize'] = newsize - args['hookargs'] = hookargs - if config_path: - args['config_path'] = config_path - if bdevtype: - args['bdevtype'] = bdevtype - if bdevdata: - args['bdevdata'] = bdevdata - - if _lxc.Container.clone(self, **args): - return Container(newname, config_path=config_path) - else: - return False - - def console(self, ttynum=-1, stdinfd=0, stdoutfd=1, stderrfd=2, escape=1): - """ - Attach to console of running container. - """ - - if not self.running: - return False - - return _lxc.Container.console(self, ttynum, stdinfd, stdoutfd, - stderrfd, escape) - - def console_getfd(self, ttynum=-1): - """ - Attach to console of running container. - """ - - if not self.running: - return False - - return _lxc.Container.console_getfd(self, ttynum) - - def get_cgroup_item(self, key): - """ - Returns the value for a given cgroup entry. - A list is returned when multiple values are set. - """ - value = _lxc.Container.get_cgroup_item(self, key) - - if value is False: - return False - else: - return value.rstrip("\n") - - def get_config_item(self, key): - """ - Returns the value for a given config key. - A list is returned when multiple values are set. - """ - value = _lxc.Container.get_config_item(self, key) - - if value is False: - return False - elif value.endswith("\n"): - return value.rstrip("\n").split("\n") - else: - return value - - def get_keys(self, key=None): - """ - Returns a list of valid sub-keys. - """ - if key: - value = _lxc.Container.get_keys(self, key) - else: - value = _lxc.Container.get_keys(self) - - if value is False: - return False - elif value.endswith("\n"): - return value.rstrip("\n").split("\n") - else: - return value - - def get_interfaces(self): - """ - Get a tuple of interfaces for the container. - """ - - return _lxc.Container.get_interfaces(self) - - def get_ips(self, interface=None, family=None, scope=None, timeout=0): - """ - Get a tuple of IPs for the container. - """ - - kwargs = {} - if interface: - kwargs['interface'] = interface - if family: - kwargs['family'] = family - if scope: - kwargs['scope'] = scope - - ips = None - timeout = int(os.environ.get('LXC_GETIP_TIMEOUT', timeout)) - - while not ips: - ips = _lxc.Container.get_ips(self, **kwargs) - if timeout == 0: - break - - timeout -= 1 - time.sleep(1) - - return ips - - def rename(self, new_name): - """ - Rename the container. - On success, returns the new Container object. - On failure, returns False. - """ - - if _lxc.Container.rename(self, new_name): - return Container(new_name) - - return False - - def set_config_item(self, key, value): - """ - Set a config key to a provided value. - The value can be a list for the keys supporting multiple values. - """ - try: - old_value = self.get_config_item(key) - except KeyError: - old_value = None - - # Check if it's a list - def set_key(key, value): - self.clear_config_item(key) - if isinstance(value, list): - for entry in value: - if not _lxc.Container.set_config_item(self, key, entry): - return False - else: - _lxc.Container.set_config_item(self, key, value) - - set_key(key, value) - new_value = self.get_config_item(key) - - # loglevel is special and won't match the string we set - if key == "lxc.log.level": - new_value = value - - if (isinstance(value, str) and isinstance(new_value, str) and - value == new_value): - return True - elif (isinstance(value, list) and isinstance(new_value, list) and - set(value) == set(new_value)): - return True - elif (isinstance(value, str) and isinstance(new_value, list) and - set([value]) == set(new_value)): - return True - elif old_value: - set_key(key, old_value) - return False - else: - self.clear_config_item(key) - return False - - def wait(self, state, timeout=-1): - """ - Wait for the container to reach a given state or timeout. - """ - - if isinstance(state, str): - state = state.upper() - - return _lxc.Container.wait(self, state, timeout) - - -def list_containers(active=True, defined=True, - as_object=False, config_path=None): - """ - List the containers on the system. - """ - - if config_path: - if not os.path.exists(config_path): - return tuple() - try: - entries = _lxc.list_containers(active=active, defined=defined, - config_path=config_path) - except ValueError: - return tuple() - else: - try: - entries = _lxc.list_containers(active=active, defined=defined) - except ValueError: - return tuple() - - if as_object: - return tuple([Container(name, config_path) for name in entries]) - else: - return entries - - -def attach_run_command(cmd): - """ - Run a command when attaching - - Please do not call directly, this will execvp the command. - This is to be used in conjunction with the attach method - of a container. - """ - if isinstance(cmd, tuple): - return _lxc.attach_run_command(cmd) - elif isinstance(cmd, list): - return _lxc.attach_run_command((cmd[0], cmd)) - else: - return _lxc.attach_run_command((cmd, [cmd])) - - -def attach_run_shell(): - """ - Run a shell when attaching - - Please do not call directly, this will execvp the shell. - This is to be used in conjunction with the attach method - of a container. - """ - return _lxc.attach_run_shell(None) - - -def arch_to_personality(arch): - """ - Determine the process personality corresponding to the architecture - """ - if isinstance(arch, bytes): - arch = str(arch, 'utf-8') - return _lxc.arch_to_personality(arch) - -# namespace flags (no other python lib exports this) -CLONE_NEWIPC = _lxc.CLONE_NEWIPC -CLONE_NEWNET = _lxc.CLONE_NEWNET -CLONE_NEWNS = _lxc.CLONE_NEWNS -CLONE_NEWPID = _lxc.CLONE_NEWPID -CLONE_NEWUSER = _lxc.CLONE_NEWUSER -CLONE_NEWUTS = _lxc.CLONE_NEWUTS - -# attach: environment variable handling -LXC_ATTACH_CLEAR_ENV = _lxc.LXC_ATTACH_CLEAR_ENV -LXC_ATTACH_KEEP_ENV = _lxc.LXC_ATTACH_KEEP_ENV - -# attach: attach options -LXC_ATTACH_DEFAULT = _lxc.LXC_ATTACH_DEFAULT -LXC_ATTACH_DROP_CAPABILITIES = _lxc.LXC_ATTACH_DROP_CAPABILITIES -LXC_ATTACH_LSM_EXEC = _lxc.LXC_ATTACH_LSM_EXEC -LXC_ATTACH_LSM_NOW = _lxc.LXC_ATTACH_LSM_NOW -LXC_ATTACH_MOVE_TO_CGROUP = _lxc.LXC_ATTACH_MOVE_TO_CGROUP -LXC_ATTACH_REMOUNT_PROC_SYS = _lxc.LXC_ATTACH_REMOUNT_PROC_SYS -LXC_ATTACH_SET_PERSONALITY = _lxc.LXC_ATTACH_SET_PERSONALITY - -# clone: clone flags -LXC_CLONE_KEEPBDEVTYPE = _lxc.LXC_CLONE_KEEPBDEVTYPE -LXC_CLONE_KEEPMACADDR = _lxc.LXC_CLONE_KEEPMACADDR -LXC_CLONE_KEEPNAME = _lxc.LXC_CLONE_KEEPNAME -LXC_CLONE_MAYBE_SNAPSHOT = _lxc.LXC_CLONE_MAYBE_SNAPSHOT -LXC_CLONE_SNAPSHOT = _lxc.LXC_CLONE_SNAPSHOT - -# create: create flags -LXC_CREATE_QUIET = _lxc.LXC_CREATE_QUIET diff --git a/src/python-lxc/setup.py b/src/python-lxc/setup.py deleted file mode 100644 index bf0d74a0c..000000000 --- a/src/python-lxc/setup.py +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/env python3 -# -# python-lxc: Python bindings for LXC -# -# (C) Copyright Canonical Ltd. 2012 -# -# Authors: -# Stéphane Graber -# -# 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 - -import os -import subprocess - -# Fix build when PIE is enabled (must run before setuptools import) -for var in ("LDFLAGS", "CFLAGS"): - current = os.environ.get(var, None) - if not current: - continue - - new = [] - for flag in current.split(" "): - if flag.lower() in ("-pie", "-fpie"): - if "-fPIC" not in new: - new.append("-fPIC") - continue - new.append(flag) - - os.environ[var] = " ".join(new) - -from setuptools import setup, Extension -from setuptools.command.build_ext import build_ext as BuildExtCommand - - -class LxcBuildExtCommand(BuildExtCommand): - user_options = BuildExtCommand.user_options + [ - ('no-pkg-config', None, - "don't use pkg-config to detect include/library paths") - ] - - def initialize_options(self): - super(LxcBuildExtCommand, self).initialize_options() - self.no_pkg_config = False - - def build_extensions(self): - if not self.no_pkg_config: - pkg_config_executable = os.environ.get('PKG_CONFIG_EXECUTABLE', - 'pkg-config') - - def get_pkg_config_var(name): - args = [pkg_config_executable, '--variable', name, 'lxc'] - output = subprocess.check_output(args, - universal_newlines=True) - return output.rstrip('\n') - - try: - includedir = get_pkg_config_var('includedir') - libdir = get_pkg_config_var('libdir') - - self.compiler.add_include_dir(includedir) - self.compiler.add_library_dir(libdir) - - except subprocess.CalledProcessError: - pass - - super(LxcBuildExtCommand, self).build_extensions() - - -setup(name='lxc', - version='0.1', - description='LXC', - packages=['lxc'], - package_dir={'lxc': 'lxc'}, - ext_modules=[Extension('_lxc', sources=['lxc.c'], libraries=['lxc'])], - cmdclass={'build_ext': LxcBuildExtCommand}, - ) From 98619a7362229198f28ee0cd682d9dea635bd3ce Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Wed, 14 Feb 2018 11:57:47 +0100 Subject: [PATCH 05/12] autotools: remove --enable-deprecated Signed-off-by: Christian Brauner --- configure.ac | 7 ------- 1 file changed, 7 deletions(-) diff --git a/configure.ac b/configure.ac index 1cf1a4ba9..a4de1f29b 100644 --- a/configure.ac +++ b/configure.ac @@ -173,13 +173,6 @@ AC_ARG_ENABLE([werror], [do not treat warnings as errors])], [], [enable_werror=yes]) -# Allow enabling deprecated executables -AC_ARG_ENABLE([deprecated], - [AC_HELP_STRING([--enable-deprecated], - [enable deprecated executables [default=no]])], - [], [enable_deprecated=false]) -AM_CONDITIONAL([ENABLE_DEPRECATED], [test "x$enable_deprecated" = "xyes"]) - # Allow disabling rpath AC_ARG_ENABLE([rpath], [AC_HELP_STRING([--enable-rpath], [set rpath in executables [default=no]])], From aafb5ea2a849056f9866359996605af0290605bd Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Mon, 26 Feb 2018 21:12:17 +0100 Subject: [PATCH 06/12] tree-wide: rm templates in favor of distrobuilder Signed-off-by: Christian Brauner --- config/templates/Makefile.am | 45 +- config/templates/alpine.common.conf.in | 24 - config/templates/alpine.userns.conf.in | 2 - config/templates/archlinux.common.conf.in | 31 - config/templates/archlinux.userns.conf.in | 2 - config/templates/centos.common.conf.in | 20 - config/templates/centos.userns.conf.in | 2 - config/templates/debian.common.conf.in | 28 - config/templates/debian.userns.conf.in | 2 - config/templates/fedora.common.conf.in | 21 - config/templates/fedora.userns.conf.in | 2 - config/templates/gentoo.common.conf.in | 27 - config/templates/gentoo.moresecure.conf.in | 45 - config/templates/gentoo.userns.conf.in | 2 - config/templates/opensuse.common.conf.in | 22 - config/templates/opensuse.userns.conf.in | 2 - config/templates/openwrt.common.conf.in | 50 - config/templates/oracle.common.conf.in | 20 - config/templates/oracle.userns.conf.in | 2 - config/templates/plamo.common.conf.in | 9 - config/templates/plamo.userns.conf.in | 2 - config/templates/sabayon.common.conf.in | 79 - config/templates/sabayon.userns.conf.in | 2 - config/templates/slackware.common.conf.in | 46 - config/templates/slackware.userns.conf.in | 2 - config/templates/sparclinux.common.conf.in | 20 - config/templates/sparclinux.userns.conf.in | 2 - config/templates/ubuntu-cloud.common.conf.in | 4 - config/templates/ubuntu-cloud.lucid.conf.in | 2 - config/templates/ubuntu-cloud.userns.conf.in | 2 - config/templates/ubuntu.common.conf.in | 35 - config/templates/ubuntu.lucid.conf.in | 2 - config/templates/ubuntu.userns.conf.in | 6 - config/templates/voidlinux.common.conf.in | 35 - config/templates/voidlinux.userns.conf.in | 8 - configure.ac | 55 - templates/Makefile.am | 30 +- templates/lxc-alpine.in | 516 ------ templates/lxc-altlinux.in | 498 ------ templates/lxc-archlinux.in | 334 ---- templates/lxc-centos.in | 968 ------------ templates/lxc-cirros.in | 343 ---- templates/lxc-debian.in | 824 ---------- templates/lxc-fedora-legacy.in | 1495 ------------------ templates/lxc-fedora.in | 1291 --------------- templates/lxc-gentoo.in | 833 ---------- templates/lxc-openmandriva.in | 484 ------ templates/lxc-opensuse.in | 557 ------- templates/lxc-oracle.in | 972 ------------ templates/lxc-plamo.in | 384 ----- templates/lxc-pld.in | 484 ------ templates/lxc-sabayon.in | 513 ------ templates/lxc-slackware.in | 793 ---------- templates/lxc-sparclinux.in | 702 -------- templates/lxc-sshd.in | 276 ---- templates/lxc-ubuntu-cloud.in | 374 ----- templates/lxc-ubuntu.in | 877 ---------- templates/lxc-voidlinux.in | 199 --- 58 files changed, 9 insertions(+), 14398 deletions(-) delete mode 100644 config/templates/alpine.common.conf.in delete mode 100644 config/templates/alpine.userns.conf.in delete mode 100644 config/templates/archlinux.common.conf.in delete mode 100644 config/templates/archlinux.userns.conf.in delete mode 100644 config/templates/centos.common.conf.in delete mode 100644 config/templates/centos.userns.conf.in delete mode 100644 config/templates/debian.common.conf.in delete mode 100644 config/templates/debian.userns.conf.in delete mode 100644 config/templates/fedora.common.conf.in delete mode 100644 config/templates/fedora.userns.conf.in delete mode 100644 config/templates/gentoo.common.conf.in delete mode 100644 config/templates/gentoo.moresecure.conf.in delete mode 100644 config/templates/gentoo.userns.conf.in delete mode 100644 config/templates/opensuse.common.conf.in delete mode 100644 config/templates/opensuse.userns.conf.in delete mode 100644 config/templates/openwrt.common.conf.in delete mode 100644 config/templates/oracle.common.conf.in delete mode 100644 config/templates/oracle.userns.conf.in delete mode 100644 config/templates/plamo.common.conf.in delete mode 100644 config/templates/plamo.userns.conf.in delete mode 100644 config/templates/sabayon.common.conf.in delete mode 100644 config/templates/sabayon.userns.conf.in delete mode 100644 config/templates/slackware.common.conf.in delete mode 100644 config/templates/slackware.userns.conf.in delete mode 100644 config/templates/sparclinux.common.conf.in delete mode 100644 config/templates/sparclinux.userns.conf.in delete mode 100644 config/templates/ubuntu-cloud.common.conf.in delete mode 100644 config/templates/ubuntu-cloud.lucid.conf.in delete mode 100644 config/templates/ubuntu-cloud.userns.conf.in delete mode 100644 config/templates/ubuntu.common.conf.in delete mode 100644 config/templates/ubuntu.lucid.conf.in delete mode 100644 config/templates/ubuntu.userns.conf.in delete mode 100644 config/templates/voidlinux.common.conf.in delete mode 100644 config/templates/voidlinux.userns.conf.in delete mode 100644 templates/lxc-alpine.in delete mode 100644 templates/lxc-altlinux.in delete mode 100644 templates/lxc-archlinux.in delete mode 100644 templates/lxc-centos.in delete mode 100644 templates/lxc-cirros.in delete mode 100644 templates/lxc-debian.in delete mode 100644 templates/lxc-fedora-legacy.in delete mode 100644 templates/lxc-fedora.in delete mode 100644 templates/lxc-gentoo.in delete mode 100644 templates/lxc-openmandriva.in delete mode 100644 templates/lxc-opensuse.in delete mode 100644 templates/lxc-oracle.in delete mode 100644 templates/lxc-plamo.in delete mode 100644 templates/lxc-pld.in delete mode 100644 templates/lxc-sabayon.in delete mode 100644 templates/lxc-slackware.in delete mode 100644 templates/lxc-sparclinux.in delete mode 100644 templates/lxc-sshd.in delete mode 100644 templates/lxc-ubuntu-cloud.in delete mode 100644 templates/lxc-ubuntu.in delete mode 100644 templates/lxc-voidlinux.in diff --git a/config/templates/Makefile.am b/config/templates/Makefile.am index 6598615b4..3ec580910 100644 --- a/config/templates/Makefile.am +++ b/config/templates/Makefile.am @@ -4,43 +4,8 @@ EXTRA_DIST = common.seccomp SUBDIRS = common.conf.d -templatesconfig_DATA = \ - alpine.common.conf \ - alpine.userns.conf \ - archlinux.common.conf \ - archlinux.userns.conf \ - centos.common.conf \ - centos.userns.conf \ - common.conf \ - common.seccomp \ - debian.common.conf \ - debian.userns.conf \ - fedora.common.conf \ - fedora.userns.conf \ - gentoo.common.conf \ - gentoo.moresecure.conf \ - gentoo.userns.conf \ - nesting.conf \ - oci.common.conf \ - opensuse.common.conf \ - opensuse.userns.conf \ - oracle.common.conf \ - oracle.userns.conf \ - plamo.common.conf \ - plamo.userns.conf \ - slackware.common.conf \ - slackware.userns.conf \ - ubuntu-cloud.common.conf \ - ubuntu-cloud.lucid.conf \ - ubuntu-cloud.userns.conf \ - ubuntu.common.conf \ - ubuntu.lucid.conf \ - ubuntu.userns.conf \ - openwrt.common.conf \ - sparclinux.common.conf \ - sparclinux.userns.conf \ - voidlinux.common.conf \ - voidlinux.userns.conf \ - sabayon.common.conf \ - sabayon.userns.conf \ - userns.conf +templatesconfig_DATA = common.conf \ + common.seccomp \ + nesting.conf \ + oci.common.conf \ + userns.conf diff --git a/config/templates/alpine.common.conf.in b/config/templates/alpine.common.conf.in deleted file mode 100644 index 1c4cf815a..000000000 --- a/config/templates/alpine.common.conf.in +++ /dev/null @@ -1,24 +0,0 @@ -# This derives from the global common config. -lxc.include = @LXCTEMPLATECONFIG@/common.conf - -# Doesn't support consoles in /dev/lxc/. -lxc.tty.dir = - -# Drop another (potentially) harmful capabilities. -lxc.cap.drop = audit_write -lxc.cap.drop = ipc_owner -lxc.cap.drop = mknod -lxc.cap.drop = setpcap -lxc.cap.drop = sys_nice -lxc.cap.drop = sys_pacct -lxc.cap.drop = sys_rawio -lxc.cap.drop = sys_resource -lxc.cap.drop = sys_tty_config -lxc.cap.drop = syslog -lxc.cap.drop = wake_alarm - -# Mount /run as tmpfs. -lxc.mount.entry=run run tmpfs rw,nodev,relatime,mode=755 0 0 - -# Mount /dev/shm as tmpfs; needed for building python and possibly other packages. -lxc.mount.entry=shm dev/shm tmpfs rw,nodev,noexec,nosuid,relatime,mode=1777,create=dir 0 0 diff --git a/config/templates/alpine.userns.conf.in b/config/templates/alpine.userns.conf.in deleted file mode 100644 index 4336b448c..000000000 --- a/config/templates/alpine.userns.conf.in +++ /dev/null @@ -1,2 +0,0 @@ -# This derives from the global userns config. -lxc.include = @LXCTEMPLATECONFIG@/userns.conf diff --git a/config/templates/archlinux.common.conf.in b/config/templates/archlinux.common.conf.in deleted file mode 100644 index 81d654883..000000000 --- a/config/templates/archlinux.common.conf.in +++ /dev/null @@ -1,31 +0,0 @@ -# This derives from the global common config -lxc.include = @LXCTEMPLATECONFIG@/common.conf - -# Allow for 6 tty devices by default -lxc.tty.max = 6 - -# Set the halt/stop signals -lxc.signal.halt=SIGRTMIN+4 - -# Uncomment to disable creating tty devices subdirectory in /dev -# lxc.tty.dir = - -# Capabilities -# Uncomment these if you don't run anything that needs the capability, and -# would like the container to run with less privilege. -# -# Dropping sys_admin disables container root from doing a lot of things -# that could be bad like re-mounting lxc fstab entries rw for example, -# but also disables some useful things like being able to nfs mount, and -# things that are already namespaced with ns_capable() kernel checks, like -# hostname(1). -# lxc.cap.drop = sys_admin -# lxc.cap.drop = net_raw # breaks dhcp/ping -# lxc.cap.drop = setgid # breaks login (initgroups/setgroups) -# lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) -# lxc.cap.drop = setuid # breaks sshd,nfs statd -# lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) -# lxc.cap.drop = audit_write -# lxc.cap.drop = setpcap # big big login delays in Fedora 20 systemd -# -lxc.cap.drop = setfcap sys_nice sys_pacct sys_rawio diff --git a/config/templates/archlinux.userns.conf.in b/config/templates/archlinux.userns.conf.in deleted file mode 100644 index 707bb30c0..000000000 --- a/config/templates/archlinux.userns.conf.in +++ /dev/null @@ -1,2 +0,0 @@ -# This derives from the global userns config -lxc.include = @LXCTEMPLATECONFIG@/userns.conf diff --git a/config/templates/centos.common.conf.in b/config/templates/centos.common.conf.in deleted file mode 100644 index 8a72ad003..000000000 --- a/config/templates/centos.common.conf.in +++ /dev/null @@ -1,20 +0,0 @@ -# This derives from the global common config -lxc.include = @LXCTEMPLATECONFIG@/common.conf - -# Capabilities -# Uncomment these if you don't run anything that needs the capability, and -# would like the container to run with less privilege. -# -# Dropping sys_admin disables container root from doing a lot of things -# that could be bad like re-mounting lxc fstab entries rw for example, -# but also disables some useful things like being able to nfs mount, and -# things that are already namespaced with ns_capable() kernel checks, like -# hostname(1). -# lxc.cap.drop = sys_admin -# lxc.cap.drop = net_raw # breaks dhcp/ping -# lxc.cap.drop = setgid # breaks login (initgroups/setgroups) -# lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) -# lxc.cap.drop = setuid # breaks sshd,nfs statd -# lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) -# lxc.cap.drop = audit_write -lxc.cap.drop = sys_nice sys_pacct sys_rawio diff --git a/config/templates/centos.userns.conf.in b/config/templates/centos.userns.conf.in deleted file mode 100644 index 707bb30c0..000000000 --- a/config/templates/centos.userns.conf.in +++ /dev/null @@ -1,2 +0,0 @@ -# This derives from the global userns config -lxc.include = @LXCTEMPLATECONFIG@/userns.conf diff --git a/config/templates/debian.common.conf.in b/config/templates/debian.common.conf.in deleted file mode 100644 index 4e6a6e6a3..000000000 --- a/config/templates/debian.common.conf.in +++ /dev/null @@ -1,28 +0,0 @@ -# This derives from the global common config -lxc.include = @LXCTEMPLATECONFIG@/common.conf - -# Doesn't support consoles in /dev/lxc/ -lxc.tty.dir = - -# When using LXC with apparmor, the container will be confined by default. -# If you wish for it to instead run unconfined, copy the following line -# (uncommented) to the container's configuration file. -#lxc.apparmor.profile = unconfined - -# If you wish to allow mounting block filesystems, then use the following -# line instead, and make sure to grant access to the block device and/or loop -# devices below in lxc.cgroup.devices.allow. -#lxc.apparmor.profile = lxc-container-default-with-mounting - -# Extra cgroup device access -## rtc -lxc.cgroup.devices.allow = c 254:0 rm -## tun -lxc.cgroup.devices.allow = c 10:200 rwm -## hpet -lxc.cgroup.devices.allow = c 10:228 rwm -## kvm -lxc.cgroup.devices.allow = c 10:232 rwm -## To use loop devices, copy the following line to the container's -## configuration file (uncommented). -#lxc.cgroup.devices.allow = b 7:* rwm diff --git a/config/templates/debian.userns.conf.in b/config/templates/debian.userns.conf.in deleted file mode 100644 index 707bb30c0..000000000 --- a/config/templates/debian.userns.conf.in +++ /dev/null @@ -1,2 +0,0 @@ -# This derives from the global userns config -lxc.include = @LXCTEMPLATECONFIG@/userns.conf diff --git a/config/templates/fedora.common.conf.in b/config/templates/fedora.common.conf.in deleted file mode 100644 index acebe3c7c..000000000 --- a/config/templates/fedora.common.conf.in +++ /dev/null @@ -1,21 +0,0 @@ -# This derives from the global common config -lxc.include = @LXCTEMPLATECONFIG@/common.conf - -# Capabilities -# Uncomment these if you don't run anything that needs the capability, and -# would like the container to run with less privilege. -# -# Dropping sys_admin disables container root from doing a lot of things -# that could be bad like re-mounting lxc fstab entries rw for example, -# but also disables some useful things like being able to nfs mount, and -# things that are already namespaced with ns_capable() kernel checks, like -# hostname(1). -# lxc.cap.drop = sys_admin -# lxc.cap.drop = net_raw # breaks dhcp/ping -# lxc.cap.drop = setgid # breaks login (initgroups/setgroups) -# lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) -# lxc.cap.drop = setuid # breaks sshd,nfs statd -# lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) -# lxc.cap.drop = audit_write -# lxc.cap.drop = setpcap # big big login delays in Fedora 20 systemd -lxc.cap.drop = setfcap sys_nice sys_pacct sys_rawio diff --git a/config/templates/fedora.userns.conf.in b/config/templates/fedora.userns.conf.in deleted file mode 100644 index 707bb30c0..000000000 --- a/config/templates/fedora.userns.conf.in +++ /dev/null @@ -1,2 +0,0 @@ -# This derives from the global userns config -lxc.include = @LXCTEMPLATECONFIG@/userns.conf diff --git a/config/templates/gentoo.common.conf.in b/config/templates/gentoo.common.conf.in deleted file mode 100644 index 477a2abfb..000000000 --- a/config/templates/gentoo.common.conf.in +++ /dev/null @@ -1,27 +0,0 @@ -# This derives from the global common config -lxc.include = @LXCTEMPLATECONFIG@/common.conf - -# Gentoo common default configuration -# This is the most feature-full container configuration -# But security is not the goal. -# Looking for more security, see gentoo.moresecure.conf - -# Doesn't support consoles in /dev/lxc/ -lxc.tty.dir = - -# Extra cgroup device access -## rtc -lxc.cgroup.devices.allow = c 254:0 rm -## tun -lxc.cgroup.devices.allow = c 10:200 rwm -## hpet -lxc.cgroup.devices.allow = c 10:228 rwm -## kvm -lxc.cgroup.devices.allow = c 10:232 rwm -## To use loop devices, copy the following line to the container's -## configuration file (uncommented). -#lxc.cgroup.devices.allow = b 7:* rwm - -# /dev/shm needs to be mounted as tmpfs. It's needed by python (bug #496328) -# and possibly other packages. -lxc.mount.entry = none dev/shm tmpfs rw,nosuid,nodev,create=dir diff --git a/config/templates/gentoo.moresecure.conf.in b/config/templates/gentoo.moresecure.conf.in deleted file mode 100644 index aa7c625cc..000000000 --- a/config/templates/gentoo.moresecure.conf.in +++ /dev/null @@ -1,45 +0,0 @@ -# This derives from the global common config -lxc.include = @LXCTEMPLATECONFIG@/common.conf - -# Gentoo security oriented default configuration -# This is a more security oriented container configuration -# "More" because this is far from fully secure -# Looking for more working features and you trust your -# Container user ? see gentoo.common.conf - -# do not mount sysfs, see http://blog.bofh.it/debian/id_413 -lxc.mount.entry=mqueue dev/mqueue mqueue rw,nodev,noexec,nosuid,create=dir 0 0 -lxc.mount.entry=shm dev/shm tmpfs rw,nosuid,nodev,noexec,relatime,create=dir 0 0 -lxc.mount.entry=run run tmpfs rw,nosuid,nodev,relatime,mode=755 0 0 - -# Capabilities -# Uncomment these if you don't run anything that needs the capability, and -# would like the container to run with less privilege. -# -# Dropping sys_admin disables container root from doing a lot of things -# that could be bad like re-mounting lxc fstab entries rw for example, -# but also disables some useful things like being able to nfs mount, and -# things that are already namespaced with ns_capable() kernel checks, like -# hostname(1). -# lxc.cap.drop = sys_admin # breaks systemd -# lxc.cap.drop = net_raw # breaks dhcp/ping -# lxc.cap.drop = setgid # breaks login (initgroups/setgroups) -# lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) -# lxc.cap.drop = setuid # breaks sshd,nfs statd -# lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) -# lxc.cap.drop = audit_write -# lxc.cap.drop = setpcap # breaks journald -# lxc.cap.drop = sys_resource # breaks systemd -# lxc.cap.drop = sys_boot # breaks sysvinit -lxc.cap.drop = audit_control audit_write dac_read_search fsetid ipc_owner linux_immutable mknod setfcap setpcap sys_admin sys_nice sys_pacct sys_ptrace sys_rawio sys_resource sys_tty_config syslog - -# WARNING: the security vulnerability reported for 'cap_net_admin' at -# http://mainisusuallyafunction.blogspot.com/2012/11/attacking-hardened-linux-systems-with.html -# via JIT spraying (the BPF JIT module disabled on most systems was used -# in the example, but others are suggested vulnerable) meant that users -# with root in a container, that capability and kernel module may escape -# the container. ALWAYS be extremely careful granting any process root -# within a container, use a minimal configuration at all levels - -# including the kernel - and multiple layers of security on any system -# where security is a priority. note that not only LXC but PAX (and -# others?) were vulnerable to this issue. diff --git a/config/templates/gentoo.userns.conf.in b/config/templates/gentoo.userns.conf.in deleted file mode 100644 index 707bb30c0..000000000 --- a/config/templates/gentoo.userns.conf.in +++ /dev/null @@ -1,2 +0,0 @@ -# This derives from the global userns config -lxc.include = @LXCTEMPLATECONFIG@/userns.conf diff --git a/config/templates/opensuse.common.conf.in b/config/templates/opensuse.common.conf.in deleted file mode 100644 index b040e95d9..000000000 --- a/config/templates/opensuse.common.conf.in +++ /dev/null @@ -1,22 +0,0 @@ -# This derives from the global common config -lxc.include = @LXCTEMPLATECONFIG@/common.conf - -# Capabilities -# Uncomment these if you don't run anything that needs the capability, and -# would like the container to run with less privilege. -# -# Dropping sys_admin disables container root from doing a lot of things -# that could be bad like re-mounting lxc fstab entries rw for example, -# but also disables some useful things like being able to nfs mount, and -# things that are already namespaced with ns_capable() kernel checks, like -# hostname(1). -# lxc.cap.drop = sys_admin -# lxc.cap.drop = net_raw # breaks dhcp/ping -# lxc.cap.drop = setgid # breaks login (initgroups/setgroups) -# lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) -# lxc.cap.drop = setuid # breaks sshd,nfs statd -# lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) -# lxc.cap.drop = audit_write -# lxc.cap.drop = setpcap # big big login delays in Fedora 20 systemd -# lxc.cap.drop = setfcap -lxc.cap.drop = sys_nice sys_pacct sys_rawio diff --git a/config/templates/opensuse.userns.conf.in b/config/templates/opensuse.userns.conf.in deleted file mode 100644 index 707bb30c0..000000000 --- a/config/templates/opensuse.userns.conf.in +++ /dev/null @@ -1,2 +0,0 @@ -# This derives from the global userns config -lxc.include = @LXCTEMPLATECONFIG@/userns.conf diff --git a/config/templates/openwrt.common.conf.in b/config/templates/openwrt.common.conf.in deleted file mode 100644 index 73db6f60b..000000000 --- a/config/templates/openwrt.common.conf.in +++ /dev/null @@ -1,50 +0,0 @@ -# Default console settings -lxc.tty.dir = lxc -lxc.tty.max = 4 -lxc.pty.max = 1024 - -# Default capabilities -lxc.cap.drop = mac_admin -lxc.cap.drop = mac_override -lxc.cap.drop = sys_admin -lxc.cap.drop = sys_module -lxc.cap.drop = sys_nice -lxc.cap.drop = sys_pacct -lxc.cap.drop = sys_ptrace -lxc.cap.drop = sys_rawio -lxc.cap.drop = sys_resource -lxc.cap.drop = sys_time -lxc.cap.drop = sys_tty_config -lxc.cap.drop = syslog -lxc.cap.drop = wake_alarm - -# Default cgroups - all denied except those whitelisted -lxc.cgroup.devices.deny = a -## /dev/null and zero -lxc.cgroup.devices.allow = c 1:3 rwm -lxc.cgroup.devices.allow = c 1:5 rwm -## consoles -lxc.cgroup.devices.allow = c 5:0 rwm -lxc.cgroup.devices.allow = c 5:1 rwm -## /dev/{,u}random -lxc.cgroup.devices.allow = c 1:8 rwm -lxc.cgroup.devices.allow = c 1:9 rwm -## /dev/pts/* -lxc.cgroup.devices.allow = c 5:2 rwm -lxc.cgroup.devices.allow = c 136:* rwm -## rtc -lxc.cgroup.devices.allow = c 254:0 rm -## tun -lxc.cgroup.devices.allow = c 10:200 rwm -## dev/tty0 -lxc.cgroup.devices.allow = c 4:0 rwm -## dev/tty1 -lxc.cgroup.devices.allow = c 4:1 rwm - -## To use loop devices, copy the following line to the container's -## configuration file (uncommented). -#lxc.cgroup.devices.allow = b 7:* rwm - -# Blacklist some syscalls which are not safe in privileged -# containers -lxc.seccomp.profile = /usr/share/lxc/config/common.seccomp diff --git a/config/templates/oracle.common.conf.in b/config/templates/oracle.common.conf.in deleted file mode 100644 index 8a72ad003..000000000 --- a/config/templates/oracle.common.conf.in +++ /dev/null @@ -1,20 +0,0 @@ -# This derives from the global common config -lxc.include = @LXCTEMPLATECONFIG@/common.conf - -# Capabilities -# Uncomment these if you don't run anything that needs the capability, and -# would like the container to run with less privilege. -# -# Dropping sys_admin disables container root from doing a lot of things -# that could be bad like re-mounting lxc fstab entries rw for example, -# but also disables some useful things like being able to nfs mount, and -# things that are already namespaced with ns_capable() kernel checks, like -# hostname(1). -# lxc.cap.drop = sys_admin -# lxc.cap.drop = net_raw # breaks dhcp/ping -# lxc.cap.drop = setgid # breaks login (initgroups/setgroups) -# lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) -# lxc.cap.drop = setuid # breaks sshd,nfs statd -# lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) -# lxc.cap.drop = audit_write -lxc.cap.drop = sys_nice sys_pacct sys_rawio diff --git a/config/templates/oracle.userns.conf.in b/config/templates/oracle.userns.conf.in deleted file mode 100644 index 707bb30c0..000000000 --- a/config/templates/oracle.userns.conf.in +++ /dev/null @@ -1,2 +0,0 @@ -# This derives from the global userns config -lxc.include = @LXCTEMPLATECONFIG@/userns.conf diff --git a/config/templates/plamo.common.conf.in b/config/templates/plamo.common.conf.in deleted file mode 100644 index 7918b4a37..000000000 --- a/config/templates/plamo.common.conf.in +++ /dev/null @@ -1,9 +0,0 @@ -# This derives from the global common config -lxc.include = @LXCTEMPLATECONFIG@/common.conf - -# Doesn't support consoles in /dev/lxc/ -lxc.tty.dir = - -# Extra cgroup device access -## rtc -lxc.cgroup.devices.allow = c 254:0 rm diff --git a/config/templates/plamo.userns.conf.in b/config/templates/plamo.userns.conf.in deleted file mode 100644 index 707bb30c0..000000000 --- a/config/templates/plamo.userns.conf.in +++ /dev/null @@ -1,2 +0,0 @@ -# This derives from the global userns config -lxc.include = @LXCTEMPLATECONFIG@/userns.conf diff --git a/config/templates/sabayon.common.conf.in b/config/templates/sabayon.common.conf.in deleted file mode 100644 index ccb4c1236..000000000 --- a/config/templates/sabayon.common.conf.in +++ /dev/null @@ -1,79 +0,0 @@ -# Default configuration for Sabayon containers - -# Setup the default mounts -lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed - -# Allow for 1024 pseudo terminals -lxc.pty.max = 1024 - -# Setup 1 tty devices for lxc-console command -lxc.tty.max = 1 - -# Needed for systemd distro -lxc.autodev = 1 - -# Doesn't support consoles in /dev/lxc/ -lxc.tty.dir = - -# CGroup whitelist -lxc.cgroup.devices.deny = a - -## Allow any mknod (but not reading/writing the node) -#lxc.cgroup.devices.allow = c *:* m -#lxc.cgroup.devices.allow = b *:* m - -## Allow specific devices -### /dev/null -lxc.cgroup.devices.allow = c 1:3 rwm -### /dev/zero -lxc.cgroup.devices.allow = c 1:5 rwm -### /dev/full -lxc.cgroup.devices.allow = c 1:7 rwm -### /dev/random -lxc.cgroup.devices.allow = c 1:8 rwm -### /dev/urandom -lxc.cgroup.devices.allow = c 1:9 rwm -### /dev/pts/* -#lxc.cgroup.devices.allow = c 136:* rwm -### /dev/tty -#lxc.cgroup.devices.allow = c 5:0 rwm -### /dev/console -#lxc.cgroup.devices.allow = c 5:1 rwm -### /dev/ptmx -#lxc.cgroup.devices.allow = c 5:2 rwm -### fuse -#lxc.cgroup.devices.allow = c 10:229 rwm -## To use loop devices, copy the following line to the container's -## configuration file (uncommented). -#lxc.cgroup.devices.allow = b 7:* rwm -## rtc -#lxc.cgroup.devices.allow = c 254:0 rm -## tun -#lxc.cgroup.devices.allow = c 10:200 rwm -## hpet -#lxc.cgroup.devices.allow = c 10:228 rwm -## kvm -#lxc.cgroup.devices.allow = c 10:232 rwm -## /dev/mem -#lxc.cgroup.devices.allow = c 1:1 rwm - -# If something doesn't work, try to comment this out. -# Dropping sys_admin disables container root from doing a lot of things -# that could be bad like re-mounting lxc fstab entries rw for example, -# but also disables some useful things like being able to nfs mount, and -# things that are already namespaced with ns_capable() kernel checks, like -# hostname(1). -lxc.cap.drop = sys_time sys_module sys_rawio mac_admin mac_override -#lxc.cap.drop = sys_admin - - -# /dev/shm needs to be mounted as tmpfs. It's needed by python (bug #496328) -# and possibly other packages. -lxc.mount.entry = none dev/shm tmpfs rw,nosuid,nodev,create=dir - -# Blacklist some syscalls which are not safe in privileged -# containers -lxc.seccomp.profile = @LXCTEMPLATECONFIG@/common.seccomp - -# Customize lxc options through common directory -lxc.include = @LXCTEMPLATECONFIG@/common.conf.d/ diff --git a/config/templates/sabayon.userns.conf.in b/config/templates/sabayon.userns.conf.in deleted file mode 100644 index 707bb30c0..000000000 --- a/config/templates/sabayon.userns.conf.in +++ /dev/null @@ -1,2 +0,0 @@ -# This derives from the global userns config -lxc.include = @LXCTEMPLATECONFIG@/userns.conf diff --git a/config/templates/slackware.common.conf.in b/config/templates/slackware.common.conf.in deleted file mode 100644 index 899c52ce3..000000000 --- a/config/templates/slackware.common.conf.in +++ /dev/null @@ -1,46 +0,0 @@ -# This derives from the global common config -lxc.include = @LXCTEMPLATECONFIG@/common.conf - -# Doesn't support consoles in /dev/lxc/ -lxc.tty.dir = - -# Extra cgroup device access -## rtc -lxc.cgroup.devices.allow = c 254:0 rm -## tun -lxc.cgroup.devices.allow = c 10:200 rwm -## hpet -lxc.cgroup.devices.allow = c 10:228 rwm -## kvm -lxc.cgroup.devices.allow = c 10:232 rwm -## To use loop devices, copy the following line to the container's -## configuration file (uncommented). -#lxc.cgroup.devices.allow = b 7:* rwm - -# mount /dev/shm as tmpfs -lxc.mount.entry = none dev/shm tmpfs rw,nosuid,nodev,create=dir - -# Capabilities -# Uncomment these if you don't run anything that needs the capability, and -# would like the container to run with less privilege. -# Note that some are already dropped in common.conf. -# -# Dropping sys_admin disables container root from doing a lot of things -# that could be bad like re-mounting lxc fstab entries rw for example, -# but also disables some useful things like being able to nfs mount, and -# things that are already namespaced with ns_capable() kernel checks, like -# hostname(1). -# -# Some of these don't apply in Slackware but are here for future reference. -# -# lxc.cap.drop = sys_admin # breaks systemd -# lxc.cap.drop = net_raw # breaks dhcp/ping -# lxc.cap.drop = setgid # breaks login (initgroups/setgroups) -# lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) -# lxc.cap.drop = setuid # breaks sshd,nfs statd -# lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) -# lxc.cap.drop = audit_write -# lxc.cap.drop = setpcap # breaks journald -# lxc.cap.drop = sys_resource # breaks systemd -# -lxc.cap.drop = mknod setfcap setpcap diff --git a/config/templates/slackware.userns.conf.in b/config/templates/slackware.userns.conf.in deleted file mode 100644 index 707bb30c0..000000000 --- a/config/templates/slackware.userns.conf.in +++ /dev/null @@ -1,2 +0,0 @@ -# This derives from the global userns config -lxc.include = @LXCTEMPLATECONFIG@/userns.conf diff --git a/config/templates/sparclinux.common.conf.in b/config/templates/sparclinux.common.conf.in deleted file mode 100644 index 8a72ad003..000000000 --- a/config/templates/sparclinux.common.conf.in +++ /dev/null @@ -1,20 +0,0 @@ -# This derives from the global common config -lxc.include = @LXCTEMPLATECONFIG@/common.conf - -# Capabilities -# Uncomment these if you don't run anything that needs the capability, and -# would like the container to run with less privilege. -# -# Dropping sys_admin disables container root from doing a lot of things -# that could be bad like re-mounting lxc fstab entries rw for example, -# but also disables some useful things like being able to nfs mount, and -# things that are already namespaced with ns_capable() kernel checks, like -# hostname(1). -# lxc.cap.drop = sys_admin -# lxc.cap.drop = net_raw # breaks dhcp/ping -# lxc.cap.drop = setgid # breaks login (initgroups/setgroups) -# lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) -# lxc.cap.drop = setuid # breaks sshd,nfs statd -# lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) -# lxc.cap.drop = audit_write -lxc.cap.drop = sys_nice sys_pacct sys_rawio diff --git a/config/templates/sparclinux.userns.conf.in b/config/templates/sparclinux.userns.conf.in deleted file mode 100644 index 707bb30c0..000000000 --- a/config/templates/sparclinux.userns.conf.in +++ /dev/null @@ -1,2 +0,0 @@ -# This derives from the global userns config -lxc.include = @LXCTEMPLATECONFIG@/userns.conf diff --git a/config/templates/ubuntu-cloud.common.conf.in b/config/templates/ubuntu-cloud.common.conf.in deleted file mode 100644 index 4d6772299..000000000 --- a/config/templates/ubuntu-cloud.common.conf.in +++ /dev/null @@ -1,4 +0,0 @@ -# This derives from the main Ubuntu config -lxc.include = @LXCTEMPLATECONFIG@/ubuntu.common.conf - -lxc.hook.clone = @LXCHOOKDIR@/ubuntu-cloud-prep diff --git a/config/templates/ubuntu-cloud.lucid.conf.in b/config/templates/ubuntu-cloud.lucid.conf.in deleted file mode 100644 index 78205e5f2..000000000 --- a/config/templates/ubuntu-cloud.lucid.conf.in +++ /dev/null @@ -1,2 +0,0 @@ -# This derives from the main Ubuntu lucid config -lxc.include = @LXCTEMPLATECONFIG@/ubuntu.lucid.conf diff --git a/config/templates/ubuntu-cloud.userns.conf.in b/config/templates/ubuntu-cloud.userns.conf.in deleted file mode 100644 index e1baca8eb..000000000 --- a/config/templates/ubuntu-cloud.userns.conf.in +++ /dev/null @@ -1,2 +0,0 @@ -# This derives from the main Ubuntu userns config -lxc.include = @LXCTEMPLATECONFIG@/ubuntu.userns.conf diff --git a/config/templates/ubuntu.common.conf.in b/config/templates/ubuntu.common.conf.in deleted file mode 100644 index ff8ef6a8f..000000000 --- a/config/templates/ubuntu.common.conf.in +++ /dev/null @@ -1,35 +0,0 @@ -# This derives from the global common config -lxc.include = @LXCTEMPLATECONFIG@/common.conf - -# Default mount entries -lxc.mount.entry = /sys/kernel/debug sys/kernel/debug none bind,optional 0 0 -lxc.mount.entry = /sys/kernel/security sys/kernel/security none bind,optional 0 0 -lxc.mount.entry = /sys/fs/pstore sys/fs/pstore none bind,optional 0 0 -lxc.mount.entry = mqueue dev/mqueue mqueue rw,relatime,create=dir,optional 0 0 - -# When using LXC with apparmor, the container will be confined by default. -# If you wish for it to instead run unconfined, copy the following line -# (uncommented) to the container's configuration file. -#lxc.apparmor.profile = unconfined - -# Uncomment the following line to autodetect squid-deb-proxy configuration on the -# host and forward it to the guest at start time. -#lxc.hook.pre-start = /usr/share/lxc/hooks/squid-deb-proxy-client - -# If you wish to allow mounting block filesystems, then use the following -# line instead, and make sure to grant access to the block device and/or loop -# devices below in lxc.cgroup.devices.allow. -#lxc.apparmor.profile = lxc-container-default-with-mounting - -# Extra cgroup device access -## rtc -lxc.cgroup.devices.allow = c 254:0 rm -## tun -lxc.cgroup.devices.allow = c 10:200 rwm -## hpet -lxc.cgroup.devices.allow = c 10:228 rwm -## kvm -lxc.cgroup.devices.allow = c 10:232 rwm -## To use loop devices, copy the following line to the container's -## configuration file (uncommented). -#lxc.cgroup.devices.allow = b 7:* rwm diff --git a/config/templates/ubuntu.lucid.conf.in b/config/templates/ubuntu.lucid.conf.in deleted file mode 100644 index b6fe37c97..000000000 --- a/config/templates/ubuntu.lucid.conf.in +++ /dev/null @@ -1,2 +0,0 @@ -# Ubuntu 10.04 LTS doesn't have /dev/lxc/ -lxc.tty.dir = diff --git a/config/templates/ubuntu.userns.conf.in b/config/templates/ubuntu.userns.conf.in deleted file mode 100644 index 0d73464cd..000000000 --- a/config/templates/ubuntu.userns.conf.in +++ /dev/null @@ -1,6 +0,0 @@ -# This derives from the global userns config -lxc.include = @LXCTEMPLATECONFIG@/userns.conf - -# Extra fstab entries as mountall can't mount those by itself -lxc.mount.entry = /sys/firmware/efi/efivars sys/firmware/efi/efivars none bind,optional 0 0 -lxc.mount.entry = /proc/sys/fs/binfmt_misc proc/sys/fs/binfmt_misc none bind,optional 0 0 diff --git a/config/templates/voidlinux.common.conf.in b/config/templates/voidlinux.common.conf.in deleted file mode 100644 index c287b45c5..000000000 --- a/config/templates/voidlinux.common.conf.in +++ /dev/null @@ -1,35 +0,0 @@ -# This derives from the global common config -lxc.include = @LXCTEMPLATECONFIG@/common.conf - -# Allow for 6 tty devices by default -lxc.tty.max = 6 - -# Set $VIRTUALIZATION so runit doesn't try to mount filesystems or start udevd -lxc.environment=VIRTUALIZATION=lxc - -# Set the halt/stop signals -lxc.signal.halt=SIGCONT - - -# Uncomment to disable creating tty devices subdirectory in /dev -# lxc.tty.dir = - -# Capabilities -# Uncomment these if you don't run anything that needs the capability, and -# would like the container to run with less privilege. -# -# Dropping sys_admin disables container root from doing a lot of things -# that could be bad like re-mounting lxc fstab entries rw for example, -# but also disables some useful things like being able to nfs mount, and -# things that are already namespaced with ns_capable() kernel checks, like -# hostname(1). -# lxc.cap.drop = sys_admin -# lxc.cap.drop = net_raw # breaks dhcp/ping -# lxc.cap.drop = setgid # breaks login (initgroups/setgroups) -# lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) -# lxc.cap.drop = setuid # breaks sshd,nfs statd -# lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) -# lxc.cap.drop = audit_write -# lxc.cap.drop = setpcap # big big login delays in Fedora 20 systemd -# -lxc.cap.drop = setfcap sys_nice sys_pacct sys_rawio diff --git a/config/templates/voidlinux.userns.conf.in b/config/templates/voidlinux.userns.conf.in deleted file mode 100644 index f319bc546..000000000 --- a/config/templates/voidlinux.userns.conf.in +++ /dev/null @@ -1,8 +0,0 @@ -# This derives from the global userns config -lxc.include = @LXCTEMPLATECONFIG@/userns.conf - -# Set $VIRTUALIZATION so runit doesn't try to mount filesystems or start udevd -lxc.environment=VIRTUALIZATION=lxc - -# Set the halt/stop signals -lxc.signal.halt=SIGCONT diff --git a/configure.ac b/configure.ac index a4de1f29b..571aa6071 100644 --- a/configure.ac +++ b/configure.ac @@ -666,44 +666,10 @@ AC_CONFIG_FILES([ config/init/upstart/Makefile config/etc/Makefile config/templates/Makefile - config/templates/alpine.common.conf - config/templates/alpine.userns.conf - config/templates/archlinux.common.conf - config/templates/archlinux.userns.conf - config/templates/centos.common.conf - config/templates/centos.userns.conf config/templates/common.conf config/templates/common.conf.d/Makefile - config/templates/debian.common.conf - config/templates/debian.userns.conf - config/templates/fedora.common.conf - config/templates/fedora.userns.conf - config/templates/gentoo.common.conf - config/templates/gentoo.moresecure.conf - config/templates/gentoo.userns.conf config/templates/nesting.conf config/templates/oci.common.conf - config/templates/opensuse.common.conf - config/templates/opensuse.userns.conf - config/templates/oracle.common.conf - config/templates/oracle.userns.conf - config/templates/plamo.common.conf - config/templates/plamo.userns.conf - config/templates/slackware.common.conf - config/templates/slackware.userns.conf - config/templates/ubuntu-cloud.common.conf - config/templates/ubuntu-cloud.lucid.conf - config/templates/ubuntu-cloud.userns.conf - config/templates/ubuntu.common.conf - config/templates/ubuntu.lucid.conf - config/templates/ubuntu.userns.conf - config/templates/openwrt.common.conf - config/templates/sparclinux.common.conf - config/templates/sparclinux.userns.conf - config/templates/voidlinux.common.conf - config/templates/voidlinux.userns.conf - config/templates/sabayon.common.conf - config/templates/sabayon.userns.conf config/templates/userns.conf config/yum/Makefile config/sysconfig/Makefile @@ -832,31 +798,10 @@ AC_CONFIG_FILES([ hooks/dhclient templates/Makefile - templates/lxc-alpine - templates/lxc-altlinux - templates/lxc-archlinux templates/lxc-busybox - templates/lxc-centos - templates/lxc-cirros - templates/lxc-debian templates/lxc-download - templates/lxc-fedora - templates/lxc-fedora-legacy - templates/lxc-gentoo templates/lxc-local templates/lxc-oci - templates/lxc-openmandriva - templates/lxc-opensuse - templates/lxc-oracle - templates/lxc-plamo - templates/lxc-pld - templates/lxc-slackware - templates/lxc-sshd - templates/lxc-ubuntu - templates/lxc-ubuntu-cloud - templates/lxc-sparclinux - templates/lxc-voidlinux - templates/lxc-sabayon src/Makefile src/lxc/Makefile diff --git a/templates/Makefile.am b/templates/Makefile.am index 63abdf6fb..15df51dff 100644 --- a/templates/Makefile.am +++ b/templates/Makefile.am @@ -1,28 +1,6 @@ templatesdir=@LXCTEMPLATEDIR@ -templates_SCRIPTS = \ - lxc-alpine \ - lxc-altlinux \ - lxc-archlinux \ - lxc-busybox \ - lxc-centos \ - lxc-cirros \ - lxc-debian \ - lxc-download \ - lxc-fedora \ - lxc-fedora-legacy \ - lxc-gentoo \ - lxc-local \ - lxc-oci \ - lxc-openmandriva \ - lxc-opensuse \ - lxc-oracle \ - lxc-plamo \ - lxc-pld \ - lxc-slackware \ - lxc-sshd \ - lxc-ubuntu \ - lxc-ubuntu-cloud \ - lxc-sparclinux \ - lxc-voidlinux \ - lxc-sabayon +templates_SCRIPTS = lxc-busybox \ + lxc-download \ + lxc-local \ + lxc-oci diff --git a/templates/lxc-alpine.in b/templates/lxc-alpine.in deleted file mode 100644 index 174c36815..000000000 --- a/templates/lxc-alpine.in +++ /dev/null @@ -1,516 +0,0 @@ -#!/bin/sh -# vim: set ts=4: - -# Exit on error and treat unset variables as an error. -set -eu - -# -# LXC template for Alpine Linux 3+ -# - -# Note: Do not replace tabs with spaces, it would break heredocs! - -# Authors: -# Jakub Jirutka - -# 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 - - -#=========================== Constants ============================# - -# Make sure the usual locations are in PATH -export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin - -readonly LOCAL_STATE_DIR='@LOCALSTATEDIR@' -readonly LXC_TEMPLATE_CONFIG='@LXCTEMPLATECONFIG@' -readonly LXC_CACHE_DIR="${LXC_CACHE_PATH:-"$LOCAL_STATE_DIR/cache/lxc"}/alpine" - -# SHA256 checksums of GPG keys for APK. -readonly APK_KEYS_SHA256="\ -9c102bcc376af1498d549b77bdbfa815ae86faa1d2d82f040e616b18ef2df2d4 alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub -2adcf7ce224f476330b5360ca5edb92fd0bf91c92d83292ed028d7c4e26333ab alpine-devel@lists.alpinelinux.org-4d07755e.rsa.pub -ebf31683b56410ecc4c00acd9f6e2839e237a3b62b5ae7ef686705c7ba0396a9 alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub -1bb2a846c0ea4ca9d0e7862f970863857fc33c32f5506098c636a62a726a847b alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub -12f899e55a7691225603d6fb3324940fc51cd7f133e7ead788663c2b7eecb00c alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub -73867d92083f2f8ab899a26ccda7ef63dfaa0032a938620eda605558958a8041 alpine-devel@lists.alpinelinux.org-58199dcc.rsa.pub -9a4cd858d9710963848e6d5f555325dc199d1c952b01cf6e64da2c15deedbd97 alpine-devel@lists.alpinelinux.org-58cbb476.rsa.pub -780b3ed41786772cbc7b68136546fa3f897f28a23b30c72dde6225319c44cfff alpine-devel@lists.alpinelinux.org-58e4f17d.rsa.pub" - -readonly APK_KEYS_URI='http://alpinelinux.org/keys' -readonly DEFAULT_MIRROR_URL='http://dl-cdn.alpinelinux.org/alpine' - -: ${APK_KEYS_DIR:=/etc/apk/keys} -if ! ls "$APK_KEYS_DIR"/alpine* >/dev/null 2>&1; then - APK_KEYS_DIR="$LXC_CACHE_DIR/bootstrap/keys" -fi -readonly APK_KEYS_DIR - -: ${APK:=$(command -v apk || true)} -if [ ! -x "$APK" ]; then - APK="$LXC_CACHE_DIR/bootstrap/sbin/apk.static" -fi -readonly APK - - -#======================== Helper Functions ========================# - -usage() { - cat <<-EOF - Template specific options can be passed to lxc-create after a '--' like this: - - lxc-create --name=NAME [lxc-create-options] -- [template-options] [PKG...] - - PKG Additional APK package(s) to install into the container. - - Template options: - -a ARCH, --arch=ARCH The container architecture (e.g. x86, x86_64); defaults - to the host arch. - -d, --debug Run this script in a debug mode (set -x and wget w/o -q). - -F, --flush-cache Remove cached files before build. - -m URL --mirror=URL The Alpine mirror to use; defaults to $DEFAULT_MIRROR_URL. - -r VER, --release=VER The Alpine release branch to install; default is the - latest stable. - - Environment variables: - APK The apk-tools binary to use when building rootfs. If not set - or not executable and apk is not on PATH, then the script - will download the latest apk-tools-static. - APK_KEYS_DIR Path to directory with GPG keys for APK. If not set and - /etc/apk/keys does not contain alpine keys, then the script - will download the keys from ${APK_KEYS_URI}. - LXC_CACHE_PATH Path to the cache directory where to store bootstrap files - and APK packages. - EOF -} - -die() { - local retval=$1; shift - - printf 'ERROR: %s\n' "$@" 1>&2 - exit $retval -} - -einfo() { - printf "\n==> $1\n" -} - -fetch() { - if [ "$DEBUG" = 'yes' ]; then - wget -T 10 -O - $@ - else - wget -T 10 -O - -q $@ - fi -} - -latest_release_branch() { - local arch="$1" - local branch=$(fetch "$MIRROR_URL/latest-stable/releases/$arch/latest-releases.yaml" \ - | sed -En 's/^[ \t]*branch: (.*)$/\1/p' \ - | head -n 1) - [ -n "$branch" ] && echo "$branch" -} - -parse_arch() { - case "$1" in - x86 | i[3-6]86) echo 'x86';; - x86_64 | amd64) echo 'x86_64';; - aarch64 | arm64) echo 'aarch64';; - armv7) echo 'armv7';; - arm*) echo 'armhf';; - ppc64le) echo 'ppc64le';; - *) return 1;; - esac -} - -run_exclusively() { - local lock_name="$1" - local timeout=$2 - shift 2 - - mkdir -p "$LOCAL_STATE_DIR/lock/subsys" - - local retval - { - echo -n "Obtaining an exclusive lock..." - if ! flock -x 9; then - echo ' failed.' - return 1 - fi - echo ' done' - - "$@"; retval=$? - } 9> "$LOCAL_STATE_DIR/lock/subsys/lxc-alpine-$lock_name" - - return $retval -} - - -#============================ Bootstrap ===========================# - -bootstrap() { - if [ "$FLUSH_CACHE" = 'yes' ] && [ -d "$LXC_CACHE_DIR/bootstrap" ]; then - einfo 'Cleaning cached bootstrap files' - rm -Rf "$LXC_CACHE_DIR/bootstrap" - fi - - einfo 'Fetching and/or verifying APK keys' - fetch_apk_keys "$APK_KEYS_DIR" - - if [ ! -x "$APK" ]; then - einfo 'Fetching apk-tools static binary' - - local host_arch=$(parse_arch $(uname -m)) - fetch_apk_static "$LXC_CACHE_DIR/bootstrap" "$host_arch" - fi -} - -fetch_apk_keys() { - local dest="$1" - local line keyname - - mkdir -p "$dest" - cd "$dest" - - echo "$APK_KEYS_SHA256" | while read -r line; do - keyname="${line##* }" - if [ ! -s "$keyname" ]; then - fetch "$APK_KEYS_URI/$keyname" > "$keyname" - fi - echo "$line" | sha256sum -c - - done || exit 2 - - cd - >/dev/null -} - -fetch_apk_static() { - local dest="$1" - local arch="$2" - local pkg_name='apk-tools-static' - - mkdir -p "$dest" - - local pkg_ver=$(fetch "$MIRROR_URL/latest-stable/main/$arch/APKINDEX.tar.gz" \ - | tar -xzO APKINDEX \ - | sed -n "/P:${pkg_name}/,/^$/ s/V:\(.*\)$/\1/p") - - [ -n "$pkg_ver" ] || die 2 "Cannot find a version of $pkg_name in APKINDEX" - - fetch "$MIRROR_URL/latest-stable/main/$arch/${pkg_name}-${pkg_ver}.apk" \ - | tar -xz -C "$dest" sbin/ # --extract --gzip --directory - - [ -s "$dest/sbin/apk.static" ] || die 2 'apk.static not found' - - local keyname=$(echo "$dest"/sbin/apk.static.*.pub | sed 's/.*\.SIGN\.RSA\.//') - openssl dgst -sha1 \ - -verify "$APK_KEYS_DIR/$keyname" \ - -signature "$dest/sbin/apk.static.SIGN.RSA.$keyname" \ - "$dest/sbin/apk.static" \ - || die 2 'Signature verification for apk.static failed' - - # Note: apk doesn't return 0 for --version - local out="$("$dest"/sbin/apk.static --version)" - echo "$out" - - [ "${out%% *}" = 'apk-tools' ] || die 3 'apk.static --version failed' -} - - -#============================ Install ============================# - -install() { - local dest="$1" - local arch="$2" - local branch="$3" - local extra_packages="$4" - local apk_cache="$LXC_CACHE_DIR/apk/$arch" - - if [ "$FLUSH_CACHE" = 'yes' ] && [ -d "$apk_cache" ]; then - einfo "Cleaning cached APK packages for $arch" - rm -Rf "$apk_cache" - fi - mkdir -p "$apk_cache" - - einfo "Installing Alpine Linux in $dest" - cd "$dest" - - mkdir -p etc/apk - ln -s "$apk_cache" etc/apk/cache - - local repo; for repo in main community; do - echo "$MIRROR_URL/$branch/$repo" >> etc/apk/repositories - done - - install_packages "$arch" "alpine-base $extra_packages" - make_dev_nodes - setup_inittab - setup_hosts - setup_network - setup_services - - chroot . /bin/true \ - || die 3 'Failed to execute /bin/true in chroot, the builded rootfs is broken!' - - rm etc/apk/cache - cd - >/dev/null -} - -install_packages() { - local arch="$1" - local packages="$2" - - $APK --arch="$arch" --root=. --keys-dir="$APK_KEYS_DIR" \ - --update-cache --initdb add $packages -} - -make_dev_nodes() { - mkdir -p -m 755 dev/pts - mkdir -p -m 1777 dev/shm - - mknod -m 666 dev/zero c 1 5 - mknod -m 666 dev/full c 1 7 - mknod -m 666 dev/random c 1 8 - mknod -m 666 dev/urandom c 1 9 - - local i; for i in $(seq 0 4); do - mknod -m 620 dev/tty$i c 4 $i - chown 0:5 dev/tty$i # root:tty - done - - mknod -m 666 dev/tty c 5 0 - chown 0:5 dev/tty # root:tty - mknod -m 620 dev/console c 5 1 - mknod -m 666 dev/ptmx c 5 2 - chown 0:5 dev/ptmx # root:tty -} - -setup_inittab() { - # Remove unwanted ttys. - sed -i '/^tty[5-9]\:\:.*$/d' etc/inittab - - cat <<-EOF >> etc/inittab - # Main LXC console console - ::respawn:/sbin/getty 38400 console - EOF -} - -setup_hosts() { - # This runscript injects localhost entries with the current hostname - # into /etc/hosts. - cat <<'EOF' > etc/init.d/hosts -#!/sbin/openrc-run - -start() { - local start_tag='# begin generated' - local end_tag='# end generated' - - local content=$( - cat <<-EOF - $start_tag by /etc/init.d/hosts - 127.0.0.1 $(hostname).local $(hostname) localhost - ::1 $(hostname).local $(hostname) localhost - $end_tag - EOF - ) - - if grep -q "^${start_tag}" /etc/hosts; then - # escape \n, busybox sed doesn't like them - content=${content//$'\n'/\\$'\n'} - - sed -ni "/^${start_tag}/ { - a\\${content} - # read and discard next line and repeat until $end_tag or EOF - :a; n; /^${end_tag}/!ba; n - }; p" /etc/hosts - else - printf "$content" >> /etc/hosts - fi -} -EOF - chmod +x etc/init.d/hosts - - # Wipe it, will be generated by the above runscript. - echo -n > etc/hosts -} - -setup_network() { - # Note: loopback is automatically started by LXC. - cat <<-EOF > etc/network/interfaces - auto eth0 - iface eth0 inet dhcp - hostname \$(hostname) - EOF -} - -setup_services() { - local svc_name - - # Specify the LXC subsystem. - sed -i 's/^#*rc_sys=.*/rc_sys="lxc"/' etc/rc.conf - - # boot runlevel - for svc_name in bootmisc hosts syslog; do - ln -s /etc/init.d/$svc_name etc/runlevels/boot/$svc_name - done - - # default runlevel - for svc_name in networking cron crond; do - # issue 1164: alpine renamed cron to crond - # Use the one that exists. - if [ -e etc/init.d/$svc_name ]; then - ln -s /etc/init.d/$svc_name etc/runlevels/default/$svc_name - fi - done -} - - -#=========================== Configure ===========================# - -configure_container() { - local config="$1" - local hostname="$2" - local arch="$3" - - cat <<-EOF >> "$config" - - # Specify container architecture. - lxc.arch = $arch - - # Set hostname. - lxc.uts.name = $hostname - - # If something doesn't work, try to comment this out. - # Dropping sys_admin disables container root from doing a lot of things - # that could be bad like re-mounting lxc fstab entries rw for example, - # but also disables some useful things like being able to nfs mount, and - # things that are already namespaced with ns_capable() kernel checks, like - # hostname(1). - lxc.cap.drop = sys_admin - - # Comment this out if you have to debug processes by tracing. - lxc.cap.drop = sys_ptrace - - # Include common configuration. - lxc.include = $LXC_TEMPLATE_CONFIG/alpine.common.conf - EOF -} - - -#============================= Main ==============================# - -if [ "$(id -u)" != "0" ]; then - die 1 "This script must be run as 'root'" -fi - -# Parse command options. -options=$(getopt -o a:dFm:n:p:r:h -l arch:,debug,flush-cache,mirror:,name:,\ -path:,release:,rootfs:,help,mapped-uid:,mapped-gid: -- "$@") -eval set -- "$options" - -# Clean variables and set defaults. -arch="$(uname -m)" -debug='no' -flush_cache='no' -mirror_url= -name= -path= -release= -rootfs= - -# Process command options. -while [ $# -gt 0 ]; do - case $1 in - -a | --arch) - arch=$2; shift 2 - ;; - -d | --debug) - debug='yes'; shift 1 - ;; - -F | --flush-cache) - flush_cache='yes'; shift 1 - ;; - -m | --mirror) - mirror_url=$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 - ;; - -h | --help) - usage; exit 0 - ;; - --) - shift; break - ;; - --mapped-[ug]id) - die 1 "This template can't be used for unprivileged containers." \ - 'You may want to try the "download" template instead.' - ;; - *) - echo "Unknown option: $1" 1>&2 - usage; exit 1 - ;; - esac -done - -extra_packages="$@" - -[ "$debug" = 'yes' ] && set -x - -# Set global variables. -readonly DEBUG="$debug" -readonly FLUSH_CACHE="$flush_cache" -readonly MIRROR_URL="${mirror_url:-$DEFAULT_MIRROR_URL}" - -# Validate options. -[ -n "$name" ] || die 1 'Missing required option --name' -[ -n "$path" ] || die 1 'Missing required option --path' - -if [ -z "$rootfs" ] && [ -f "$path/config" ]; then - rootfs="$(sed -nE 's/^lxc.rootfs.path\s*=\s*(.*)$/\1/p' "$path/config")" -fi -if [ -z "$rootfs" ]; then - rootfs="$path/rootfs" -fi - -arch=$(parse_arch "$arch") \ - || die 1 "Unsupported architecture: $arch" - -if [ -z "$release" ]; then - release=$(latest_release_branch "$arch") \ - || die 2 'Failed to resolve Alpine last release branch' -fi - -# Here we go! -run_exclusively 'bootstrap' 10 bootstrap -run_exclusively "$arch" 30 install "$rootfs" "$arch" "$release" "$extra_packages" -configure_container "$path/config" "$name" "$arch" - -einfo "Container's rootfs and config have been created" -cat <<-EOF - Edit the config file $path/config to check/enable networking setup. - The installed system is preconfigured for a loopback and single network - interface configured via DHCP. - - To start the container, run "lxc-start -n $name". - The root password is not set; to enter the container run "lxc-attach -n $name". -EOF diff --git a/templates/lxc-altlinux.in b/templates/lxc-altlinux.in deleted file mode 100644 index d526fa096..000000000 --- a/templates/lxc-altlinux.in +++ /dev/null @@ -1,498 +0,0 @@ -#!/bin/bash - -# -# template script for generating altlinux container for LXC -# - -# -# lxc: linux Container library - -# Authors: -# Alexey Shabalin - -# 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 - -# 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 - -#Configurations -arch=$(uname -m) -cache_base=@LOCALSTATEDIR@/cache/lxc/altlinux/$arch -default_path=@LXCPATH@ -default_profile=default -profile_dir=/etc/lxc/profiles -lxc_network_type=veth -lxc_network_link=virbr0 - -# is this altlinux? -[ -f /etc/altlinux-release ] && is_altlinux=true - -configure_altlinux() -{ - - # disable selinux in altlinux - mkdir -p $rootfs_path/selinux - echo 0 > $rootfs_path/selinux/enforce - - mkdir -p ${rootfs_path}/etc/net/ifaces/eth0 - cat < ${rootfs_path}/etc/net/ifaces/eth0/options -BOOTPROTO=${BOOTPROTO} -ONBOOT=yes -NM_CONTROLLED=yes -TYPE=eth -EOF - -if [ ${BOOTPROTO} != "dhcp" ]; then - # ip address - cat < ${rootfs_path}/etc/net/ifaces/eth0/ipv4address -${ipv4} -EOF - - cat < ${rootfs_path}/etc/net/ifaces/eth0/ipv4route -${gw} -EOF - - cat < ${rootfs_path}/etc/net/ifaces/eth0/resolv.conf -nameserver ${dns} -EOF - - cat < ${rootfs_path}/etc/net/ifaces/eth0/ipv6address -${ipv6} -EOF - - cat < ${rootfs_path}/etc/net/ifaces/eth0/ipv6route -${gw6} -EOF - -fi - - # set the hostname - cat < ${rootfs_path}/etc/sysconfig/network -NETWORKING=yes -CONFMETHOD=etcnet -HOSTNAME=${UTSNAME} -RESOLV_MODS=yes -EOF - - # set minimal hosts - cat < $rootfs_path/etc/hosts -127.0.0.1 localhost.localdomain localhost $name -EOF - # Allow to login at virsh console. loginuid.so doen't work in the absence of auditd. -# sed -i 's/^.*loginuid.so.*$/\#&/' ${rootfs_path}/etc/pam.d/common-login - - # Allow root to login at virsh console - echo "pts/0" >> ${rootfs_path}/etc/securetty - echo "console" >> ${rootfs_path}/etc/securetty - - # Enable services - for service in network syslogd random NetworkManager - do - chroot ${rootfs_path} chkconfig $service --list &>/dev/null && chroot ${rootfs_path} chkconfig $service on || true - # For systemd - chroot ${rootfs_path} systemctl -q enable $service &>/dev/null|| true - done - # Disable services - for service in rawdevices fbsetfont - do - chroot ${rootfs_path} chkconfig $service --list &>/dev/null && chroot ${rootfs_path} chkconfig $service off || true - chroot ${rootfs_path} systemctl -q disable $service &>/dev/null || true - done - - subst 's/^\([3-9]\+:[0-9]\+:respawn:\/sbin\/mingetty.*\)/#\1/' ${rootfs_path}/etc/inittab - echo "c1:2345:respawn:/sbin/mingetty --noclear console" >> ${rootfs_path}/etc/inittab - - [ -f "${rootfs_path}/etc/syslog.conf" ] && \ - subst 's,\/dev\/tty12,/var/log/syslog/console,' ${rootfs_path}/etc/syslog.conf - - dev_path="${rootfs_path}/dev" - rm -rf ${dev_path} - mkdir -p ${dev_path} - mknod -m 666 ${dev_path}/null c 1 3 - mknod -m 666 ${dev_path}/zero c 1 5 - mknod -m 644 ${dev_path}/random c 1 8 - mknod -m 644 ${dev_path}/urandom c 1 9 - mkdir -m 755 ${dev_path}/pts - mkdir -m 1777 ${dev_path}/shm - mknod -m 666 ${dev_path}/tty c 5 0 - chown root:tty ${dev_path}/tty - mknod -m 600 ${dev_path}/tty0 c 4 0 - mknod -m 600 ${dev_path}/tty1 c 4 1 - mknod -m 600 ${dev_path}/tty2 c 4 2 - mknod -m 600 ${dev_path}/tty3 c 4 3 - mknod -m 600 ${dev_path}/tty4 c 4 4 - mknod -m 600 ${dev_path}/console c 5 1 - mknod -m 666 ${dev_path}/full c 1 7 - mknod -m 600 ${dev_path}/initctl p - mknod -m 666 ${dev_path}/ptmx c 5 2 - chown root:tty ${dev_path}/ptmx - ln -s /proc/self/fd ${dev_path}/fd - ln -s /proc/kcore ${dev_path}/core - mkdir -m 755 ${dev_path}/mapper - mknod -m 600 ${dev_path}/mapper/control c 10 236 - mkdir -m 755 ${dev_path}/net - mknod -m 666 ${dev_path}/net/tun c 10 200 - - if [ -n "${root_password}" ]; then - echo "setting root passwd to $root_password" - echo "root:$root_password" | chroot $rootfs_path chpasswd - fi - - return 0 -} - -download_altlinux() -{ - - if [ -z "$aptconfver" ]; then - case "$release" in - sisyphus) - aptconfver=apt-conf-sisyphus ;; - *) - aptconfver=apt-conf-branch ;; - esac - fi - - # check the mini altlinux was not already downloaded - INSTALL_ROOT=$cache/partial - mkdir -p $INSTALL_ROOT - if [ $? -ne 0 ]; then - echo "Failed to create '$INSTALL_ROOT' directory" - return 1 - fi - - # download a mini altlinux into a cache - echo "Downloading altlinux minimal ..." - APT_GET="apt-get -o RPM::RootDir=$INSTALL_ROOT -y" - PKG_LIST="$(grep -hs '^[^#]' "$profile_dir/$profile")" - # if no configuration file $profile -- fall back to default list of packages - [ -z "$PKG_LIST" ] && PKG_LIST="interactivesystem apt $aptconfver etcnet-full openssh-server systemd-sysvinit systemd-units systemd NetworkManager-daemon" - - mkdir -p $INSTALL_ROOT/var/lib/rpm - rpm --root $INSTALL_ROOT --initdb - - # some scripts want to have /dev/null at least - dev_path="$INSTALL_ROOT/dev" - if [ ! -c "${dev_path}/null" ]; then - mkdir -p "${dev_path}" - mknod -m 666 "${dev_path}/null" c 1 3 - fi - - $APT_GET install $PKG_LIST - - if [ $? -ne 0 ]; then - echo "Failed to download the rootfs, aborting." - return 1 - fi - - mv "$INSTALL_ROOT" "$cache/rootfs" - echo "Download complete." - - return 0 -} - -copy_altlinux() -{ - - # make a local copy of the minialtlinux - echo -n "Copying rootfs to $rootfs_path ..." - #cp -a $cache/rootfs-$arch $rootfs_path || return 1 - # i prefer rsync (no reason really) - mkdir -p $rootfs_path - rsync -SHaAX $cache/rootfs/ $rootfs_path/ - return 0 -} - -update_altlinux() -{ - chroot $cache/rootfs apt-get update - chroot $cache/rootfs apt-get -y dist-upgrade -} - -install_altlinux() -{ - mkdir -p @LOCALSTATEDIR@/lock/subsys/ - ( - flock -x 9 - if [ $? -ne 0 ]; then - echo "Cache repository is busy." - return 1 - fi - - echo "Checking cache download in $cache/rootfs ... " - if [ ! -e "$cache/rootfs" ]; then - download_altlinux - if [ $? -ne 0 ]; then - echo "Failed to download 'altlinux base'" - return 1 - fi - else - echo "Cache found. Updating..." - update_altlinux - if [ $? -ne 0 ]; then - echo "Failed to update 'altlinux base', continuing with last known good cache" - else - echo "Update finished" - fi - fi - - echo "Copy $cache/rootfs to $rootfs_path ... " - copy_altlinux - if [ $? -ne 0 ]; then - echo "Failed to copy rootfs" - return 1 - fi - return 0 - ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-altlinux - - return $? -} - -copy_configuration() -{ - - mkdir -p $config_path - grep -q "^lxc.rootfs.path" $config_path/config 2>/dev/null || echo "lxc.rootfs.path = $rootfs_path" >> $config_path/config - cat <> $config_path/config -lxc.uts.name = $name -lxc.tty.max = 4 -lxc.pty.max = 1024 -lxc.cap.drop = sys_module mac_admin mac_override sys_time - -# When using LXC with apparmor, uncomment the next line to run unconfined: -#lxc.apparmor.profile = unconfined - -#networking -#lxc.net.0.type = $lxc_network_type -#lxc.net.0.flags = up -#lxc.net.0.link = $lxc_network_link -#lxc.net.0.name = veth0 -#lxc.net.0.mtu = 1500 -EOF -if [ ! -z ${ipv4} ]; then - cat <> $config_path/config -lxc.net.0.ipv4.address = $ipv4 -EOF -fi -if [ ! -z ${gw} ]; then - cat <> $config_path/config -lxc.net.0.ipv4.gateway = $gw -EOF -fi -if [ ! -z ${ipv6} ]; then - cat <> $config_path/config -lxc.net.0.ipv6.address = $ipv6 -EOF -fi -if [ ! -z ${gw6} ]; then - cat <> $config_path/config -lxc.net.0.ipv6.gateway = $gw6 -EOF -fi - cat <> $config_path/config -#cgroups -lxc.cgroup.devices.deny = a -# /dev/null and zero -lxc.cgroup.devices.allow = c 1:3 rwm -lxc.cgroup.devices.allow = c 1:5 rwm -# consoles -lxc.cgroup.devices.allow = c 5:1 rwm -lxc.cgroup.devices.allow = c 5:0 rwm -lxc.cgroup.devices.allow = c 4:0 rwm -lxc.cgroup.devices.allow = c 4:1 rwm -# /dev/{,u}random -lxc.cgroup.devices.allow = c 1:9 rwm -lxc.cgroup.devices.allow = c 1:8 rwm -lxc.cgroup.devices.allow = c 136:* rwm -lxc.cgroup.devices.allow = c 5:2 rwm -# rtc -lxc.cgroup.devices.allow = c 10:135 rwm - -lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed -EOF - - if [ $? -ne 0 ]; then - echo "Failed to add configuration" - return 1 - fi - - return 0 -} - -clean() -{ - - if [ ! -e $cache ]; then - exit 0 - fi - - # lock, so we won't purge while someone is creating a repository - ( - flock -x 9 - if [ $? != 0 ]; then - echo "Cache repository is busy." - exit 1 - fi - - echo -n "Purging the download cache for ALTLinux-$release..." - rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1 - exit 0 - ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-altlinux -} - -usage() -{ - cat < - [-p|--path=] [-c|--clean] [-R|--release=] - [-4|--ipv4=] [-6|--ipv6=] - [-g|--gw=] [-d|--dns=] - [-P|--profile=] [--rootfs=] - [-a|--apt-conf=] - [-A|--arch=] - [-h|--help] -Mandatory args: - -n,--name container name, used to as an identifier for that container from now on -Optional args: - -p,--path path to where the container rootfs will be created, defaults to @LXCPATH@. The container config will go under @LXCPATH@ in that case - -c,--clean clean the cache - -R,--release ALTLinux release for the new container. if the host is ALTLinux, then it will defaultto the host's release. - -4,--ipv4 specify the ipv4 address to assign to the virtualized interface, eg. 192.168.1.123/24 - -6,--ipv6 specify the ipv6 address to assign to the virtualized interface, eg. 2003:db8:1:0:214:1234:fe0b:3596/64 - -g,--gw specify the default gw, eg. 192.168.1.1 - -G,--gw6 specify the default gw, eg. 2003:db8:1:0:214:1234:fe0b:3596 - -d,--dns specify the DNS server, eg. 192.168.1.2 - -a,--apt-conf specify preferred 'apt-conf' package, eg. 'apt-conf-branch' - -P,--profile Profile name is the file name in /etc/lxc/profiles contained packages name for install to cache. - -A,--arch NOT USED YET. Define what arch the container will be [i686,x86_64] - ---rootfs rootfs path - -h,--help print this help -EOF - return 0 -} - -options=$(getopt -o hp:n:P:cR:4:6:g:d:a: -l help,rootfs:,path:,name:,profile:,clean,release:,ipv4:,ipv6:,gw:,dns:,apt-conf: -- "$@") -if [ $? -ne 0 ]; then - usage $(basename $0) - exit 1 -fi -eval set -- "$options" - -while true -do - case "$1" in - -h|--help) usage $0 && exit 0;; - -p|--path) path=$2; shift 2;; - --rootfs) rootfs_path=$2; shift 2;; - -n|--name) name=$2; shift 2;; - -P|--profile) profile=$2; shift 2;; - -c|--clean) clean=1; shift 1;; - -R|--release) release=$2; shift 2;; - -4|--ipv4) ipv4=$2; shift 2;; - -6|--ipv6) ipv6=$2; shift 2;; - -g|--gw) gw=$2; shift 2;; - -d|--dns) dns=$2; shift 2;; - -a|--apt-conf) aptconfver=$2; shift 2;; - --) shift 1; break ;; - *) break ;; - esac -done - -if [ ! -z "$clean" -a -z "$path" ]; then - clean || exit 1 - exit 0 -fi - -type apt-get >/dev/null 2>&1 -if [ $? -ne 0 ]; then - echo "'apt-get' command is missing" - exit 1 -fi - -if [ -z "$path" ]; then - path=$default_path -fi - -if [ -z "$profile" ]; then - profile=$default_profile -fi - -if [ -z "$release" ]; then - if [ "$is_altlinux" ]; then - release=$(cat /etc/altlinux-release |awk '/^ALT/ {print $3}') - else - echo "This is not a ALTLinux host and release missing, use -R|--release to specify release" - exit 1 - fi -fi - -if [ -z "$ipv4" -a -z "$ipv6" ]; then - BOOTPROTO="dhcp" -else - BOOTPROTO="static" -fi - -if [ "$(id -u)" != "0" ]; then - echo "This script should be run as 'root'" - exit 1 -fi - -# check for 'lxc.rootfs.path' passed in through default config by lxc-create -if [ -z "$rootfs_path" ]; then - if grep -q '^lxc.rootfs.path' $path/config 2>/dev/null ; then - rootfs_path=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $path/config) - else - rootfs_path=$path/rootfs - fi -fi - -config_path=$default_path/$name -cache=$cache_base/$release/$profile - -install_altlinux -if [ $? -ne 0 ]; then - echo "failed to install altlinux" - exit 1 -fi - -configure_altlinux -if [ $? -ne 0 ]; then - echo "failed to configure altlinux for a container" - exit 1 -fi - -copy_configuration -if [ $? -ne 0 ]; then - echo "failed write configuration file" - exit 1 -fi - -if [ ! -z "$clean" ]; then - clean || exit 1 - exit 0 -fi -echo "container rootfs and config created" -echo "network configured as $lxc_network_type in the $lxc_network_link" diff --git a/templates/lxc-archlinux.in b/templates/lxc-archlinux.in deleted file mode 100644 index f8d4ba01c..000000000 --- a/templates/lxc-archlinux.in +++ /dev/null @@ -1,334 +0,0 @@ -#!/bin/bash - -# -# template script for generating Arch Linux container for LXC -# - -# -# lxc: linux Container library - -# Authors: -# Alexander Vladimirov -# John Lane - -# 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 - -# 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 - -# defaults -arch=$(uname -m) -default_path="@LXCPATH@" -default_locale="en_US.UTF-8" -pacman_config="/etc/pacman.conf" -common_config="@LXCTEMPLATECONFIG@/common.conf" -shared_config="@LXCTEMPLATECONFIG@/archlinux.common.conf" - -# by default, install 'base' except the kernel -pkg_blacklist="linux" -base_packages=() -for pkg in $(pacman -Sqg base); do - [ "${pkg_blacklist#*$pkg}" = "$pkg_blacklist" ] && base_packages+=($pkg) -done -declare -a additional_packages - -# split comma-separated string into an array -# ${1} - string to split -# ${2} - separator (default is ",") -# ${result} - result value on success -split_string() { - local ifs=${IFS} - IFS="${2:-,}" - read -a result < <(echo "${1}") - IFS=${ifs} - return 0 -} - -[ -f /etc/arch-release ] && is_arch=true - -# Arch-specific preconfiguration for container -configure_arch() { - # on ArchLinux, read defaults from host systemd configuration - if [ "${is_arch}" ]; then - cp -p /etc/locale.conf /etc/locale.gen "${rootfs_path}/etc/" - else - echo "LANG=${default_locale}" > "${rootfs_path}/etc/locale.conf" - if [ -e "${rootfs_path}/etc/locale.gen" ]; then - sed -i 's@^#\(en_US\.UTF-8\)@\1@' "${rootfs_path}/etc/locale.gen" - if [ ! "${default_locale}" = "en_US.UTF-8" ]; then - echo "${default_locale} ${default_locale##*.}" >> \ - "${rootfs_path}/etc/locale.gen" - fi - fi - fi - - # hostname and nameservers - echo "${name}" > "${rootfs_path}/etc/hostname" - - # network configuration - cat > "${rootfs_path}/etc/systemd/network/eth0.network" << EOF -[Match] -Name=eth0 - -[Network] -DHCP=ipv4 -EOF - - # chroot and configure system - arch-chroot "${rootfs_path}" /bin/bash -s << EOF -mkdir /run/lock -locale-gen -# set default boot target -ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target -# override getty@.service for container ttys -sed -e 's/^ConditionPathExists=/# ConditionPathExists=/' \ - -e 's/After=dev-%i.device/After=/' \ - < /lib/systemd/system/getty\@.service \ - > /etc/systemd/system/getty\@.service -# fix systemd-sysctl service -sed -e 's/^ConditionPathIsReadWrite=\/proc\/sys\/$/ConditionPathIsReadWrite=\/proc\/sys\/net\//' \ - -e 's/^ExecStart=\/usr\/lib\/systemd\/systemd-sysctl$/ExecStart=\/usr\/lib\/systemd\/systemd-sysctl --prefix net/' \ - -i /usr/lib/systemd/system/systemd-sysctl.service -# initialize pacman keyring -pacman-key --init -pacman-key --populate archlinux - -# enable networkd -systemctl enable systemd-networkd -systemctl enable systemd-resolved -ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf -EOF - # enable getty on active ttys - local nttys=$(cat "${config_path}/config" ${shared_config} ${common_config} | grep "^lxc.tty.max" | head -n1 | cut -d= -f2 | tr -d "[:blank:]") - local devttydir=$(cat "${config_path}/config" ${shared_config} ${common_config} | grep "^lxc.tty.dir" | head -n1 | cut -d= -f2 | tr -d "[:blank:]") - local devtty="" - # bind getty instances to /dev//tty* if lxc.tty.dir is set - [ -n "${devttydir}" ] && devtty="${devttydir}-" - if [ ${nttys:-0} -gt 1 ]; then - ( cd "${rootfs_path}/etc/systemd/system/getty.target.wants" - for i in $(seq 1 $nttys); do ln -sf "../getty@.service" "getty@${devtty}tty${i}.service"; done ) - fi - # update securetty to allow console login if devttydir is set - if [ -n "${devttydir}" ]; then - for i in $(seq 1 ${nttys:-1}); do - echo "${devttydir}/tty${i}" >> "${rootfs_path}/etc/securetty" - done - fi - [ -n "${devttydir}" ] && echo "${devttydir}/console" >> "${rootfs_path}/etc/securetty" - # Arch default configuration allows only tty1-6 for login - [ ${nttys:-0} -gt 6 ] && echo \ - "You may want to modify container's /etc/securetty \ - file to allow root logins on tty7 and higher" - return 0 -} - -# write container configuration files -copy_configuration() { - mkdir -p "${config_path}" - local config="${config_path}/config" - echo "lxc.uts.name = ${name}" >> "${config}" - grep -q "^lxc.arch" "${config}" 2>/dev/null \ - || echo "lxc.arch = ${arch}" >> "${config}" - grep -q "^lxc.rootfs.path" "${config}" 2>/dev/null \ - || echo "lxc.rootfs.path = ${rootfs_path}" >> "${config}" - [ -e "${shared_config}" ] \ - && echo "lxc.include = ${shared_config}" >> "${config}" - if [ $? -ne 0 ]; then - echo "Failed to configure container" - return 1 - fi - return 0 -} - -# install packages within container chroot -install_arch() { - [ "${arch}" != "$(uname -m)" ] && different_arch=true - - if [ "${different_arch}" = "true" ]; then - container_pacman_config=$(mktemp) - container_mirrorlist=$(mktemp) - sed -e "s:Architecture =.*:Architecture = ${arch}:g" \ - -e "s:/etc/pacman.d/mirrorlist:${container_mirrorlist}:g" \ - "${pacman_config}" > "${container_pacman_config}" - sed -e "s:\(x86_64\|\$arch\):${arch}:g" \ - /etc/pacman.d/mirrorlist > "${container_mirrorlist}" - - pacman_config="${container_pacman_config}" - fi - - if ! pacstrap -dcGC "${pacman_config}" "${rootfs_path}" \ - ${base_packages[@]}; then - echo "Failed to install container packages" - return 1 - fi - - if [ "${different_arch}" = "true" ]; then - sed -i -e "s:Architecture =.*:Architecture = ${arch}:g" \ - "${rootfs_path}"/etc/pacman.conf - cp "${container_mirrorlist}" "${rootfs_path}"/etc/pacman.d/mirrorlist - rm "${container_pacman_config}" "${container_mirrorlist}" - fi - - [ -d "${rootfs_path}/lib/modules" ] && ldconfig -r "${rootfs_path}" - return 0 -} - -usage() { - cat < [-p|--path=] [-a|--arch=] - [-r|--root_password=] [-P|--packages=] - [-e|--enable_units=unit1,unit2...] [-d|--disable_units=unit1,unit2...] - [-c|--config=] [-h|--help] - -Mandatory args: - -n,--name container name, used to as an identifier for that container from now on -Optional args: - -p,--path path to where the container rootfs will be created (${default_path}) - --rootfs path for actual container rootfs, (${default_path}/rootfs) - -P,--packages preinstall additional packages, comma-separated list - -e,--enable_units enable systemd services, comma-separated list - -d,--disable_units disable systemd services, comma-separated list - -c,--config use specified pacman config when installing container packages - -a,--arch use specified architecture instead of host's architecture - -r,--root_password set container root password - -h,--help print this help -EOF - return 0 -} - -options=$(getopt -o hp:P:e:d:n:c:a:r: -l help,rootfs:,path:,packages:,enable_units:,disable_units:,name:,config:,arch:,root_password: -- "${@}") -if [ ${?} -ne 0 ]; then - usage $(basename ${0}) - exit 1 -fi -eval set -- "${options}" - -while true -do - case "${1}" in - -h|--help) usage ${0} && exit 0;; - -p|--path) path=${2}; shift 2;; - -n|--name) name=${2}; shift 2;; - --rootfs) rootfs_path=${2}; shift 2;; - -P|--packages) additional_packages=${2}; shift 2;; - -e|--enable_units) enable_units=${2}; shift 2;; - -d|--disable_units) disable_units=${2}; shift 2;; - -c|--config) pacman_config=${2}; shift 2;; - -a|--arch) arch=${2}; shift 2;; - -r|--root_password) root_passwd=${2}; shift 2;; - --) shift 1; break ;; - *) break ;; - esac -done - -if [ -z "${name}" ]; then - echo "missing required 'name' parameter" - exit 1 -fi - -type pacman >/dev/null 2>&1 -if [ ${?} -ne 0 ]; then - echo "'pacman' command is missing, refer to wiki.archlinux.org for information about installing pacman" - exit 1 -fi - -if [ -z "${path}" ]; then - path="${default_path}/${name}" -fi - -if [ "${EUID}" != "0" ]; then - echo "This script should be run as 'root'" - exit 1 -fi - -if [ -z "$rootfs_path" ]; then - rootfs_path="${path}/rootfs" -fi -config_path="${path}" - -revert() { - echo "Interrupted, cleaning up" - lxc-destroy -n "${name}" - rm -rf "${path}/${name}" - rm -rf "${default_path}/${name}" - exit 1 -} - -trap revert SIGHUP SIGINT SIGTERM - -copy_configuration -if [ ${?} -ne 0 ]; then - echo "failed to write configuration file" - rm -rf "${config_path}" - exit 1 -fi - -if [ ${#additional_packages[@]} -gt 0 ]; then - split_string ${additional_packages} - base_packages+=(${result[@]}) -fi - -mkdir -p "${rootfs_path}" -install_arch -if [ ${?} -ne 0 ]; then - echo "failed to install Arch Linux" - rm -rf "${config_path}" "${path}" - exit 1 -fi - -configure_arch -if [ ${?} -ne 0 ]; then - echo "failed to configure Arch Linux for a container" - rm -rf "${config_path}" "${path}" - exit 1 -fi - -if [ ${#enable_units[@]} -gt 0 ]; then - split_string ${enable_units} - for unit in ${result[@]}; do - [ "${unit##*.}" = "service" ] || unit="${unit}.service" - ln -s "/usr/lib/systemd/system/${unit}" \ - "${rootfs_path}/etc/systemd/system/multi-user.target.wants/" - done -fi - -if [ ${#disable_units[@]} -gt 0 ]; then - split_string ${disable_units} - for unit in ${result[@]}; do - [ "${unit##*.}" = "service" ] || unit="${unit}.service" - ln -s /dev/null "${rootfs_path}/etc/systemd/system/${unit}" - done -fi - -if [ -n "${root_passwd}" ]; then - echo "root:${root_passwd}" | chroot "${rootfs_path}" chpasswd -fi - -cat << EOF -Arch Linux container ${name} is successfully created! The configuration is -stored in ${config_path}/config. Please refer to https://wiki.archlinux.org for -information about configuring Arch Linux. -EOF diff --git a/templates/lxc-centos.in b/templates/lxc-centos.in deleted file mode 100644 index eba5ec8a3..000000000 --- a/templates/lxc-centos.in +++ /dev/null @@ -1,968 +0,0 @@ -#!/bin/bash - -# -# template script for generating CentOS container for LXC - -# -# lxc: linux Container library - -# Authors: -# Daniel Lezcano -# Ramez Hanna -# Fajar A. Nugraha -# Michael H. Warfield - -# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -#Configurations -default_path=@LXCPATH@ - -# Some combinations of the tuning knobs below do not exactly make sense. -# but that's ok. -# -# If the "root_password" is non-blank, use it, else set a default. -# This can be passed to the script as an environment variable and is -# set by a shell conditional assignment. Looks weird but it is what it is. -# -# 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 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. -# If root_store_password = yes, store it in the configuration directory -# If root_prompt_password = yes, invoke "passwd" to force the user to change -# the root password after the container is created. -# If root_expire_password = yes, you will be prompted to change the root -# password at the first login. -# -# These are conditional assignments... The can be overridden from the -# preexisting environment variables... -# -# Make sure this is in single quotes to defer expansion to later! -# :{root_password='Root-${name}-${RANDOM}'} -: ${root_password='Root-${name}-XXXXXX'} - -# Now, it doesn't make much sense to display, store, and force change -# together. But, we gotta test, right??? -: ${root_display_password='no'} -: ${root_store_password='yes'} -# Prompting for something interactive has potential for mayhem -# with users running under the API... Don't default to "yes" -: ${root_prompt_password='no'} - -# Expire root password? Default to yes, but can be overridden from -# the environment variable -: ${root_expire_password='yes'} - -# These are only going into comments in the resulting config... -lxc_network_type=veth -lxc_network_link=lxcbr0 - -# is this CentOS? -# Alow for weird remixes like the Raspberry Pi -# -# Use the Mitre standard CPE identifier for the release ID if possible... -# This may be in /etc/os-release or /etc/system-release-cpe. We -# should be able to use EITHER. Give preference to /etc/os-release for now. - -# 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 - -if [ -e /etc/os-release ] -then -# This is a shell friendly configuration file. We can just source it. -# What we're looking for in here is the ID, VERSION_ID and the CPE_NAME - . /etc/os-release - echo "Host CPE ID from /etc/os-release: ${CPE_NAME}" -fi - -if [ "${CPE_NAME}" = "" -a -e /etc/system-release-cpe ] -then - CPE_NAME=$(head -n1 /etc/system-release-cpe) - CPE_URI=$(expr ${CPE_NAME} : '\([^:]*:[^:]*\)') - if [ "${CPE_URI}" != "cpe:/o" ] - then - CPE_NAME= - else - # Probably a better way to do this but sill remain posix - # compatible but this works, shrug... - # Must be nice and not introduce convenient bashisms here. - # - # According to the official registration at Mitre and NIST, - # this should have been something like this for CentOS: - # cpe:/o:centos:centos:6 - # or this: - # cpe:/o:centos:centos:6.5 - # - ID=$(expr ${CPE_NAME} : '[^:]*:[^:]*:[^:]*:\([^:]*\)') - # The "enterprise_linux" is a bone toss back to RHEL. - # Since CentOS and RHEL are so tightly coupled, we'll - # take the RHEL version if we're running on it and do the - # equivalent version for CentOS. - if [ ${ID} = "linux" -o ${ID} = "enterprise_linux" ] - then - # Instead we got this: cpe:/o:centos:linux:6 - ID=$(expr ${CPE_NAME} : '[^:]*:[^:]*:\([^:]*\)') - fi - - VERSION_ID=$(expr ${CPE_NAME} : '[^:]*:[^:]*:[^:]*:[^:]*:\([^:]*\)') - echo "Host CPE ID from /etc/system-release-cpe: ${CPE_NAME}" - fi -fi - -if [ "${CPE_NAME}" != "" -a "${ID}" = "centos" -a "${VERSION_ID}" != "" ] -then - centos_host_ver=${VERSION_ID} - is_centos=true -elif [ "${CPE_NAME}" != "" -a "${ID}" = "redhat" -o "${ID}" = "rhel" -a "${VERSION_ID}" != "" ] -then - # RHEL 7+ /etc/os-release ID = 'rhel', which doesn't enter this elif without the added OR statement - redhat_host_ver=${VERSION_ID} - is_redhat=true -elif [ -e /etc/centos-release ] -then - # Only if all other methods fail, try to parse the redhat-release file. - centos_host_ver=$( sed -e '/^CentOS /!d' -e 's/CentOS.*\srelease\s*\([0-9][0-9.]*\)\s.*/\1/' < /etc/centos-release ) - if [ "$centos_host_ver" != "" ] - then - is_centos=true - fi -fi - -force_mknod() -{ - # delete a device node if exists, and create a new one - rm -f $2 && mknod -m $1 $2 $3 $4 $5 -} - -configure_centos() -{ - - # disable selinux in CentOS - mkdir -p $rootfs_path/selinux - echo 0 > $rootfs_path/selinux/enforce - - # Also kill it in the /etc/selinux/config file if it's there... - if [ -f $rootfs_path/etc/selinux/config ] - then - sed -i '/^SELINUX=/s/.*/SELINUX=disabled/' $rootfs_path/etc/selinux/config - fi - - # Nice catch from Dwight Engen in the Oracle template. - # Wantonly plagerized here with much appreciation. - if [ -f $rootfs_path/usr/sbin/selinuxenabled ]; then - mv $rootfs_path/usr/sbin/selinuxenabled $rootfs_path/usr/sbin/selinuxenabled.lxcorig - ln -s /bin/false $rootfs_path/usr/sbin/selinuxenabled - fi - - # This is a known problem and documented in RedHat bugzilla as relating - # to a problem with auditing enabled. This prevents an error in - # the container "Cannot make/remove an entry for the specified session" - sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc/pam.d/login - sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc/pam.d/sshd - - if [ -f ${rootfs_path}/etc/pam.d/crond ] - then - sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc/pam.d/crond - fi - - # In addition to disabling pam_loginuid in the above config files - # we'll also disable it by linking it to pam_permit to catch any - # we missed or any that get installed after the container is built. - # - # Catch either or both 32 and 64 bit archs. - if [ -f ${rootfs_path}/lib/security/pam_loginuid.so ] - then - ( cd ${rootfs_path}/lib/security/ - mv pam_loginuid.so pam_loginuid.so.disabled - ln -s pam_permit.so pam_loginuid.so - ) - fi - - if [ -f ${rootfs_path}/lib64/security/pam_loginuid.so ] - then - ( cd ${rootfs_path}/lib64/security/ - mv pam_loginuid.so pam_loginuid.so.disabled - ln -s pam_permit.so pam_loginuid.so - ) - fi - - # Set default localtime to the host localtime if not set... - if [ -e /etc/localtime -a ! -e ${rootfs_path}/etc/localtime ] - then - # if /etc/localtime is a symlink, this should preserve it. - cp -a /etc/localtime ${rootfs_path}/etc/localtime - fi - - # Deal with some dain bramage in the /etc/init.d/halt script. - # Trim it and make it our own and link it in before the default - # halt script so we can intercept it. This also preventions package - # updates from interferring with our interferring with it. - # - # There's generally not much in the halt script that useful but what's - # in there from resetting the hardware clock down is generally very bad. - # So we just eliminate the whole bottom half of that script in making - # ourselves a copy. That way a major update to the init scripts won't - # trash what we've set up. - if [ -f ${rootfs_path}/etc/init.d/halt ] - then - sed -e '/hwclock/,$d' \ - < ${rootfs_path}/etc/init.d/halt \ - > ${rootfs_path}/etc/init.d/lxc-halt - - echo '$command -f' >> ${rootfs_path}/etc/init.d/lxc-halt - chmod 755 ${rootfs_path}/etc/init.d/lxc-halt - - # Link them into the rc directories... - ( - cd ${rootfs_path}/etc/rc.d/rc0.d - ln -s ../init.d/lxc-halt S00lxc-halt - cd ${rootfs_path}/etc/rc.d/rc6.d - ln -s ../init.d/lxc-halt S00lxc-reboot - ) - fi - - # configure the network using the dhcp - cat < ${rootfs_path}/etc/sysconfig/network-scripts/ifcfg-eth0 -DEVICE=eth0 -BOOTPROTO=dhcp -ONBOOT=yes -HOSTNAME=${utsname} -NM_CONTROLLED=no -TYPE=Ethernet -MTU=${MTU} -DHCP_HOSTNAME=\`hostname\` -EOF - - # set the hostname - cat < ${rootfs_path}/etc/sysconfig/network -NETWORKING=yes -HOSTNAME=${utsname} -EOF - - # set minimal hosts - cat < $rootfs_path/etc/hosts -127.0.0.1 localhost $name -EOF - - # set minimal fstab - cat < $rootfs_path/etc/fstab -/dev/root / rootfs defaults 0 0 -EOF - - # create lxc compatibility init script - if [ "$release" = "6" ]; then - cat < $rootfs_path/etc/init/lxc-sysinit.conf -start on startup -env container - -pre-start script - if [ "x\$container" != "xlxc" -a "x\$container" != "xlibvirt" ]; then - stop; - fi - - rm -f /var/lock/subsys/* - rm -f /var/run/*.pid - [ -e /etc/mtab ] || ln -s /proc/mounts /etc/mtab - mkdir -p /dev/shm - mount -t tmpfs -o nosuid,nodev tmpfs /dev/shm - - initctl start tty TTY=console - telinit 3 - exit 0 -end script -EOF - elif [ "$release" = "5" ]; then - cat < $rootfs_path/etc/rc.d/lxc.sysinit -#! /bin/bash -rm -f /etc/mtab /var/run/*.{pid,lock} /var/lock/subsys/* -rm -rf {/,/var}/tmp/* -echo "/dev/root / rootfs defaults 0 0" > /etc/mtab -exit 0 -EOF - chmod 755 $rootfs_path/etc/rc.d/lxc.sysinit - sed -i 's|si::sysinit:/etc/rc.d/rc.sysinit|si::bootwait:/etc/rc.d/lxc.sysinit|' $rootfs_path/etc/inittab - # prevent mingetty from calling vhangup(2) since it fails with userns. - # Same issue as oracle template: prevent mingetty from calling vhangup(2) - # commit 2e83f7201c5d402478b9849f0a85c62d5b9f1589. - sed -i 's|^1:|co:2345:respawn:/sbin/mingetty --nohangup console\n1:|' $rootfs_path/etc/inittab - sed -i 's|^\([56]:\)|#\1|' $rootfs_path/etc/inittab - fi - - dev_path="${rootfs_path}/dev" - rm -rf $dev_path - mkdir -p $dev_path - mknod -m 666 ${dev_path}/null c 1 3 - mknod -m 666 ${dev_path}/zero c 1 5 - mknod -m 666 ${dev_path}/random c 1 8 - mknod -m 666 ${dev_path}/urandom c 1 9 - mkdir -m 755 ${dev_path}/pts - mkdir -m 1777 ${dev_path}/shm - mknod -m 666 ${dev_path}/tty c 5 0 - mknod -m 666 ${dev_path}/tty0 c 4 0 - mknod -m 666 ${dev_path}/tty1 c 4 1 - mknod -m 666 ${dev_path}/tty2 c 4 2 - mknod -m 666 ${dev_path}/tty3 c 4 3 - mknod -m 666 ${dev_path}/tty4 c 4 4 - mknod -m 600 ${dev_path}/console c 5 1 - mknod -m 666 ${dev_path}/full c 1 7 - mknod -m 600 ${dev_path}/initctl p - mknod -m 666 ${dev_path}/ptmx c 5 2 - - # setup console and tty[1-4] for login. note that /dev/console and - # /dev/tty[1-4] will be symlinks to the ptys /dev/lxc/console and - # /dev/lxc/tty[1-4] so that package updates can overwrite the symlinks. - # lxc will maintain these links and bind mount ptys over /dev/lxc/* - # since lxc.tty.dir is specified in the config. - - # allow root login on console, tty[1-4], and pts/0 for libvirt - echo "# LXC (Linux Containers)" >>${rootfs_path}/etc/securetty - echo "lxc/console" >>${rootfs_path}/etc/securetty - echo "lxc/tty1" >>${rootfs_path}/etc/securetty - echo "lxc/tty2" >>${rootfs_path}/etc/securetty - echo "lxc/tty3" >>${rootfs_path}/etc/securetty - echo "lxc/tty4" >>${rootfs_path}/etc/securetty - echo "# For libvirt/Virtual Machine Monitor" >>${rootfs_path}/etc/securetty - echo "pts/0" >>${rootfs_path}/etc/securetty - - # prevent mingetty from calling vhangup(2) since it fails with userns. - # Same issue as oracle template: prevent mingetty from calling vhangup(2) - # commit 2e83f7201c5d402478b9849f0a85c62d5b9f1589. - test -f $rootfs_path/etc/init/tty.conf && sed -i 's|mingetty|mingetty --nohangup|' $rootfs_path/etc/init/tty.conf - - if [ ${root_display_password} = "yes" ] - then - echo "Setting root password to '$root_password'" - fi - if [ ${root_store_password} = "yes" ] - then - touch ${config_path}/tmp_root_pass - chmod 600 ${config_path}/tmp_root_pass - echo ${root_password} > ${config_path}/tmp_root_pass - echo "Storing root password in '${config_path}/tmp_root_pass'" - fi - - echo "root:$root_password" | chroot $rootfs_path chpasswd - - if [ ${root_expire_password} = "yes" ] - then - # Also set this password as expired to force the user to change it! - chroot $rootfs_path passwd -e root - fi - - # This will need to be enhanced for CentOS 7 when systemd - # comes into play... /\/\|=mhw=|\/\/ - - return 0 -} - -configure_centos_init() -{ - test -f ${rootfs_path}/etc/rc.sysinit && sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc/rc.sysinit - test -f ${rootfs_path}/etc/rc.d/rc.sysinit && sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc/rc.d/rc.sysinit - if [ "$release" = "6" ]; then - chroot ${rootfs_path} chkconfig udev-post off - fi - chroot ${rootfs_path} chkconfig network on - - if [ "$release" = "7" ]; then - # don't wait for the timeout - chroot ${rootfs_path} chkconfig systemd-remount-fs off - fi - - if [ -d ${rootfs_path}/etc/init ] - then - # This is to make upstart honor SIGPWR - cat <${rootfs_path}/etc/init/power-status-changed.conf -# power-status-changed - shutdown on SIGPWR -# -start on power-status-changed - -exec /sbin/shutdown -h now "SIGPWR received" -EOF - fi -} - -download_centos() -{ - - # check the mini CentOS was not already downloaded - INSTALL_ROOT=$cache/partial - mkdir -p $INSTALL_ROOT - if [ $? -ne 0 ]; then - echo "Failed to create '$INSTALL_ROOT' directory" - return 1 - fi - - # download a mini CentOS into a cache - echo "Downloading CentOS minimal ..." - YUM0="yum --installroot $INSTALL_ROOT -y --nogpgcheck" - - if yum -h | grep -q 'releasever=RELEASEVER'; then - YUM="$YUM0 --releasever=$release" - else - YUM="$YUM0" - fi - PKG_LIST="yum initscripts passwd rsyslog vim-minimal openssh-server openssh-clients dhclient chkconfig rootfiles policycoreutils cronie" - - # use temporary repository definition - # always prefer the repo given by the user - # if no repo given, use mirrorlist.centos.org for i386 and x86_64 - # and http://mirror.centos.org/altarch/ otherwise - REPO_FILE=$INSTALL_ROOT/etc/yum.repos.d/lxc-centos-temp.repo - mkdir -p $(dirname $REPO_FILE) - if [ -n "$repo" ]; then - cat < $REPO_FILE -[base] -name=local repository -baseurl="$repo" -EOF - elif [ ${basearch} = 'i386' ] || [ ${basearch} = 'x86_64' ]; then - cat < $REPO_FILE -[base] -name=CentOS-$release - Base -mirrorlist=http://mirrorlist.centos.org/?release=$release&arch=$basearch&repo=os - -[updates] -name=CentOS-$release - Updates -mirrorlist=http://mirrorlist.centos.org/?release=$release&arch=$basearch&repo=updates -EOF - else - cat < $REPO_FILE -[base] -name=CentOS-$release - Base -baseurl=http://mirror.centos.org/altarch/7/os/$basearch/ - -[updates] -name=CentOS-$release - Updates -baseurl=http://mirror.centos.org/altarch/7/updates/$basearch/ -EOF - fi - - # create minimal device nodes, needed for "yum install" and "yum update" process - mkdir -p $INSTALL_ROOT/dev - force_mknod 666 $INSTALL_ROOT/dev/null c 1 3 - force_mknod 666 $INSTALL_ROOT/dev/urandom c 1 9 - - # create /run directory, just in case it is missing (e.g. RHEL7) - mkdir -p $INSTALL_ROOT/run - - $YUM install $PKG_LIST - - # create symlink for /var/run -> ../run - if [ "$release" = "7" ]; then - mv $INSTALL_ROOT/var/run/* $INSTALL_ROOT/run/ - rmdir $INSTALL_ROOT/var/run - ln -sf ../run $INSTALL_ROOT/var/run - fi - - if [ $? -ne 0 ]; then - echo "Failed to download the rootfs, aborting." - return 1 - fi - - # use same nameservers as hosts, needed for "yum update later" - cp /etc/resolv.conf $INSTALL_ROOT/etc/ - - # check whether rpmdb is under $HOME - if [ ! -e $INSTALL_ROOT/var/lib/rpm/Packages -a -e $INSTALL_ROOT/$HOME/.rpmdb/Packages ]; then - echo "Fixing rpmdb location ..." - mv $INSTALL_ROOT/$HOME/.rpmdb/[A-Z]* $INSTALL_ROOT/var/lib/rpm/ - rm -rf $INSTALL_ROOT/$HOME/.rpmdb - chroot $INSTALL_ROOT rpm --rebuilddb 2>/dev/null - fi - - # check whether rpmdb version is correct - chroot $INSTALL_ROOT rpm --quiet -q yum 2>/dev/null - ret=$? - - # if "rpm -q" doesn't work due to rpmdb version difference, - # then we need to redo the process using the newly-installed yum - if [ $ret -gt 0 ]; then - echo "Reinstalling packages ..." - mv $REPO_FILE $REPO_FILE.tmp - mkdir $INSTALL_ROOT/etc/yum.repos.disabled - mv $INSTALL_ROOT/etc/yum.repos.d/*.repo $INSTALL_ROOT/etc/yum.repos.disabled/ - mv $REPO_FILE.tmp $REPO_FILE - mkdir -p $INSTALL_ROOT/$INSTALL_ROOT/etc - cp /etc/resolv.conf $INSTALL_ROOT/$INSTALL_ROOT/etc/ - mkdir -p $INSTALL_ROOT/$INSTALL_ROOT/dev - mknod -m 666 $INSTALL_ROOT/$INSTALL_ROOT/dev/null c 1 3 - mknod -m 666 $INSTALL_ROOT/$INSTALL_ROOT/dev/urandom c 1 9 - mkdir -p $INSTALL_ROOT/$INSTALL_ROOT/var/cache/yum - cp -al $INSTALL_ROOT/var/cache/yum/* $INSTALL_ROOT/$INSTALL_ROOT/var/cache/yum/ - chroot $INSTALL_ROOT $YUM0 install $PKG_LIST - if [ $? -ne 0 ]; then - echo "Failed to download the rootfs, aborting." - return 1 - fi - mv $INSTALL_ROOT/$INSTALL_ROOT $INSTALL_ROOT.tmp - rm -rf $INSTALL_ROOT - mv $INSTALL_ROOT.tmp $INSTALL_ROOT - fi - - rm -f $REPO_FILE - rm -rf $INSTALL_ROOT/var/cache/yum/* - - mv "$INSTALL_ROOT" "$cache/rootfs" - echo "Download complete." - - return 0 -} - -copy_centos() -{ - - # make a local copy of the mini CentOS - echo -n "Copying rootfs to $rootfs_path ..." - #cp -a $cache/rootfs-$arch $rootfs_path || return 1 - # i prefer rsync (no reason really) - mkdir -p $rootfs_path - rsync -SHaAX $cache/rootfs/ $rootfs_path/ - echo - return 0 -} - -update_centos() -{ - YUM="chroot $cache/rootfs yum -y --nogpgcheck" - $YUM update - if [ $? -ne 0 ]; then - return 1 - fi - $YUM clean packages -} - -install_centos() -{ - mkdir -p /var/lock/subsys/ - ( - flock -x 9 - if [ $? -ne 0 ]; then - echo "Cache repository is busy." - return 1 - fi - - echo "Checking cache download in $cache/rootfs ... " - if [ ! -e "$cache/rootfs" ]; then - download_centos - if [ $? -ne 0 ]; then - echo "Failed to download 'CentOS base'" - return 1 - fi - else - echo "Cache found. Updating..." - update_centos - if [ $? -ne 0 ]; then - echo "Failed to update 'CentOS base', continuing with last known good cache" - else - echo "Update finished" - fi - fi - - echo "Copy $cache/rootfs to $rootfs_path ... " - copy_centos - if [ $? -ne 0 ]; then - echo "Failed to copy rootfs" - return 1 - fi - - return 0 - - ) 9>/var/lock/subsys/lxc-centos - - return $? -} - -create_hwaddr() -{ - openssl rand -hex 5 | sed -e 's/\(..\)/:\1/g; s/^/fe/' -} - -copy_configuration() -{ - mkdir -p $config_path - - grep -q "^lxc.rootfs.path" $config_path/config 2>/dev/null || echo " -lxc.rootfs.path = $rootfs_path -" >> $config_path/config - - # The following code is to create static MAC addresses for each - # interface in the container. This code will work for multiple - # interfaces in the default config. - mv $config_path/config $config_path/config.def - while read LINE - do - # This should catch variable expansions from the default config... - if expr "${LINE}" : '.*\$' > /dev/null 2>&1 - then - LINE=$(eval "echo \"${LINE}\"") - fi - - # There is a tab and a space in the regex bracket below! - # Seems that \s doesn't work in brackets. - KEY=$(expr "${LINE}" : '\s*\([^ ]*\)\s*=') - - if [[ "${KEY}" != "lxc.net.0.hwaddr" ]] - then - echo ${LINE} >> $config_path/config - - if [[ "${KEY}" == "lxc.net.0.link" ]] - then - echo "lxc.net.0.hwaddr = $(create_hwaddr)" >> $config_path/config - fi - fi - done < $config_path/config.def - - rm -f $config_path/config.def - - if [ -e "@LXCTEMPLATECONFIG@/centos.common.conf" ]; then - echo " -# Include common configuration -lxc.include = @LXCTEMPLATECONFIG@/centos.common.conf -" >> $config_path/config - fi - - # Append things which require expansion here... - cat <> $config_path/config -lxc.arch = $arch -lxc.uts.name = $utsname - -# When using LXC with apparmor, uncomment the next line to run unconfined: -#lxc.apparmor.profile = unconfined - -# example simple networking setup, uncomment to enable -#lxc.net.0.type = $lxc_network_type -#lxc.net.0.flags = up -#lxc.net.0.link = $lxc_network_link -#lxc.net.0.name = eth0 -# Additional example for veth network type -# static MAC address, -#lxc.net.0.hwaddr = 00:16:3e:77:52:20 -# persistent veth device name on host side -# Note: This may potentially collide with other containers of same name! -#lxc.net.0.veth.pair = v-$name-e0 - -EOF - - if [ $? -ne 0 ]; then - echo "Failed to add configuration" - return 1 - fi - - return 0 -} - -clean() -{ - - if [ ! -e $cache ]; then - exit 0 - fi - - # lock, so we won't purge while someone is creating a repository - ( - flock -x 9 - if [ $? != 0 ]; then - echo "Cache repository is busy." - exit 1 - fi - - echo -n "Purging the download cache for CentOS-$release..." - rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1 - exit 0 - - ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-centos -} - -usage() -{ - cat < - [-p|--path=] [-c|--clean] [-R|--release=] [-a|--arch=] - [-h|--help] -Mandatory args: - -n,--name container name, used to as an identifier for that container from now on -Optional args: - -p,--path path to where the container rootfs will be created, defaults to /var/lib/lxc/name. - -c,--clean clean the cache - -R,--release CentOS release for the new container. If the host is CentOS, then it will default to the host's release. - --fqdn fully qualified domain name (FQDN) for DNS and system naming - --repo repository to use (url) - -a,--arch Define what arch the container will be [i686,x86_64] - -h,--help print this help -EOF - return 0 -} - -options=$(getopt -o a:hp:n:cR: -l help,path:,rootfs:,name:,clean,release:,repo:,arch:,fqdn: -- "$@") -if [ $? -ne 0 ]; then - usage $(basename $0) - exit 1 -fi - -arch=$(uname -m) -eval set -- "$options" -while true -do - case "$1" in - -h|--help) usage $0 && exit 0;; - -p|--path) path=$2; shift 2;; - --rootfs) rootfs_path=$2; shift 2;; - -n|--name) name=$2; shift 2;; - -c|--clean) clean=1; shift 1;; - -R|--release) release=$2; shift 2;; - --repo) repo="$2"; shift 2;; - -a|--arch) newarch=$2; shift 2;; - --fqdn) utsname=$2; shift 2;; - --) shift 1; break ;; - *) break ;; - esac -done - -if [ ! -z "$clean" -a -z "$path" ]; then - clean || exit 1 - exit 0 -fi - -basearch=${arch} -# Map a few architectures to their generic CentOS repository archs. -# The two ARM archs are a bit of a guesstimate for the v5 and v6 -# archs. V6 should have hardware floating point (Rasberry Pi). -# The "arm" arch is safer (no hardware floating point). So -# there may be cases where we "get it wrong" for some v6 other -# than RPi. -case "$arch" in -i686) basearch=i386 ;; -armv3l|armv4l|armv5l) basearch=arm ;; -armv6l|armv7l|armv8l) basearch=armhfp ;; -*) ;; -esac - -# Somebody wants to specify an arch. This is very limited case. -# i386/i586/i686 on i386/x86_64 -# - or - -# x86_64 on x86_64 -if [ "${newarch}" != "" -a "${newarch}" != "${arch}" ] -then - case "${newarch}" in - i386|i586|i686) - if [ "${basearch}" = "i386" -o "${basearch}" = "x86_64" ] - then - # Make the arch a generic x86 32 bit... - arch=${newarch} - basearch=i386 - else - basearch=bad - fi - ;; - *) - basearch=bad - ;; - esac - - if [ "${basearch}" = "bad" ] - then - echo "You cannot build a ${newarch} CentOS container on a ${arch} host. Sorry!" - exit 1 - fi -fi - -# Allow the cache base to be set by environment variable -cache_base=${LXC_CACHE_PATH:-"@LOCALSTATEDIR@/cache/lxc"}/centos/$basearch - -# Let's do something better for the initial root password. -# It's not perfect but it will defeat common scanning brute force -# attacks in the case where ssh is exposed. It will also be set to -# expired, forcing the user to change it at first login. -if [ "${root_password}" = "" ] -then - root_password=Root-${name}-${RANDOM} -else - # If it's got a ding in it, try and expand it! - if [ $(expr "${root_password}" : '.*$.') != 0 ] - then - root_password=$(eval echo "${root_password}") - fi - - # 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 - root_password=$(mktemp -u ${root_password}) - fi -fi - -if [ -z "${utsname}" ]; then - utsname=${name} -fi - -# This follows a standard "resolver" convention that an FQDN must have -# at least two dots or it is considered a local relative host name. -# If it doesn't, append the dns domain name of the host system. -# -# This changes one significant behavior when running -# "lxc_create -n Container_Name" without using the -# --fqdn option. -# -# Old behavior: -# utsname and hostname = Container_Name -# New behavior: -# utsname and hostname = Container_Name.Domain_Name - -if [ $(expr "$utsname" : '.*\..*\.') = 0 ]; then - if [[ "$(dnsdomainname)" != "" && "$(dnsdomainname)" != "localdomain" ]]; then - utsname=${utsname}.$(dnsdomainname) - fi -fi - -type yum >/dev/null 2>&1 -if [ $? -ne 0 ]; then - echo "'yum' command is missing" - exit 1 -fi - -if [ -z "$path" ]; then - path=$default_path/$name -fi - -if [ -z "$release" ]; then - if [ "$is_centos" -a "$centos_host_ver" ]; then - release=$centos_host_ver - elif [ "$is_redhat" -a "$redhat_host_ver" ]; then - # This is needed to clean out bullshit like 6workstation and 6server. - release=$(expr $redhat_host_ver : '\([0-9.]*\)') - else - echo "This is not a CentOS or Red Hat host and release is missing, defaulting to 7, use -R|--release to specify release" - release=7 - fi -fi - -if [ "$(id -u)" != "0" ]; then - echo "This script should be run as 'root'" - exit 1 -fi - -if [ -z "$rootfs_path" ]; then - rootfs_path=$path/rootfs - # check for 'lxc.rootfs.path' passed in through default config by lxc-create - if grep -q '^lxc.rootfs.path' $path/config 2>/dev/null ; then - rootfs_path=$(sed -e '/^lxc.rootfs.path\s*=/!d' -e 's/\s*#.*//' \ - -e 's/^lxc.rootfs.path\s*=\s*//' -e q $path/config) - fi -fi -config_path=$path -cache=$cache_base/$release - -revert() -{ - echo "Interrupted, so cleaning up" - lxc-destroy -n $name - # maybe was interrupted before copy config - rm -rf $path - echo "exiting..." - exit 1 -} - -trap revert SIGHUP SIGINT SIGTERM - -copy_configuration -if [ $? -ne 0 ]; then - echo "failed write configuration file" - exit 1 -fi - -install_centos -if [ $? -ne 0 ]; then - echo "failed to install CentOS" - exit 1 -fi - -configure_centos -if [ $? -ne 0 ]; then - echo "failed to configure CentOS for a container" - exit 1 -fi - -configure_centos_init - -if [ ! -z "$clean" ]; then - clean || exit 1 - exit 0 -fi -echo " -Container rootfs and config have been created. -Edit the config file to check/enable networking setup. -" - -if [ ${root_display_password} = "yes" ] -then - echo "The temporary password for root is: '$root_password' - -You may want to note that password down before starting the container. -" -fi - -if [ ${root_store_password} = "yes" ] -then - echo "The temporary root password is stored in: - - '${config_path}/tmp_root_pass' -" -fi - -if [ ${root_prompt_password} = "yes" ] -then - echo "Invoking the passwd command in the container to set the root password. - - chroot ${rootfs_path} passwd -" - chroot ${rootfs_path} passwd -else - if [ ${root_expire_password} = "yes" ] - then - if ( mountpoint -q -- "${rootfs_path}" ) - then - echo "To reset the root password, you can do: - - lxc-start -n ${name} - lxc-attach -n ${name} -- passwd - lxc-stop -n ${name} -" - else - echo " -The root password is set up as "expired" and will require it to be changed -at first login, which you should do as soon as possible. If you lose the -root password or wish to change it without starting the container, you -can change it from the host by running the following command (which will -also reset the expired flag): - - chroot ${rootfs_path} passwd -" - fi - fi -fi diff --git a/templates/lxc-cirros.in b/templates/lxc-cirros.in deleted file mode 100644 index de79dafd8..000000000 --- a/templates/lxc-cirros.in +++ /dev/null @@ -1,343 +0,0 @@ -#!/bin/bash - -# template script for generating ubuntu container for LXC -# -# This script consolidates and extends the existing lxc ubuntu scripts -# - -# Copyright © 2013 Canonical Ltd. -# Author: Scott Moser -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2, as -# published by the Free Software Foundation. - -# This program 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 General Public License for more details. - -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -# Detect use under userns (unsupported) -# 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/" - -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" -case "${UNAME_M}" in - i?86) DEF_ARCH="i386";; - x86_64) DEF_ARCH="x86_64";; - arm*) DEF_ARCH="arm";; - *) 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 - -# Allow the cache base to be set by environment variable -if [ $(id -u) -eq 0 ]; then - CACHE_D=${LXC_CACHE_PATH:-"@LOCALSTATEDIR@/cache/lxc/cirros"} -else - CACHE_D=${LXC_CACHE_PATH:-"$HOME/.cache/lxc/cirros"} -fi - -error() { echo "$@" 1>&2; } -inargs() { - local needle="$1" x="" - shift - for x in "$@"; do - [ "$needle" = "$x" ] && return 0 - done - return 1 -} - -Usage() { - cat <&2; [ $# -eq 0 ] || error "$@"; return 1; } - -debug() { - local level=${1}; shift; - [ "${level}" -gt "${VERBOSITY}" ] && return - error "${@}" -} -jsondict() { - local k="" v="" ret="{" - for arg in "$@"; do - k="${arg%%=*}" - v="${arg#*=}" - ret="${ret} \"${k}\": \"$v\"," - done - ret="${ret%,} }" - echo "$ret" -} - -copy_configuration() -{ - local path=$1 rootfs=$2 name=$3 arch=$4 release=$5 -cat >> "$path/config" <> $path/config - fi - -} - -insert_ds_nocloud() { - local root_d="$1" authkey="$2" udfile="$3" - local sdir="$root_d/var/lib/cloud/seed/nocloud" - - mkdir -p "$sdir" || - { error "failed to make datasource dir $sdir"; return 1; } - rm -f "$sdir/meta-data" "$sdir/user-data" || - { error "failed to clean old data from $sdir"; return 1; } - - iid="iid-local01" - jsondict "instance-id=$iid" \ - ${authkeys:+"public-keys=${authkeys}"} > "$sdir/meta-data" || - { error "failed to write metadata to $sdir/meta-data"; return 1; } - - if [ -n "$udfile" ]; then - cat "$udfile" > "$sdir/user-data" || - { error "failed to write user-data to $sdir"; return 1; } - else - rm -f "$sdir/user-data" - fi -} - -insert_ds() { - local dstype="$1" root_d="$2" authkey="$3" udfile="$4" - case "$dstype" in - nocloud) insert_ds_nocloud "$root_d" "$authkey" "$udfile" - esac -} - -extract_rootfs() { - local tarball="$1" rootfs_d="$2" - mkdir -p "${rootfs_d}" || - { error "failed to make rootfs dir ${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 -} - -download_tarball() { - local arch="$1" ver="$2" cached="$3" baseurl="$4" - local out="" outd="" file="" dlpath="" - file="cirros-$ver-$arch-lxc.tar.gz" - dlpath="$ver/$file" - outd="${cached}/${dlpath%/*}" - if [ -f "$cached/$dlpath" ]; then - _RET="$cached/$dlpath" - return 0 - fi - - mkdir -p "${outd}" || - { error "failed to create ${outd}"; return 1; } - - debug 1 "downloading ${baseurl%/}/$dlpath" to "${cached}/$dlpath" - wget "${baseurl%/}/$dlpath" -O "$cached/${dlpath}.$$" && - mv "$cached/$dlpath.$$" "$cached/$dlpath" || { - rm -f "$cached/$dlpath.$$"; - error "failed to download $dlpath"; - return 1; - } - _RET="$cached/$dlpath" -} - -create_main() { - local short_opts="a:hn:p:S:uvV" - 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}" -- "$@") && - eval set -- "${getopt_out}" || - { bad_Usage; return; } - - local arch="${DEF_ARCH}" dsource="${DEF_SOURCE}" version="${DEF_VERSION}" - local authkey_f="" authkeys="" userdata_f="" path="" tarball="" - local cur="" next="" - local rootfs_d="" - - while [ $# -ne 0 ]; do - cur=$1; next=$2; - case "$cur" in - -a|--arch) arch="$next"; shift;; - -h|--help) Usage ; return 0;; - -n|--name) name="$next"; shift;; - -v|--verbose) VERBOSITY=$((${VERBOSITY}+1));; - -S|--auth-key) authkey_f="$next"; shift;; - -p|--path) path=$next; shift;; - -v|--version) version=$next; shift;; - -u|--userdata) userdata_f="$next"; shift;; - --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; - done - - [ -n "$rootfs_d" ] || rootfs_d="$path/rootfs" - [ $# -eq 0 ] || { bad_Usage "unexpected arguments: $*"; return; } - [ -n "$path" ] || { error "'path' parameter is required"; return 1; } - - if [ "$(id -u)" != "0" ]; then - { error "must be run as root"; return 1; } - fi - - case "$arch" in - i?86) arch="i386";; - amd64) arch="x86_64";; - esac - - inargs "$arch" "${ARCHES[@]}" || - { error "bad arch '$arch'. allowed: ${ARCHES[*]}"; return 1; } - - inargs "$dsource" "${SOURCES[@]}" || - { error "bad source '$dsource'. allowed: ${SOURCES[*]}"; return 1; } - - if [ "$dsource" = "none" ] && [ -n "$userdata_f" -o -n "$authkey_f" ]; then - error "userdata and authkey are incompatible with --source=none"; - return 1; - fi - - if [ -n "$authkey_f" ]; then - if [ ! -f "$authkey_f" ]; then - error "--auth-key=${authkey_f} must reference a file" - return 1 - fi - authkeys=$(cat "$authkey_f") || - { error "failed to read ${authkey_f}"; return 1; } - fi - - if [ -n "$userdata_f" -a ! -f "${userdata_f}" ]; then - error "${userdata_f}: --userdata arg not a file" - return 1 - fi - - if [ -z "$tarball" ]; then - if inargs "$version" "${STREAMS[@]}"; then - out=$(wget -O - -q "${DOWNLOAD_URL%/}/version/$version") || - { error "failed to convert 'version=$version'"; return 1; } - version="$out" - fi - download_tarball "$arch" "$version" "${CACHE_D}" "${DOWNLOAD_URL}" || - return - tarball="$_RET" - fi - - extract_rootfs "${tarball}" "${rootfs_d}" || return - - 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' \ - "$rootfs_d/etc/inittab" || - { error "failed to fix console entry for $version"; return 1; } - fi - - if [ "$dsource" != "none" ]; then - insert_ds "$dsource" "$path/rootfs" "$authkeys" "$userdata_f" || { - error "failed to insert userdata to $path/rootfs" - return 1 - } - fi - - copy_configuration "$path" "$path/rootfs" "$name" "$arch" "$release" - return -} - -create_main "$@" - -# vi: ts=4 expandtab diff --git a/templates/lxc-debian.in b/templates/lxc-debian.in deleted file mode 100644 index 438847894..000000000 --- a/templates/lxc-debian.in +++ /dev/null @@ -1,824 +0,0 @@ -#!/bin/bash - -# -# lxc: linux Container library - -# Authors: -# Daniel Lezcano - -# 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 - -# 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 -export GREP_OPTIONS="" - -MIRROR=${MIRROR:-http://deb.debian.org/debian} -SECURITY_MIRROR=${SECURITY_MIRROR:-http://security.debian.org/} -LOCALSTATEDIR="@LOCALSTATEDIR@" -LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@" -# Allows the lxc-cache directory to be set by environment variable -LXC_CACHE_PATH=${LXC_CACHE_PATH:-"$LOCALSTATEDIR/cache/lxc"} - -find_interpreter() -{ - given_interpreter=$(basename "$1") - - if [ ! -d /proc/sys/fs/binfmt_misc/ ] ; then - return 1 - fi - for file in /proc/sys/fs/binfmt_misc/* ; do - if [ "$file" = "/proc/sys/fs/binfmt_misc/register" -o \ - "$file" = "/proc/sys/fs/binfmt_misc/status" ] ; then - continue - fi - interpreter_path=$(sed -n "/^interpreter/s/interpreter \([^[:space:]]*\)/\1/p" "$file") - interpreter=$(basename "$interpreter_path") - - if [ "$given_interpreter" = "$interpreter" ] ; then - echo "$interpreter_path" - return 0 - fi - done - return 1 -} - -configure_debian() -{ - rootfs=$1 - hostname=$2 - num_tty=$3 - - # squeeze only has /dev/tty and /dev/tty0 by default, - # therefore creating missing device nodes for tty1-4. - for tty in $(seq 1 "$num_tty"); do - if [ ! -e "$rootfs/dev/tty$tty" ]; then - mknod "$rootfs/dev/tty$tty" c 4 "$tty" - fi - done - - # configure the inittab - cat < $rootfs/etc/inittab -id:3:initdefault: -si::sysinit:/etc/init.d/rcS -l0:0:wait:/etc/init.d/rc 0 -l1:1:wait:/etc/init.d/rc 1 -l2:2:wait:/etc/init.d/rc 2 -l3:3:wait:/etc/init.d/rc 3 -l4:4:wait:/etc/init.d/rc 4 -l5:5:wait:/etc/init.d/rc 5 -l6:6:wait:/etc/init.d/rc 6 -# Normally not reached, but fallthrough in case of emergency. -z6:6:respawn:/sbin/sulogin -1:2345:respawn:/sbin/getty 38400 console -$(for tty in $(seq 1 "$num_tty"); do echo "c${tty}:12345:respawn:/sbin/getty 38400 tty${tty} linux" ; done;) -p6::ctrlaltdel:/sbin/init 6 -p0::powerfail:/sbin/init 0 -EOF - - # symlink mtab - [ -e "$rootfs/etc/mtab" ] && rm "$rootfs/etc/mtab" - ln -s /proc/self/mounts "$rootfs/etc/mtab" - - # disable selinux in debian - mkdir -p "$rootfs/selinux" - echo 0 > "$rootfs/selinux/enforce" - - # configure the network using the dhcp - cat < $rootfs/etc/network/interfaces -auto lo -iface lo inet loopback - -auto eth0 -iface eth0 inet dhcp -EOF - - # set the hostname - cat < $rootfs/etc/hostname -$hostname -EOF - - # reconfigure some services - - # but first reconfigure locales - so we get no noisy perl-warnings - if [ -z "$LANG" ] || echo $LANG | grep -E -q "^C(\..+)*$"; then - cat >> "$rootfs/etc/locale.gen" << EOF -en_US.UTF-8 UTF-8 -EOF - chroot "$rootfs" locale-gen en_US.UTF-8 UTF-8 - chroot "$rootfs" update-locale LANG=en_US.UTF-8 - else - encoding=$(echo "$LANG" | cut -d. -f2) - chroot "$rootfs" sed -e "s/^# \(${LANG} ${encoding}\)/\1/" \ - -i /etc/locale.gen 2> /dev/null - cat >> "$rootfs/etc/locale.gen" << EOF -$LANG $encoding -EOF - chroot "$rootfs" locale-gen "$LANG" "$encoding" - chroot "$rootfs" update-locale LANG="$LANG" - fi - - # remove pointless services in a container - 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 - cat > "$rootfs/usr/sbin/policy-rc.d" << EOF -#!/bin/sh -exit 101 -EOF - chmod +x "$rootfs/usr/sbin/policy-rc.d" - - if [ -f "$rootfs/etc/init/ssh.conf" ]; then - mv "$rootfs/etc/init/ssh.conf" "$rootfs/etc/init/ssh.conf.disabled" - fi - - rm -f "$rootfs/etc/ssh/"ssh_host_*key* - - DPKG_MAINTSCRIPT_PACKAGE=openssh DPKG_MAINTSCRIPT_NAME=postinst chroot "$rootfs" /var/lib/dpkg/info/openssh-server.postinst configure - sed -i "s/root@$(hostname)/root@$hostname/g" "$rootfs/etc/ssh/"ssh_host_*.pub - - if [ -f "$rootfs/etc/init/ssh.conf.disabled" ]; then - mv "$rootfs/etc/init/ssh.conf.disabled" "$rootfs/etc/init/ssh.conf" - fi - - rm -f "$rootfs/usr/sbin/policy-rc.d" - fi - - # set initial timezone as on host - if [ -f /etc/timezone ]; then - cat /etc/timezone > "$rootfs/etc/timezone" - chroot "$rootfs" dpkg-reconfigure -f noninteractive tzdata - elif [ -f /etc/sysconfig/clock ]; then - . /etc/sysconfig/clock - echo "$ZONE" > "$rootfs/etc/timezone" - chroot "$rootfs" dpkg-reconfigure -f noninteractive tzdata - else - echo "Timezone in container is not configured. Adjust it manually." - fi - - if [ -n "$authkey" ]; then - local ssh_dir_path="${rootfs}/root/.ssh" - mkdir -p "$ssh_dir_path" - cp "$authkey" "${ssh_dir_path}/authorized_keys" - chmod 700 "$ssh_dir_path" - echo "Inserted SSH public key from '$authkey' into /root/.ssh/authorized_keys" - fi - - 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 - - if [ "$mainonly" = 1 ]; then - non_main='' - else - non_main=' contrib non-free' - fi - - cat >> "${rootfs}/etc/apt/sources.list" << EOF -${prefix} $MIRROR ${release} main${non_main} -EOF - - if [ "$release" != "unstable" -a "$release" != "sid" ]; then - cat >> "${rootfs}/etc/apt/sources.list" << EOF -${prefix} $SECURITY_MIRROR ${release}/updates main${non_main} -EOF - fi -} - -install_packages() -{ - local rootfs="$1"; shift - local packages="$*" - - chroot "${rootfs}" apt-get update - if [ -n "${packages}" ]; then - chroot "${rootfs}" apt-get install --force-yes -y --no-install-recommends ${packages} - fi -} - -configure_debian_systemd() -{ - path=$1 - rootfs=$2 - config=$3 - num_tty=$4 - - # just in case systemd is not installed - mkdir -p "${rootfs}/lib/systemd/system" - mkdir -p "${rootfs}/etc/systemd/system/getty.target.wants" - - # Fix getty-static-service as debootstrap does not install dbus - if [ -e "$rootfs//lib/systemd/system/getty-static.service" ] ; then - local tty_services - tty_services=$(for i in $(seq 2 "$num_tty"); do echo -n "getty@tty${i}.service "; done; ) - sed 's/ getty@tty.*/'" $tty_services "'/g' \ - "$rootfs/lib/systemd/system/getty-static.service" | \ - sed 's/\(tty2-tty\)[5-9]/\1'"${num_tty}"'/g' > "$rootfs/etc/systemd/system/getty-static.service" - fi - - # This function has been copied and adapted from lxc-fedora - rm -f "${rootfs}/etc/systemd/system/default.target" - 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 - # Setup getty service on the ttys we are going to allow in the - # default config. Number should match lxc.tty.max - ( cd "${rootfs}/etc/systemd/system/getty.target.wants" - for i in $(seq 1 "$num_tty") ; do ln -sf ../getty\@.service getty@tty"${i}".service; done ) - - # Since we use static-getty.target; we need to mask container-getty@.service generated by - # container-getty-generator, so we don't get multiple instances of agetty running. - # See https://github.com/lxc/lxc/issues/520 and https://github.com/lxc/lxc/issues/484 - ( cd "${rootfs}/etc/systemd/system/getty.target.wants" - for i in $(seq 0 "$num_tty"); do ln -sf /dev/null container-getty\@"${i}".service; done ) - - return 0 -} - -# Check if given path is in a btrfs partition -is_btrfs() -{ - [ -e "$1" -a "$(stat -f -c '%T' "$1")" = "btrfs" ] -} - -# Check if given path is the root of a btrfs subvolume -is_btrfs_subvolume() -{ - [ -d "$1" -a "$(stat -f -c '%T' "$1")" = "btrfs" -a "$(stat -c '%i' "$1")" -eq 256 ] -} - -try_mksubvolume() -{ - path=$1 - [ -d "$path" ] && return 0 - mkdir -p "$(dirname "$path")" - if which btrfs >/dev/null 2>&1 && is_btrfs "$(dirname "$path")"; then - btrfs subvolume create "$path" - else - mkdir -p "$path" - fi -} - -try_rmsubvolume() -{ - path=$1 - [ -d "$path" ] || return 0 - if which btrfs >/dev/null 2>&1 && is_btrfs_subvolume "$path"; then - btrfs subvolume delete "$path" - else - rm -rf "$path" - fi -} - -cleanup() -{ - try_rmsubvolume "$cache/partial-$release-$arch" - try_rmsubvolume "$cache/rootfs-$release-$arch" -} - -download_debian() -{ - case "$release" in - wheezy) - init=sysvinit - iproute=iproute - ;; - *) - init=init - iproute=iproute2 - ;; - esac - packages=\ -$init,\ -ifupdown,\ -locales,\ -dialog,\ -isc-dhcp-client,\ -netbase,\ -net-tools,\ -$iproute,\ -openssh-server - - cache=$1 - arch=$2 - release=$3 - interpreter="$4" - interpreter_path="$5" - - trap cleanup EXIT SIGHUP SIGINT SIGTERM - - # Create the cache - mkdir -p "$cache" - - # If debian-archive-keyring isn't installed, fetch GPG keys directly - releasekeyring=/usr/share/keyrings/debian-archive-keyring.gpg - if [ ! -f $releasekeyring ]; then - releasekeyring="$cache/archive-key.gpg" - case $release in - "wheezy") - gpgkeyname="archive-key-7.0" - ;; - *) - gpgkeyname="archive-key-8" - ;; - esac - wget https://ftp-master.debian.org/keys/${gpgkeyname}.asc -O - --quiet \ - | gpg --import --no-default-keyring --keyring="${releasekeyring}" - fi - # check the mini debian was not already downloaded - try_mksubvolume "$cache/partial-$release-$arch" - if [ $? -ne 0 ]; then - echo "Failed to create '$cache/partial-$release-$arch' directory" - return 1 - fi - - # download a mini debian into a cache - echo "Downloading debian minimal ..." - if [ "$interpreter" = "" ] ; then - debootstrap --verbose --variant=minbase --arch="$arch" \ - --include=$packages --keyring="${releasekeyring}" \ - "$release" "$cache/partial-$release-$arch" "$MIRROR" - if [ $? -ne 0 ]; then - echo "Failed to download the rootfs, aborting." - return 1 - fi - else - debootstrap --foreign --verbose --variant=minbase --arch="$arch" \ - --include=$packages --keyring="${releasekeyring}" \ - "$release" "$cache/partial-$release-$arch" "$MIRROR" - if [ $? -ne 0 ]; then - echo "Failed to download the rootfs, aborting." - return 1 - fi - mkdir -p "$(basename "$cache/partial-$release-$arch/$interpreter_path")" - cp "$interpreter" "$cache/partial-$release-$arch/$interpreter_path" - if [ $? -ne 0 ]; then - echo "failed to copy $interpreter to $cache/partial-$release-$arch/$interpreter_path" - return 1 - fi - chroot "$cache/partial-$release-$arch" debootstrap/debootstrap --second-stage - if [ $? -ne 0 ]; then - echo "failed to update the rootfs, aborting" - return 1 - fi - fi - - mv "$1/partial-$release-$arch" "$1/rootfs-$release-$arch" - echo "Download complete." - trap EXIT - trap SIGINT - trap SIGTERM - trap SIGHUP - - return 0 -} - -copy_debian() -{ - cache=$1 - arch=$2 - rootfs=$3 - release=$4 - - # make a local copy of the minidebian - echo -n "Copying rootfs to $rootfs..." - try_mksubvolume "$rootfs" - if which btrfs >/dev/null 2>&1 && \ - is_btrfs_subvolume "$cache/rootfs-$release-$arch" && \ - is_btrfs_subvolume "$rootfs"; then - realrootfs="$(dirname "$config")"/rootfs - [ "$rootfs" = "$realrootfs" ] || umount "$rootfs" || return 1 - btrfs subvolume delete "$realrootfs" || return 1 - btrfs subvolume snapshot "$cache/rootfs-$release-$arch" "$realrootfs" || return 1 - [ "$rootfs" = "$realrootfs" ] || mount --bind "$realrootfs" "$rootfs" || return 1 - else - rsync -SHaAX "$cache/rootfs-$release-$arch"/ $rootfs/ || return 1 - fi - return 0 -} - -install_debian() -{ - rootfs=$1 - release=$2 - arch=$3 - cache="$4/debian" - interpreter="$5" - interpreter_path="$6" - flushcache=$7 - mkdir -p $LOCALSTATEDIR/lock/subsys/ - ( - flock -x 9 - if [ $? -ne 0 ]; then - echo "Cache repository is busy." - return 1 - fi - - if [ "$flushcache" -eq 1 ]; then - echo "Flushing cache..." - cleanup - fi - - echo "Checking cache download in $cache/rootfs-$release-$arch ... " - if [ ! -e "$cache/rootfs-$release-$arch" ]; then - download_debian "$cache" "$arch" "$release" "$interpreter" "$interpreter_path" - if [ $? -ne 0 ]; then - echo "Failed to download 'debian base'" - return 1 - fi - fi - - copy_debian "$cache" "$arch" "$rootfs" "$release" - if [ $? -ne 0 ]; then - echo "Failed to copy rootfs" - return 1 - fi - - return 0 - - ) 9>$LOCALSTATEDIR/lock/subsys/lxc-debian - - return $? -} - -copy_configuration() -{ - path=$1 - rootfs=$2 - hostname=$3 - arch=$4 - num_tty=$5 - - # Generate the configuration file - # if there is exactly one veth network entry, make sure it has an - # associated hwaddr. - nics=$(grep -ce '^lxc\.net\.0\.type[ \t]*=[ \t]*veth' "$path/config") - if [ "$nics" -eq 1 ]; then - grep -q "^lxc.net.0.hwaddr" "$path/config" || sed -i -e "/^lxc\.net\.0\.type[ \t]*=[ \t]*veth/a lxc.net.0.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')" "$path/config" - fi - - ## Add all the includes - echo "" >> "$path/config" - echo "# Common configuration" >> "$path/config" - if [ -e "${LXC_TEMPLATE_CONFIG}/debian.common.conf" ]; then - echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/debian.common.conf" >> "$path/config" - fi - if [ -e "${LXC_TEMPLATE_CONFIG}/debian.${release}.conf" ]; then - echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/debian.${release}.conf" >> "$path/config" - fi - - ## Add the container-specific config - echo "" >> "$path/config" - echo "# Container specific configuration" >> "$path/config" - grep -q "^lxc.rootfs.path" "$path/config" 2> /dev/null || echo "lxc.rootfs.path = $rootfs" >> "$path/config" - - cat <> $path/config -lxc.tty.max = $num_tty -lxc.uts.name = $hostname -lxc.arch = $arch -lxc.pty.max = 1024 -EOF - - if [ $? -ne 0 ]; then - echo "Failed to add configuration" - return 1 - fi - - return 0 -} - -post_process() -{ - local rootfs="$1"; shift - local release="$1"; shift - local arch="$1"; shift - local hostarch="$1"; shift - local interpreter="$1"; shift - local packages="$*" - - # 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 [ "$interpreter" = "" -a "${arch}" != "${hostarch}" ]; then - # Test if dpkg supports multiarch - if ! chroot "$rootfs" dpkg --print-foreign-architectures 2>&1; then - chroot "$rootfs" dpkg --add-architecture "${hostarch}" - fi - fi - - # Write a new sources.list containing both native and multiarch entries - > "${rootfs}/etc/apt/sources.list" - if [ "$interpreter" != "" -a "${arch}" = "${hostarch}" ]; then - write_sourceslist "${rootfs}" "${release}" "${arch}" - else - write_sourceslist "${rootfs}" "${release}" - fi - - # Install Packages in container - if [ -n "${packages}" ]; then - local pack_list - pack_list="${packages//,/ }" - echo "Installing packages: ${pack_list}" - install_packages "${rootfs}" "${pack_list}" - fi - - # Re-enable service startup - rm "${rootfs}/usr/sbin/policy-rc.d" - - # end -} - -clean() -{ - cache=${LXC_CACHE_PATH:-"$LOCALSTATEDIR/cache/lxc/debian"} - - if [ ! -e "$cache" ]; then - exit 0 - fi - - # lock, so we won't purge while someone is creating a repository - ( - flock -x 9 - if [ $? != 0 ]; then - echo "Cache repository is busy." - exit 1 - fi - - echo -n "Purging the download cache..." - rm --preserve-root --one-file-system -rf "$cache" && echo "Done." || exit 1 - exit 0 - - ) 9>$LOCALSTATEDIR/lock/subsys/lxc-debian -} - -usage() -{ - cat < [-c|--clean] [-a|--arch=] [-r|--release=] - [--mirror=] [--security-mirror=] - [--package=] - [-I|--interpreter-path=] - [-F | --flush-cache] [-S|--auth-key=] - -Options : - - -h, --help print this help text - -p, --path=PATH directory where config and rootfs of this VM will be kept - -S, --auth-key=KEYFILE SSH public key to inject into the container as the root user. - -a, --arch=ARCH The container architecture. Can be one of: i686, x86_64, - amd64, armhf, armel, powerpc. Defaults to host arch. - -r, --release=RELEASE Debian release. Can be one of: wheezy, jessie, stretch, buster, sid. - Defaults to current stable. - --mirror=MIRROR Debian mirror to use during installation. Overrides the MIRROR - environment variable (see below). - --security-mirror=SECURITY_MIRROR - Debian mirror to use for security updates. Overrides the - SECURITY_MIRROR environment variable (see below). - --packages=PACKAGE_NAME1,PACKAGE_NAME2,... - List of additional packages to install. Comma separated, without space. - -c, --clean only clean up the cache and terminate - --enable-non-free include also Debian's contrib and non-free repositories. - -I|--interpreter-path=INTERPRETER-PATH - Path of the binfmt interpreter to copy to the rootfs - -F | --flush-cache Flush the debian release cache - -Environment variables: - - MIRROR The Debian package mirror to use. See also the --mirror switch above. - Defaults to '$MIRROR' - SECURITY_MIRROR The Debian package security mirror to use. See also the --security-mirror switch above. - Defaults to '$SECURITY_MIRROR' - -EOF - return 0 -} - -options=$(getopt -o hp:n:a:r:cI:FS: -l arch:,auth-key:,clean,help,enable-non-free,mirror:,name:,packages:,path:,release:,rootfs:,security-mirror:,interpreter-path:,flush-cache -- "$@") -if [ $? -ne 0 ]; then - usage "$(basename "$0")" - exit 1 -fi -eval set -- "$options" - -littleendian=$(lscpu | grep '^Byte Order' | grep -q Little && echo yes) - -arch=$(uname -m) -if [ "$arch" = "i686" ]; then - arch="i386" -elif [ "$arch" = "x86_64" ]; then - arch="amd64" -elif [ "$arch" = "armv7l" ]; then - arch="armhf" -elif [ "$arch" = "aarch64" ]; then - arch="arm64" -elif [ "$arch" = "ppc" ]; then - arch="powerpc" -elif [ "$arch" = "ppc64le" ]; then - arch="ppc64el" -elif [ "$arch" = "mips" -a "$littleendian" = "yes" ]; then - arch="mipsel" -elif [ "$arch" = "mips64" -a "$littleendian" = "yes" ]; then - arch="mips64el" -fi -hostarch=$arch -mainonly=1 -flushcache=0 - -while true -do - case "$1" in - -h|--help) usage "$0" && exit 1;; - --) shift 1; break ;; - - -a|--arch) arch=$2; shift 2;; - -S|--auth-key) authkey=$2; shift 2;; - -I|--interpreter-path) - interpreter="$2"; shift 2;; - -c|--clean) clean=1; shift 1;; - --enable-non-free) mainonly=0; shift 1;; - --mirror) MIRROR=$2; shift 2;; - -n|--name) name=$2; shift 2;; - --packages) packages=$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;; - -F|--flush-cache) flushcache=1; shift 1;; - *) break ;; - esac -done - -if [ ! -z "$clean" -a -z "$path" ]; then - clean || exit 1 - exit 0 -fi - -if [ "$arch" = "i686" ]; then - arch=i386 -fi - -if [ "$arch" = "x86_64" ]; then - arch=amd64 -fi - -if [ "$interpreter" = "" ] ; then - if [ $hostarch = "i386" -a $arch = "amd64" ]; then - echo "can't create $arch container on $hostarch" - exit 1 - fi - - if [ $hostarch = "armhf" -o $hostarch = "armel" ] && \ - [ $arch != "armhf" -a $arch != "armel" ]; then - echo "can't create $arch container on $hostarch" - exit 1 - fi - - if [ $hostarch = "powerpc" -a $arch != "powerpc" ]; then - echo "can't create $arch container on $hostarch" - exit 1 - fi - - if [ $hostarch = "mips" -a $arch != "mips" ] || \ - [ $hostarch = "mipsel" -a $arch != "mipsel" ] || \ - [ $hostarch = "mips64" -a $arch != "mips" -a $arch != "mips64" ] || \ - [ $hostarch = "mips64el" -a $arch != "mipsel" -a $arch != "mips64el" ]; then - echo "can't create $arch container on $hostarch" - exit 1 - fi -else - if ! file -b "${interpreter}" |grep -q "statically linked" ; then - echo "'${interpreter}' must be statically linked" 1>&2 - exit 1 - fi - interpreter_path=$(find_interpreter "$interpreter") - if [ $? -ne 0 ] ; then - echo "no binfmt interpreter using $(basename "$interpreter")" 1>&2 - exit 1 - fi -fi - -type debootstrap -if [ $? -ne 0 ]; then - echo "'debootstrap' command is missing" - exit 1 -fi - -if [ -z "$path" ]; then - echo "'path' parameter is required" - exit 1 -fi - -if [ "$(id -u)" != "0" ]; then - echo "This script should be run as 'root'" - exit 1 -fi - -if [ -n "$authkey" ]; then - if [ ! -f "$authkey" ]; then - echo "SSH keyfile '$authkey' not found" - exit 1 - fi - # This is mostly to prevent accidental uage of the private key instead - # of the public key. - if [ "${authkey: -4}" != ".pub" ]; then - echo "SSH keyfile '$authkey' does not end with '.pub'" - exit 1 - fi -fi - -release=${release:-stable} -permanent_releases=('stable' 'testing' 'sid' 'unstable') -if [[ ! "${permanent_releases[*]}" =~ (^|[^[:alpha:]])$release([^[:alpha:]]|$) ]]; then - if ! wget "${MIRROR}/dists/${release}/Release" -O /dev/null 2> /dev/null; then - echo "Invalid release ${release} (not found in mirror)" - exit 1 - fi -fi - -# detect rootfs -config="$path/config" -if [ -z "$rootfs" ]; then - if grep -q '^lxc.rootfs.path' "$config" 2> /dev/null ; then - rootfs=$(awk -F= '/^lxc.rootfs.path[ \t]+=/{ print $2 }' "$config") - else - rootfs=$path/rootfs - fi -fi - -# determine the number of ttys - default is 4 -if grep -q '^lxc.tty.max' "$config" 2> /dev/null ; then - num_tty=$(awk -F= '/^lxc.tty.max[ \t]+=/{ print $2 }' "$config") -else - num_tty=4 -fi - -install_debian "$rootfs" "$release" "$arch" "$LXC_CACHE_PATH" "$interpreter" "$interpreter_path" "$flushcache" -if [ $? -ne 0 ]; then - echo "failed to install debian" - exit 1 -fi - -configure_debian "$rootfs" "$name" $num_tty -if [ $? -ne 0 ]; then - echo "failed to configure debian for a container" - exit 1 -fi - -copy_configuration "$path" "$rootfs" "$name" $arch $num_tty -if [ $? -ne 0 ]; then - echo "failed write configuration file" - exit 1 -fi - -configure_debian_systemd "$path" "$rootfs" "$config" $num_tty - -post_process "${rootfs}" "${release}" ${arch} ${hostarch} "${interpreter}" "${packages}" - -if [ ! -z "$clean" ]; then - clean || exit 1 - exit 0 -fi diff --git a/templates/lxc-fedora-legacy.in b/templates/lxc-fedora-legacy.in deleted file mode 100644 index 3ef341530..000000000 --- a/templates/lxc-fedora-legacy.in +++ /dev/null @@ -1,1495 +0,0 @@ -#!/bin/bash - -# -# template script for generating fedora container for LXC -# - -# -# lxc: linux Container library - -# Authors: -# Daniel Lezcano -# Ramez Hanna -# Michael H. Warfield - -# 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 - -#Configurations -default_path=@LXCPATH@ - -# Some combinations of the tuning knobs below do not exactly make sense. -# but that's ok. -# -# If the "root_password" is non-blank, use it, else set a default. -# This can be passed to the script as an environment variable and is -# set by a shell conditional assignment. Looks weird but it is what it is. -# -# 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 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. -# If root_store_password = yes, store it in the configuration directory -# If root_prompt_password = yes, invoke "passwd" to force the user to change -# the root password after the container is created. -# If root_expire_password = yes, you will be prompted to change the root -# password at the first login. -# -# These are conditional assignments... The can be overridden from the -# preexisting environment variables... -# -# Make sure this is in single quotes to defer expansion to later! -# :{root_password='Root-${name}-${RANDOM}'} -: ${root_password='Root-${name}-XXXXXX'} - -# Now, it doesn't make much sense to display, store, and force change -# together. But, we gotta test, right??? -: ${root_display_password='no'} -: ${root_store_password='yes'} -# Prompting for something interactive has potential for mayhem -# with users running under the API... Don't default to "yes" -: ${root_prompt_password='no'} - -# Expire root password? Default to yes, but can be overridden from -# the environment variable -: ${root_expire_password='yes'} - -# These are only going into comments in the resulting config... -lxc_network_type=veth -lxc_network_link=lxcbr0 - -# is this fedora? -# Alow for weird remixes like the Raspberry Pi -# -# Use the Mitre standard CPE identifier for the release ID if possible... -# This may be in /etc/os-release or /etc/system-release-cpe. We -# should be able to use EITHER. Give preference to /etc/os-release for now. - -# 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 - -if [ -e /etc/os-release ] -then -# This is a shell friendly configuration file. We can just source it. -# What we're looking for in here is the ID, VERSION_ID and the CPE_NAME - . /etc/os-release - echo "Host CPE ID from /etc/os-release: ${CPE_NAME}" -fi - -if [ "${CPE_NAME}" = "" -a -e /etc/system-release-cpe ] -then - CPE_NAME=$(head -n1 /etc/system-release-cpe) - CPE_URI=$(expr ${CPE_NAME} : '\([^:]*:[^:]*\)') - if [ "${CPE_URI}" != "cpe:/o" ] - then - CPE_NAME= - else - echo "Host CPE ID from /etc/system-release-cpe: ${CPE_NAME}" - # Probably a better way to do this but sill remain posix - # compatible but this works, shrug... - # Must be nice and not introduce convenient bashisms here. - ID=$(expr ${CPE_NAME} : '[^:]*:[^:]*:[^:]*:\([^:]*\)') - VERSION_ID=$(expr ${CPE_NAME} : '[^:]*:[^:]*:[^:]*:[^:]*:\([^:]*\)') - fi -fi - -if [ "${CPE_NAME}" != "" -a "${ID}" = "fedora" -a "${VERSION_ID}" != "" ] -then - fedora_host_ver=${VERSION_ID} - is_fedora=true -elif [ -e /etc/redhat-release ] -then - # Only if all other methods fail, try to parse the redhat-release file. - fedora_host_ver=$( sed -e '/^Fedora /!d' -e 's/Fedora.*\srelease\s*\([0-9][0-9]*\)\s.*/\1/' < /etc/redhat-release ) - if [ "$fedora_host_ver" != "" ] - then - is_fedora=true - fi -fi - -configure_fedora() -{ - - # disable selinux in fedora - mkdir -p $rootfs_path/selinux - echo 0 > $rootfs_path/selinux/enforce - - # Also kill it in the /etc/selinux/config file if it's there... - if [[ -f $rootfs_path/etc/selinux/config ]] - then - sed -i '/^SELINUX=/s/.*/SELINUX=disabled/' $rootfs_path/etc/selinux/config - fi - - # Nice catch from Dwight Engen in the Oracle template. - # Wantonly plagerized here with much appreciation. - if [ -f $rootfs_path/usr/sbin/selinuxenabled ]; then - mv $rootfs_path/usr/sbin/selinuxenabled $rootfs_path/usr/sbin/selinuxenabled.lxcorig - ln -s /bin/false $rootfs_path/usr/sbin/selinuxenabled - fi - - # This is a known problem and documented in RedHat bugzilla as relating - # to a problem with auditing enabled. This prevents an error in - # the container "Cannot make/remove an entry for the specified session" - sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc/pam.d/login - sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc/pam.d/sshd - - if [ -f ${rootfs_path}/etc/pam.d/crond ] - then - sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc/pam.d/crond - fi - - # In addition to disabling pam_loginuid in the above config files - # we'll also disable it by linking it to pam_permit to catch any - # we missed or any that get installed after the container is built. - # - # Catch either or both 32 and 64 bit archs. - if [ -f ${rootfs_path}/lib/security/pam_loginuid.so ] - then - ( cd ${rootfs_path}/lib/security/ - mv pam_loginuid.so pam_loginuid.so.disabled - ln -s pam_permit.so pam_loginuid.so - ) - fi - - if [ -f ${rootfs_path}/lib64/security/pam_loginuid.so ] - then - ( cd ${rootfs_path}/lib64/security/ - mv pam_loginuid.so pam_loginuid.so.disabled - ln -s pam_permit.so pam_loginuid.so - ) - fi - - # Set default localtime to the host localtime if not set... - if [ -e /etc/localtime -a ! -e ${rootfs_path}/etc/localtime ] - then - # if /etc/localtime is a symlink, this should preserve it. - cp -a /etc/localtime ${rootfs_path}/etc/localtime - fi - - # Deal with some dain bramage in the /etc/init.d/halt script. - # Trim it and make it our own and link it in before the default - # halt script so we can intercept it. This also preventions package - # updates from interferring with our interferring with it. - # - # There's generally not much in the halt script that useful but what's - # in there from resetting the hardware clock down is generally very bad. - # So we just eliminate the whole bottom half of that script in making - # ourselves a copy. That way a major update to the init scripts won't - # trash what we've set up. - # - # This is mostly for legacy distros since any modern systemd Fedora - # release will not have this script so we won't try to intercept it. - if [ -f ${rootfs_path}/etc/init.d/halt ] - then - sed -e '/hwclock/,$d' \ - < ${rootfs_path}/etc/init.d/halt \ - > ${rootfs_path}/etc/init.d/lxc-halt - - echo '$command -f' >> ${rootfs_path}/etc/init.d/lxc-halt - chmod 755 ${rootfs_path}/etc/init.d/lxc-halt - - # Link them into the rc directories... - ( - cd ${rootfs_path}/etc/rc.d/rc0.d - ln -s ../init.d/lxc-halt S00lxc-halt - cd ${rootfs_path}/etc/rc.d/rc6.d - ln -s ../init.d/lxc-halt S00lxc-reboot - ) - fi - - # configure the network using the dhcp - cat < ${rootfs_path}/etc/sysconfig/network-scripts/ifcfg-eth0 -DEVICE=eth0 -BOOTPROTO=dhcp -ONBOOT=yes -HOSTNAME=${utsname} -DHCP_HOSTNAME=\`hostname\` -NM_CONTROLLED=no -TYPE=Ethernet -MTU=${MTU} -EOF - - # set the hostname - cat < ${rootfs_path}/etc/sysconfig/network -NETWORKING=yes -HOSTNAME=${utsname} -EOF - - # set hostname on systemd Fedora systems - if [ $release -gt 14 ]; then - echo "${utsname}" > ${rootfs_path}/etc/hostname - fi - - # set minimal hosts - cat < $rootfs_path/etc/hosts -127.0.0.1 localhost.localdomain localhost $utsname -::1 localhost6.localdomain6 localhost6 -EOF - - # These mknod's really don't make any sense with modern releases of - # Fedora with systemd, devtmpfs, and autodev enabled. They are left - # here for legacy reasons and older releases with upstart and sysv init. - dev_path="${rootfs_path}/dev" - rm -rf $dev_path - mkdir -p $dev_path - mknod -m 666 ${dev_path}/null c 1 3 - mknod -m 666 ${dev_path}/zero c 1 5 - mknod -m 666 ${dev_path}/random c 1 8 - mknod -m 666 ${dev_path}/urandom c 1 9 - mkdir -m 755 ${dev_path}/pts - mkdir -m 1777 ${dev_path}/shm - mknod -m 666 ${dev_path}/tty c 5 0 - mknod -m 666 ${dev_path}/tty0 c 4 0 - mknod -m 666 ${dev_path}/tty1 c 4 1 - mknod -m 666 ${dev_path}/tty2 c 4 2 - mknod -m 666 ${dev_path}/tty3 c 4 3 - mknod -m 666 ${dev_path}/tty4 c 4 4 - mknod -m 600 ${dev_path}/console c 5 1 - mknod -m 666 ${dev_path}/full c 1 7 - mknod -m 600 ${dev_path}/initctl p - mknod -m 666 ${dev_path}/ptmx c 5 2 - - # setup console and tty[1-4] for login. note that /dev/console and - # /dev/tty[1-4] will be symlinks to the ptys /dev/lxc/console and - # /dev/lxc/tty[1-4] so that package updates can overwrite the symlinks. - # lxc will maintain these links and bind mount ptys over /dev/lxc/* - # since lxc.tty.dir is specified in the config. - - # allow root login on console, tty[1-4], and pts/0 for libvirt - echo "# LXC (Linux Containers)" >>${rootfs_path}/etc/securetty - echo "lxc/console" >>${rootfs_path}/etc/securetty - echo "lxc/tty1" >>${rootfs_path}/etc/securetty - echo "lxc/tty2" >>${rootfs_path}/etc/securetty - echo "lxc/tty3" >>${rootfs_path}/etc/securetty - echo "lxc/tty4" >>${rootfs_path}/etc/securetty - echo "# For libvirt/Virtual Machine Monitor" >>${rootfs_path}/etc/securetty - echo "pts/0" >>${rootfs_path}/etc/securetty - - if [ ${root_display_password} = "yes" ] - then - echo "Setting root password to '$root_password'" - fi - if [ ${root_store_password} = "yes" ] - then - touch ${config_path}/tmp_root_pass - chmod 600 ${config_path}/tmp_root_pass - echo ${root_password} > ${config_path}/tmp_root_pass - echo "Storing root password in '${config_path}/tmp_root_pass'" - fi - - echo "root:$root_password" | chroot $rootfs_path chpasswd - - if [ ${root_expire_password} = "yes" ] - then - # Also set this password as expired to force the user to change it! - chroot $rootfs_path passwd -e root - fi - - # specifying this in the initial packages doesn't always work. - # Even though it should have... - echo "installing fedora-release package" - mount -o bind /dev ${rootfs_path}/dev - mount -t proc proc ${rootfs_path}/proc - # Always make sure /etc/resolv.conf is up to date in the target! - cp /etc/resolv.conf ${rootfs_path}/etc/ - # Rebuild the rpm database based on the target rpm version... - rm -f ${rootfs_path}/var/lib/rpm/__db* - chroot ${rootfs_path} rpm --rebuilddb - chroot ${rootfs_path} yum -y install fedora-release - - if [[ ! -e ${rootfs_path}/sbin/NetworkManager ]] - then - # NetworkManager has not been installed. Use the - # legacy chkconfig command to enable the network startup - # scripts in the container. - chroot ${rootfs_path} chkconfig network on - fi - - umount ${rootfs_path}/proc - umount ${rootfs_path}/dev - - # silence some needless startup errors - touch ${rootfs_path}/etc/fstab - - # give us a console on /dev/console - sed -i 's/ACTIVE_CONSOLES=.*$/ACTIVE_CONSOLES="\/dev\/console \/dev\/tty[1-4]"/' \ - ${rootfs_path}/etc/sysconfig/init - - return 0 -} - -configure_fedora_init() -{ - sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc/rc.sysinit - sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc/rc.d/rc.sysinit - # don't mount devpts, for pete's sake - sed -i 's/^.*dev.pts.*$/#\0/' ${rootfs_path}/etc/rc.sysinit - sed -i 's/^.*dev.pts.*$/#\0/' ${rootfs_path}/etc/rc.d/rc.sysinit - chroot ${rootfs_path} chkconfig udev-post off - chroot ${rootfs_path} chkconfig network on - - if [ -d ${rootfs_path}/etc/init ] - then - # This is to make upstart honor SIGPWR. Should do no harm - # on systemd systems and some systems may have both. - cat <${rootfs_path}/etc/init/power-status-changed.conf -# power-status-changed - shutdown on SIGPWR -# -start on power-status-changed - -exec /sbin/shutdown -h now "SIGPWR received" -EOF - fi -} - -configure_fedora_systemd() -{ - rm -f ${rootfs_path}/etc/systemd/system/default.target - touch ${rootfs_path}/etc/fstab - chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/udev.service - chroot ${rootfs_path} ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target - # Make systemd honor SIGPWR - chroot ${rootfs_path} ln -s /usr/lib/systemd/system/halt.target /etc/systemd/system/sigpwr.target - - # if desired, prevent systemd from over-mounting /tmp with tmpfs - if [ $masktmp -eq 1 ]; then - chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/tmp.mount - fi - - #dependency on a device unit fails it specially that we disabled udev - # sed -i 's/After=dev-%i.device/After=/' ${rootfs_path}/lib/systemd/system/getty\@.service - # - # Actually, the After=dev-%i.device line does not appear in the - # Fedora 17 or Fedora 18 systemd getty\@.service file. It may be left - # over from an earlier version and it's not doing any harm. We do need - # to disable the "ConditionalPathExists=/dev/tty0" line or no gettys are - # started on the ttys in the container. Lets do it in an override copy of - # the service so it can still pass rpm verifies and not be automatically - # updated by a new systemd version. -- mhw /\/\|=mhw=|\/\/ - - sed -e 's/^ConditionPathExists=/# ConditionPathExists=/' \ - -e 's/After=dev-%i.device/After=/' \ - < ${rootfs_path}/lib/systemd/system/getty\@.service \ - > ${rootfs_path}/etc/systemd/system/getty\@.service - # Setup getty service on the 4 ttys we are going to allow in the - # default config. Number should match lxc.tty - ( cd ${rootfs_path}/etc/systemd/system/getty.target.wants - for i in 1 2 3 4 ; do ln -sf ../getty\@.service getty@tty${i}.service; done ) -} - -### BEGIN Bootstrap Environment Code... Michael H. Warfield /\/\|=mhw=|\/\/ - -# Ok... Heads up. If you're reading these comments, you're either a -# template owner or someone wondering how the hell I did this (or, worse, -# someone in the future trying to maintain it). This code is slightly -# "evil coding bastard" code with one significant hack / dirty trick -# that you would probably miss just reading the code below. I'll mark -# it out with comments. -# -# Because of what this code does, it deserves a lot of comments so people -# can understand WHY I did it this way... -# -# Ultimate Objective - Build a Fedora container on a host system which does -# not have a (complete compatible) version of rpm and/or yum. That basically -# means damn near any distro other than Fedora and Ubuntu (which has rpm and -# yum available). Only requirements for this function are rsync and -# squashfs available to the kernel. If you don't have those, why are you -# even attempting to build containers? -# -# Challenge for this function - Bootstrap a Fedora install bootstrap -# run time environment which has all the pieces to run rpm and yum and -# from which we can build targets containers even where the host system -# has no support for rpm, yum, or fedora. -# -# Steps: -# Stage 0 - Download a Fedora LiveOS squashfs core (netinst core). -# Stage 1 - Extract filesystem from Stage 0 and update to full rpm & yum -# Stage 2 - Use Stage 1 to build a rootfs with python, rpm, and yum. -# -# Stage 2 becomes our bootstrap file system which can be cached -# and then used to build other arbitrary vesions of Fedora of a -# given architecture. Note that this only has to run once for -# Fedora on a given architecture since rpm and yum can build other -# versions. We'll arbitrarily pick Fedora 20 to build this. This -# will need to change as time goes on. - -# Programmers Note... A future fall back may be to download the netinst -# iso image instead of the LiveOS squasfs image and work from that. -# That may be more general but will introduce another substep -# (mounting the iso) to the stage0 setup. - -# This system is designed to be as autonomous as possible so all whitelists -# and controls are self-contained. - -# Initial testing - Whitelist nobody. Build for everybody... -# Initial deployment - Whitelist Fedora. -# Long term - Whitelist Fedora, Debian, Ubuntu, CentOs, Scientific, and NST. - -# List of distros which do not (should not) need a bootstrap (but we will test -# for rpm and yum none the less... OS SHOULD be taken from CPE values but -# Debian / Ubuntu doesn't support CPE yet. - -# BOOTSTRAP_WHITE_LIST="" -BOOTSTRAP_WHITE_LIST="fedora" -# BOOTSTRAP_WHITE_LIST="fedora debian ubuntu centos scientific sl nst" - -BOOTSTRAP=0 -BOOTSTRAP_DIR= -BOOTSTRAP_CHROOT= - -fedora_get_bootstrap() -{ - echo "Bootstrap Environment testing..." - - WHITE_LISTED=1 - - # We need rpm. No rpm - not possible to white list... - if ! which rpm > /dev/null 2>&1 - then - WHITE_LISTED=0 - fi - - # We need yum No yum - not possible to white list... - if ! which yum > /dev/null 2>&1 - then - WHITE_LISTED=0 - fi - - if [[ ${WHITE_LISTED} != 0 ]] - then - for OS in ${BOOTSTRAP_WHITE_LIST} - do - if [[ ${ID} = ${OS} ]] - then - echo " -OS ${ID} is whitelisted. Installation Bootstrap Environment not required. -" - return 0; - fi - done - fi - - echo " -Fedora Installation Bootstrap Build..." - - if ! which rsync > /dev/null 2>&1 - then - echo " -Unable to locate rsync. Cravely bailing out before even attempting to build -an Installation Bootstrap Please install rsync and then rerun this process. -" - - return 255 - fi - - [[ -d ${cache_base} ]] || mkdir -p ${cache_base} - - cd ${cache_base} - - # 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 preferring higher over - # lower - which makes for really ugly code... - - # Is this a "bashism" that will need cleaning up???? - BOOTSTRAP_LIST="$(( $release + 1 ))/rootfs $(( $release - 1 ))/rootfs \ -$(( $release + 2 ))/rootfs $(( $release - 2 ))/rootfs \ -$(( $release + 3 ))/rootfs $(( $release - 3 ))/rootfs \ -bootstrap" - - for bootstrap in ${BOOTSTRAP_LIST} - do - if [[ -d ${bootstrap} ]] - then - echo " -Existing Bootstrap found. Testing..." - - mount -o bind /dev ${bootstrap}/dev - mount -t proc proc ${bootstrap}/proc - # Always make sure /etc/resolv.conf is up to date in the target! - cp /etc/resolv.conf ${bootstrap}/etc/ - rm -f ${bootstrap}/var/lib/rpm/__db* - chroot ${bootstrap} rpm --rebuilddb - chroot ${bootstrap} yum -y update - RC=$? - umount ${bootstrap}/proc - umount ${bootstrap}/dev - - if [[ 0 == ${RC} ]] - then - BOOTSTRAP=1 - BOOTSTRAP_DIR="${cache_base}/${bootstrap}" - BOOTSTRAP_CHROOT="chroot ${BOOTSTRAP_DIR} " - BOOTSTRAP_INSTALL_ROOT=/run/install - - echo " -Functional Installation Bootstrap exists and appears to be completed. -Will use existing Bootstrap: ${BOOTSTRAP_DIR} -" - return 0 - fi - echo " -Installation Bootstrap in ${BOOTSTRAP_DIR} exists -but appears to be non-functional. Skipping... It should be removed. -" - fi - done - - TMP_BOOTSTRAP_DIR=$( mktemp -d --tmpdir=${cache_base} bootstrap_XXXXXX ) - - cd ${TMP_BOOTSTRAP_DIR} - - mkdir squashfs stage0 stage1 bootstrap - -### Stage 0 setup. -# Download the LiveOS squashfs image -# mount image to "squashfs" -# mount contained LiveOS to stage0 - -# We're going to use the archives.fedoraproject.org mirror for the initial stages... -# 1 - It's generally up to date and complete -# 2 - It's has high bandwidth access -# 3 - It supports rsync and wildcarding (and we need both) -# 4 - Not all the mirrors carry the LiveOS images - - if [[ ! -f ../LiveOS/squashfs.img ]] - then - echo " -Downloading stage 0 LiveOS squashfs file system from archives.fedoraproject.org... -Have a beer or a cup of coffee. This will take a bit (~300MB). -" - sleep 3 # let him read it... - - # Right now, we are using Fedora 20 for the inial bootstrap. - # We could make this the "current" Fedora rev (F > 15). - - rsync -av ${mirrorurl}/fedora/linux/releases/20/Fedora/$basearch/os/LiveOS . - - if [[ 0 == $? ]] - then - echo "Download of squashfs image complete." - mv LiveOS .. - else - echo " -Download of squashfs image failed. -" - return 255 - fi - else - echo "Using cached stage 0 LiveOS squashfs file system." - fi - - mount -o loop ../LiveOS/squashfs.img squashfs - - if [[ $? != 0 ]] - then - echo " -Mount of LiveOS squashfs image failed! You mush have squashfs support -available to mount image. Unable to continue. Correct and retry -process later! LiveOS image not removed. Process may be rerun -without penalty of downloading LiveOS again. If LiveOS is corrupt, -remove ${cache_base}/LiveOS before rerunning to redownload. -" - return 255 - fi - - mount -o loop squashfs/LiveOS/rootfs.img stage0 - - if [[ $? != 0 ]] - then - echo " -Mount of LiveOS stage0 rootfs image failed! LiveOS download may be corrupt. -Remove ${cache_base}/LiveOS to force a new download or -troubleshoot cached image and then rerun process. -" - return 255 - fi - - -### Stage 1 setup. -# Copy stage0 (which is ro) to stage1 area (rw) for modification. -# Unmount stage0 mounts - we're done with stage 0 at this point. -# Download our rpm and yum rpm packages. -# Force install of rpm and yum into stage1 image (dirty hack!) - - echo "Stage 0 complete, building Stage 1 image... -This will take a couple of minutes. Patience..." - - echo "Creating Stage 1 r/w copy of r/o Stage 0 squashfs image from LiveOS." - - rsync -aAHS stage0/. stage1/ - - umount stage0 - umount squashfs - - cd stage1 - - # Setup stage1 image with pieces to run installs... - - - mount -o bind /dev dev - mount -t proc proc proc - # Always make sure /etc/resolv.conf is up to date in the target! - cp /etc/resolv.conf etc/ - - mkdir run/install - - echo "Updating Stage 1 image with full rpm and yum packages" - - # Retrieve our 2 rpm packages we need to force down the throat - # of this LiveOS image we're camped out on. This is the beginning - # of the butt ugly hack. Look close or you may missing it... - - rsync -av ${mirrorurl}/fedora/linux/releases/20/Fedora/$basearch/os/Packages/r/rpm-[0-9]* \ - ${mirrorurl}/fedora/linux/releases/20/Fedora/$basearch/os/Packages/y/yum-[0-9]* . - - # And here it is... - # The --nodeps is STUPID but F15 had a bogus dependency on RawHide?!?! - chroot . rpm -ivh --nodeps rpm-* yum-* - # Did you catch it? - - # The LiveOS image contains rpm (but not rpmdb) and yum (but not - # yummain.py - What the hell good does yum do with no - # yummain.py?!?! - Sigh...). It contains all the supporting - # pieces but the rpm database has not be initialized and it - # doesn't know all the dependences (seem to) have been met. - # So we do a "--nodeps" rpm install in the chrooted environment - # to force the installation of the full rpm and yum packages. - # - # For the purists - Yes, I know the rpm database is wildly out - # of whack now. That's why this is a butt ugly hack / dirty trick. - # But, this is just the stage1 image that we are going to discard as - # soon as the stage2 image is built, so we don't care. All we care - # is that the stage2 image ends up with all the pieces it need to - # run yum and rpm and that the stage2 rpm database is coherent. - # - # NOW we can really go to work! - -### Stage 2 setup. -# Download our Fedora Release rpm packages. -# Install fedora-release into bootstrap to initialize fs and databases. -# Install rpm, and yum into bootstrap image using yum - - echo "Stage 1 creation complete. Building stage 2 Installation Bootstrap" - - mount -o bind ../bootstrap run/install - rsync -av ${mirrorurl}/fedora/linux/releases/20/Fedora/$basearch/os/Packages/f/fedora-release-20* . - - # The --nodeps is STUPID but F15 had a bogus dependency on RawHide?!?! - chroot . rpm --root /run/install --nodeps -ivh fedora-release-* - - # yum will take $basearch from host, so force the arch we want - sed -i "s|\$basearch|$basearch|" ./run/install/etc/yum.repos.d/* - - chroot . yum -y --nogpgcheck --installroot /run/install install python rpm yum - - umount run/install - umount proc - umount dev - -# That's it! We should now have a viable installation BOOTSTRAP in -# bootstrap We'll do a yum update in that to verify and then -# move it to the cache location before cleaning up. - - cd ../bootstrap - mount -o bind /dev dev - mount -t proc proc proc - # Always make sure /etc/resolv.conf is up to date in the target! - cp /etc/resolv.conf etc/ - - # yum will take $basearch from host, so force the arch we want - sed -i "s|\$basearch|$basearch|" ./etc/yum.repos.d/* - - chroot . yum -y update - - RC=$? - - umount proc - umount dev - - cd .. - - if [[ ${RC} != 0 ]] - then - echo " -Build of Installation Bootstrap failed. Temp directory -not removed so it can be investigated. -" - return 255 - fi - - # We know have a working run time environment in rootfs... - mv bootstrap .. - cd .. - rm -rf ${TMP_BOOTSTRAP_DIR} - - echo " -Build of Installation Bootstrap complete! We now return you to your -normally scheduled template creation. -" - - BOOTSTRAP=1 - BOOTSTRAP_DIR="${cache_base}/bootstrap" - BOOTSTRAP_CHROOT="chroot ${BOOTSTRAP_DIR} " - BOOTSTRAP_INSTALL_ROOT=/run/install - - return 0 -} - - -fedora_bootstrap_mounts() -{ - if [[ ${BOOTSTRAP} -ne 1 ]] - then - return 0 - fi - - BOOTSTRAP_CHROOT="chroot ${BOOTSTRAP_DIR} " - - echo "Mounting Bootstrap mount points" - - [[ -d ${BOOTSTRAP_DIR}/run/install ]] || mkdir -p ${BOOTSTRAP_DIR}/run/install - - mount -o bind ${INSTALL_ROOT} ${BOOTSTRAP_DIR}/run/install - mount -o bind /dev ${BOOTSTRAP_DIR}/dev - mount -t proc proc ${BOOTSTRAP_DIR}/proc - # Always make sure /etc/resolv.conf is up to date in the target! - cp /etc/resolv.conf ${BOOTSTRAP_DIR}/etc/ -} - -fedora_bootstrap_umounts() -{ - if [[ ${BOOTSTRAP} -ne 1 ]] - then - return 0 - fi - - umount ${BOOTSTRAP_DIR}/proc - umount ${BOOTSTRAP_DIR}/dev - umount ${BOOTSTRAP_DIR}/run/install -} - - -# This is the code to create the initial roofs for Fedora. It may -# require a run time environment by calling the routines above... - -download_fedora() -{ - - # check the mini fedora was not already downloaded - INSTALL_ROOT=$cache/partial - mkdir -p $INSTALL_ROOT - if [ $? -ne 0 ]; then - echo "Failed to create '$INSTALL_ROOT' directory" - return 1 - fi - - # download a mini fedora into a cache - echo "Downloading fedora minimal ..." - - # These will get changed if it's decided that we need a - # boostrap environment (can not build natively). These - # are the defaults for the non-boostrap (native) mode. - - BOOTSTRAP_INSTALL_ROOT=${INSTALL_ROOT} - BOOTSTRAP_CHROOT= - BOOTSTRAP_DIR= - - PKG_LIST="yum initscripts passwd rsyslog vim-minimal openssh-server openssh-clients dhclient chkconfig rootfiles policycoreutils fedora-release" - MIRRORLIST_URL="http://mirrors.fedoraproject.org/mirrorlist?repo=fedora-$release&arch=$basearch" - - if [[ ${release} -lt 17 ]] - then - # The reflects the move of db_dump and db_load from db4_utils to - # libdb_utils in Fedora 17 and above and it's inclusion as a dep... - # Prior to Fedora 11, we need to explicitly include it! - PKG_LIST="${PKG_LIST} db4-utils" - fi - - if [[ ${release} -ge 21 ]] - then - # Since Fedora 21, a separate fedora-repos package is needed. - # Before, the information was conained in fedora-release. - PKG_LIST="${PKG_LIST} fedora-repos" - fi - - DOWNLOAD_OK=no - - # We're splitting the old loop into two loops plus a directory retrival. - # First loop... Try and retrive a mirror list with retries and a slight - # delay between attempts... - for trynumber in 1 2 3 4; do - [ $trynumber != 1 ] && echo "Trying again..." - # This code is mildly "brittle" in that it assumes a certain - # page format and parsing HTML. I've done worse. :-P - MIRROR_URLS=$(curl -s -S -f "$MIRRORLIST_URL" | sed -e '/^http:/!d' -e '2,6!d') - if [ $? -eq 0 ] && [ -n "$MIRROR_URLS" ] - then - break - fi - - echo "Failed to get a mirror on try $trynumber" - sleep 3 - done - - # This will fall through if we didn't get any URLS above - for MIRROR_URL in ${MIRROR_URLS} - do - if [ "$release" -gt "16" ]; then - RELEASE_URL="$MIRROR_URL/Packages/f" - else - RELEASE_URL="$MIRROR_URL/Packages/" - fi - - echo "Fetching release rpm name from $RELEASE_URL..." - # This code is mildly "brittle" in that it assumes a certain directory - # page format and parsing HTML. I've done worse. :-P - RELEASE_RPM=$(curl -L -f "$RELEASE_URL" | sed -e "/fedora-release-${release}-/!d" -e 's/.*.*//' ) - if [ $? -ne 0 -o "${RELEASE_RPM}" = "" ]; then - echo "Failed to identify fedora release rpm." - continue - fi - - echo "Fetching fedora release rpm from ${RELEASE_URL}/${RELEASE_RPM}......" - curl -L -f "${RELEASE_URL}/${RELEASE_RPM}" > ${INSTALL_ROOT}/${RELEASE_RPM} - if [ $? -ne 0 ]; then - echo "Failed to download fedora release rpm ${RELEASE_RPM}." - continue - fi - - # F21 and newer need fedora-repos in addition to fedora-release. - if [ "$release" -ge "21" ]; then - echo "Fetching repos rpm name from $RELEASE_URL..." - REPOS_RPM=$(curl -L -f "$RELEASE_URL" | sed -e "/fedora-repos-${release}-/!d" -e 's/.*.*//' ) - if [ $? -ne 0 -o "${REPOS_RPM}" = "" ]; then - echo "Failed to identify fedora repos rpm." - continue - fi - - echo "Fetching fedora repos rpm from ${RELEASE_URL}/${REPOS_RPM}..." - curl -L -f "${RELEASE_URL}/${REPOS_RPM}" > ${INSTALL_ROOT}/${REPOS_RPM} - if [ $? -ne 0 ]; then - echo "Failed to download fedora repos rpm ${RELEASE_RPM}." - continue - fi - fi - - - DOWNLOAD_OK=yes - break - done - - if [ $DOWNLOAD_OK != yes ]; then - echo "Aborting" - return 1 - fi - - mkdir -p ${INSTALL_ROOT}/var/lib/rpm - - if ! fedora_get_bootstrap - then - echo "Fedora Bootstrap setup failed" - return 1 - fi - - fedora_bootstrap_mounts - - ${BOOTSTRAP_CHROOT}rpm --root ${BOOTSTRAP_INSTALL_ROOT} --initdb - - # The --nodeps is STUPID but F15 had a bogus dependency on RawHide?!?! - ${BOOTSTRAP_CHROOT}rpm --root ${BOOTSTRAP_INSTALL_ROOT} --nodeps -ivh ${BOOTSTRAP_INSTALL_ROOT}/${RELEASE_RPM} - - # F21 and newer need fedora-repos in addition to fedora-release... - # Note that fedora-release and fedora-system have a mutual dependency. - # So installing the reops package after the release package we can - # spare one --nodeps. - if [ "$release" -ge "21" ]; then - ${BOOTSTRAP_CHROOT}rpm --root ${BOOTSTRAP_INSTALL_ROOT} -ivh ${BOOTSTRAP_INSTALL_ROOT}/${REPOS_RPM} - fi - - # yum will take $basearch from host, so force the arch we want - sed -i "s|\$basearch|$basearch|" ${BOOTSTRAP_DIR}/${BOOTSTRAP_INSTALL_ROOT}/etc/yum.repos.d/* - - ${BOOTSTRAP_CHROOT}yum --installroot ${BOOTSTRAP_INSTALL_ROOT} -y --nogpgcheck install ${PKG_LIST} - - RC=$? - - if [[ ${BOOTSTRAP} -eq 1 ]] - then - # Here we have a bit of a sticky problem. We MIGHT have just installed - # this template cache using versions of yum and rpm in the bootstrap - # chroot that use a different database version than the target version. - # That can be a very big problem. Solution is to rebuild the rpmdatabase - # with the target database now that we are done building the cache. In the - # vast majority of cases, this is a do-not-care with no harm done if we - # didn't do it. But it catches several corner cases with older unsupported - # releases and it really doesn't cost us a lot of time for a one shot - # install that will never be done again for this rev. - # - # Thanks and appreciation to Dwight Engen and the Oracle template for the - # database rewrite hint! - - echo "Fixing up rpm databases" - - # Change to our target install directory (if we're not already - # there) just to simplify some of the logic to follow... - cd ${INSTALL_ROOT} - - rm -f var/lib/rpm/__db* - # Programmers Note (warning): - # - # Pay careful attention to the following commands! It - # crosses TWO chroot boundaries linked by a bind mount! - # In the bootstrap case, that's the bind mount of ${INSTALL_ROOT} - # to the ${BOOTSTRAP_CHROOT}/run/install directory! This is - # a deliberate hack across that bind mount to do a database - # translation between two environments, neither of which may - # be the host environment! It's ugly and hard to follow but, - # if you don't understand it, don't mess with it! The pipe - # is in host space between the two chrooted environments! - # This is also why we cd'ed into the INSTALL_ROOT directory - # in advance of this loop, so everything is relative to the - # current working directory and congruent with the same working - # space in both chrooted environments. The output into the new - # db is also done in INSTALL_ROOT space but works in either host - # space or INSTALL_ROOT space for the mv, so we don't care. It's - # just not obvious what's happening in the db_dump and db_load - # commands... - # - for db in var/lib/rpm/* ; do - ${BOOTSTRAP_CHROOT} db_dump ${BOOTSTRAP_INSTALL_ROOT}/$db | chroot . db_load $db.new - mv $db.new $db - done - # finish up by rebuilding the database... - # This should be redundant but we do it for completeness and - # any corner cases I may have missed... - mount -t proc proc proc - mount -o bind /dev dev - chroot . rpm --rebuilddb - umount dev - umount proc - fi - - fedora_bootstrap_umounts - - if [ ${RC} -ne 0 ]; then - echo "Failed to download the rootfs, aborting." - return 1 - fi - - mv "$INSTALL_ROOT" "$cache/rootfs" - echo "Download complete." - - return 0 -} - -copy_fedora() -{ - - # make a local copy of the minifedora - echo -n "Copying rootfs to $rootfs_path ..." - #cp -a $cache/rootfs-$basearch $rootfs_path || return 1 - # i prefer rsync (no reason really) - mkdir -p $rootfs_path - rsync -SHaAX $cache/rootfs/ $rootfs_path/ - echo - return 0 -} - -update_fedora() -{ - mount -o bind /dev ${cache}/rootfs/dev - mount -t proc proc ${cache}/rootfs/proc - # Always make sure /etc/resolv.conf is up to date in the target! - cp /etc/resolv.conf ${cache}/rootfs/etc/ - chroot ${cache}/rootfs yum -y update - umount ${cache}/rootfs/proc - umount ${cache}/rootfs/dev -} - -install_fedora() -{ - mkdir -p @LOCALSTATEDIR@/lock/subsys/ - ( - flock -x 9 - if [ $? -ne 0 ]; then - echo "Cache repository is busy." - return 1 - fi - - echo "Checking cache download in $cache/rootfs ... " - if [ ! -e "$cache/rootfs" ]; then - download_fedora - if [ $? -ne 0 ]; then - echo "Failed to download 'fedora base'" - return 1 - fi - else - echo "Cache found. Updating..." - update_fedora - if [ $? -ne 0 ]; then - echo "Failed to update 'fedora base', continuing with last known good cache" - else - echo "Update finished" - fi - fi - - echo "Copy $cache/rootfs to $rootfs_path ... " - copy_fedora - if [ $? -ne 0 ]; then - echo "Failed to copy rootfs" - return 1 - fi - - return 0 - ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-fedora - - return $? -} - -# Generate a random hardware (MAC) address composed of FE followed by -# 5 random bytes... -create_hwaddr() -{ - openssl rand -hex 5 | sed -e 's/\(..\)/:\1/g; s/^/fe/' -} - -copy_configuration() -{ - mkdir -p $config_path - - grep -q "^lxc.rootfs.path" $config_path/config 2>/dev/null || echo " -lxc.rootfs.path = $rootfs_path -" >> $config_path/config - - # The following code is to create static MAC addresses for each - # interface in the container. This code will work for multiple - # interfaces in the default config. It will also strip any - # hwaddr stanzas out of the default config since we can not share - # MAC addresses between containers. - mv $config_path/config $config_path/config.def - while read LINE - do - # This should catch variable expansions from the default config... - if expr "${LINE}" : '.*\$' > /dev/null 2>&1 - then - LINE=$(eval "echo \"${LINE}\"") - fi - - # There is a tab and a space in the regex bracket below! - # Seems that \s doesn't work in brackets. - KEY=$(expr "${LINE}" : '\s*\([^ ]*\)\s*=') - - if [[ "${KEY}" != "lxc.net.0.hwaddr" ]] - then - echo "${LINE}" >> $config_path/config - - if [[ "${KEY}" == "lxc.net.0.link" ]] - then - echo "lxc.net.0.hwaddr = $(create_hwaddr)" >> $config_path/config - fi - fi - done < $config_path/config.def - - rm -f $config_path/config.def - - if [ -e "@LXCTEMPLATECONFIG@/fedora.common.conf" ]; then - echo " -# Include common configuration -lxc.include = @LXCTEMPLATECONFIG@/fedora.common.conf -" >> $config_path/config - fi - - # Append things which require expansion here... - cat <> $config_path/config -lxc.arch = $arch -lxc.uts.name = $utsname - -# When using LXC with apparmor, uncomment the next line to run unconfined: -#lxc.apparmor.profile = unconfined - -# example simple networking setup, uncomment to enable -#lxc.net.0.type = $lxc_network_type -#lxc.net.0.flags = up -#lxc.net.0.link = $lxc_network_link -#lxc.net.0.name = eth0 -# Additional example for veth network type -# static MAC address, -#lxc.net.0.hwaddr = 00:16:3e:77:52:20 -# persistent veth device name on host side -# Note: This may potentially collide with other containers of same name! -#lxc.net.0.veth.pair = v-$name-e0 - -EOF - - if [ $? -ne 0 ]; then - echo "Failed to add configuration" - return 1 - fi - - return 0 -} - -clean() -{ - - if [ ! -e $cache ]; then - exit 0 - fi - - # lock, so we won't purge while someone is creating a repository - ( - flock -x 9 - if [ $? != 0 ]; then - echo "Cache repository is busy." - exit 1 - fi - - echo -n "Purging the download cache for Fedora-$release..." - rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1 - exit 0 - ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-fedora -} - -usage() -{ - cat < - [-p|--path=] [-c|--clean] [-R|--release=] - [--fqdn=] [-a|--arch=] - [--mask-tmp] - [-h|--help] -Mandatory args: - -n,--name container name, used to as an identifier for that container -Optional args: - -p,--path path to where the container will be created, - defaults to @LXCPATH@. - --rootfs path for actual rootfs. - -c,--clean clean the cache - -R,--release Fedora release for the new container. - Defaults to host's release if the host is Fedora. - --fqdn fully qualified domain name (FQDN) for DNS and system naming - -a,--arch Define what arch the container will be [i686,x86_64] - --mask-tmp Prevent systemd from over-mounting /tmp with tmpfs. - -h,--help print this help -EOF - return 0 -} - -options=$(getopt -o a:hp:n:cR: -l help,path:,rootfs:,name:,clean,release:,arch:,fqdn:,mask-tmp -- "$@") -if [ $? -ne 0 ]; then - usage $(basename $0) - exit 1 -fi - -arch=$(uname -m) -masktmp=0 - -eval set -- "$options" -while true -do - case "$1" in - -h|--help) usage $0 && exit 0;; - -p|--path) path=$2; shift 2;; - --rootfs) rootfs_path=$2; shift 2;; - -n|--name) name=$2; shift 2;; - -c|--clean) clean=1; shift 1;; - -R|--release) release=$2; shift 2;; - -a|--arch) newarch=$2; shift 2;; - --fqdn) utsname=$2; shift 2;; - --mask-tmp) masktmp=1; shift 1;; - --) shift 1; break ;; - *) break ;; - esac -done - -if [ ! -z "$clean" -a -z "$path" ]; then - clean || exit 1 - exit 0 -fi - -basearch=${arch} -# Map a few architectures to their generic Fedora repository archs. -# The two ARM archs are a bit of a guesstimate for the v5 and v6 -# archs. V6 should have hardware floating point (Rasberry Pi). -# The "arm" arch is safer (no hardware floating point). So -# there may be cases where we "get it wrong" for some v6 other -# than RPi. -case "$arch" in -i686) basearch=i386 ;; -armv3l|armv4l|armv5l) basearch=arm ;; -armv6l|armv7l|armv8l) basearch=armhfp ;; -*) ;; -esac - -mirrorurl="archives.fedoraproject.org::fedora-archive" -case "$basearch" in -ppc64|s390x) mirrorurl="archives.fedoraproject.org::fedora-secondary" ;; -*) ;; -esac - -# Somebody wants to specify an arch. This is very limited case. -# i386/i586/i686 on i386/x86_64 -# - or - -# x86_64 on x86_64 -if [ "${newarch}" != "" -a "${newarch}" != "${arch}" ] -then - case "${newarch}" in - i386|i586|i686) - if [ "${basearch}" = "i386" -o "${basearch}" = "x86_64" ] - then - # Make the arch a generic x86 32 bit... - arch=${newarch} - basearch=i386 - else - basearch=bad - fi - ;; - *) - basearch=bad - ;; - esac - - if [ "${basearch}" = "bad" ] - then - echo "You cannot build a ${newarch} Fedora container on a ${arch} host. Sorry!" - exit 1 - fi -fi - -# Allow the cache base to be set by environment variable -cache_base=${LXC_CACHE_PATH:-"@LOCALSTATEDIR@/cache/lxc"}/fedora/$basearch - -# Let's do something better for the initial root password. -# It's not perfect but it will defeat common scanning brute force -# attacks in the case where ssh is exposed. It will also be set to -# expired, forcing the user to change it at first login. -if [ "${root_password}" = "" ] -then - root_password=Root-${name}-${RANDOM} -else - # If it's got a ding in it, try and expand it! - if [ $(expr "${root_password}" : '.*$.') != 0 ] - then - root_password=$(eval echo "${root_password}") - fi - - # 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 - root_password=$(mktemp -u ${root_password}) - fi -fi - -if [ -z "${utsname}" ]; then - utsname=${name} -fi - -# This follows a standard "resolver" convention that an FQDN must have -# at least two dots or it is considered a local relative host name. -# If it doesn't, append the dns domain name of the host system. -# -# This changes one significant behavior when running -# "lxc_create -n Container_Name" without using the -# --fqdn option. -# -# Old behavior: -# utsname and hostname = Container_Name -# New behavior: -# utsname and hostname = Container_Name.Domain_Name - -if [ $(expr "$utsname" : '.*\..*\.') = 0 ]; then - if [[ "$(dnsdomainname)" != "" && "$(dnsdomainname)" != "localdomain" ]]; then - utsname=${utsname}.$(dnsdomainname) - fi -fi - -needed_pkgs="" - -type curl >/dev/null 2>&1 -if [ $? -ne 0 ]; then - needed_pkgs="curl $needed_pkgs" -fi -type openssl >/dev/null 2>&1 -if [ $? -ne 0 ]; then - needed_pkgs="openssl $needed_pkgs" -fi - -if [ -n "$needed_pkgs" ]; then - echo "Missing commands: $needed_pkgs" - echo "Please install these using \"sudo yum install $needed_pkgs\"" - exit 1 -fi - -if [ -z "$path" ]; then - path=$default_path/$name -fi - -if [ -z "$release" ]; then - if [ "$is_fedora" -a "$fedora_host_ver" ]; then - release=$fedora_host_ver - else - echo "This is not a fedora host and release missing, defaulting to 22 use -R|--release to specify release" - release=22 - fi -fi - -if [ "$(id -u)" != "0" ]; then - echo "This script should be run as 'root'" - exit 1 -fi - -if [ -z "$rootfs_path" ]; then - rootfs_path=$path/rootfs - # check for 'lxc.rootfs.path' passed in through default config by lxc-create - if grep -q '^lxc.rootfs.path' $path/config 2>/dev/null ; then - rootfs_path=$(sed -e '/^lxc.rootfs.path\s*=/!d' -e 's/\s*#.*//' \ - -e 's/^lxc.rootfs.path\s*=\s*//' -e q $path/config) - fi -fi -config_path=$path -cache=$cache_base/$release - -revert() -{ - echo "Interrupted, so cleaning up" - lxc-destroy -n $name - # maybe was interrupted before copy config - rm -rf $path - echo "exiting..." - exit 1 -} - -trap revert SIGHUP SIGINT SIGTERM - -copy_configuration -if [ $? -ne 0 ]; then - echo "failed write configuration file" - exit 1 -fi - -install_fedora -if [ $? -ne 0 ]; then - echo "failed to install fedora" - exit 1 -fi - -configure_fedora -if [ $? -ne 0 ]; then - echo "failed to configure fedora for a container" - exit 1 -fi - -# If the systemd configuration directory exists - set it up for what we need. -if [ -d ${rootfs_path}/etc/systemd/system ] -then - configure_fedora_systemd -fi - -# This configuration (rc.sysinit) is not inconsistent with the systemd stuff -# above and may actually coexist on some upgraded systems. Let's just make -# sure that, if it exists, we update this file, even if it's not used... -if [ -f ${rootfs_path}/etc/rc.sysinit ] -then - configure_fedora_init -fi - -if [ ! -z "$clean" ]; then - clean || exit 1 - exit 0 -fi -echo " -Container rootfs and config have been created. -Edit the config file to check/enable networking setup. -" - -if [[ -d ${cache_base}/bootstrap ]] -then - echo "You have successfully built a Fedora container and cache. This cache may -be used to create future containers of various revisions. The directory -${cache_base}/bootstrap contains a bootstrap -which may no longer needed and can be removed. -" -fi - -if [[ -e ${cache_base}/LiveOS ]] -then - echo "A LiveOS directory exists at ${cache_base}/LiveOS. -This is only used in the creation of the bootstrap run-time-environment -and may be removed. -" -fi - -if [ ${root_display_password} = "yes" ] -then - echo "The temporary password for root is: '$root_password' - -You may want to note that password down before starting the container. -" -fi - -if [ ${root_store_password} = "yes" ] -then - echo "The temporary root password is stored in: - - '${config_path}/tmp_root_pass' -" -fi - -if [ ${root_prompt_password} = "yes" ] -then - echo "Invoking the passwd command in the container to set the root password. - - chroot ${rootfs_path} passwd -" - chroot ${rootfs_path} passwd -else - if [ ${root_expire_password} = "yes" ] - then - if ( mountpoint -q -- "${rootfs_path}" ) - then - echo "To reset the root password, you can do: - - lxc-start -n ${name} - lxc-attach -n ${name} -- passwd - lxc-stop -n ${name} -" - else - echo " -The root password is set up as "expired" and will require it to be changed -at first login, which you should do as soon as possible. If you lose the -root password or wish to change it without starting the container, you -can change it from the host by running the following command (which will -also reset the expired flag): - - chroot ${rootfs_path} passwd -" - fi - fi -fi diff --git a/templates/lxc-fedora.in b/templates/lxc-fedora.in deleted file mode 100644 index 10b90b1e5..000000000 --- a/templates/lxc-fedora.in +++ /dev/null @@ -1,1291 +0,0 @@ -#!/bin/bash - -# -# template script for generating Fedora container for LXC -# - -# -# lxc: linux Container library - -# Authors: -# Daniel Lezcano -# Ramez Hanna -# Michael H. Warfield -# Reto Gantenbein - -# 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 - -# configurations -FEDORA_RELEASE_MIN=24 -FEDORA_RELEASE_DEFAULT=${FEDORA_RELEASE_DEFAULT:-25} -FEDORA_RSYNC_URL="${FEDORA_RSYNC_URL:-archives.fedoraproject.org::fedora-enchilada}" -MIRRORLIST_URL=${MIRRORLIST_URL:-https://mirrors.fedoraproject.org/mirrorlist} - -local_state_dir="@LOCALSTATEDIR@" -lxc_path="@LXCPATH@" -lxc_template_config="@LXCTEMPLATECONFIG@" -lxc_default_conf="@LXC_DEFAULT_CONFIG@" - -# allows the cache directory to be set by environment variable -LXC_CACHE_PATH="${LXC_CACHE_PATH:-"${local_state_dir}/cache/lxc"}" - -# these are only going into comments in the resulting config... -lxc_network_type=veth -lxc_network_link=lxcbr0 - -# Some combinations of the tuning knobs below do not exactly make sense. -# but that's ok. -# -# If the "root_password" is non-blank, use it, else set a default. -# This can be passed to the script as an environment variable and is -# set by a shell conditional assignment. Looks weird but it is what it is. -# -# 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 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. -# If root_store_password = yes, store it in the configuration directory -# If root_prompt_password = yes, invoke "passwd" to force the user to change -# the root password after the container is created. -# If root_expire_password = yes, you will be prompted to change the root -# password at the first login. -# -# These are conditional assignments... The can be overridden from the -# preexisting environment variables... -# -# Make sure this is in single quotes to defer expansion to later! -# :{root_password='Root-${name}-${RANDOM}'} -: "${root_password='Root-${name}-XXXXXX'}" - -# Now, it doesn't make much sense to display, store, and force change -# together. But, we gotta test, right??? -: "${root_display_password='no'}" -: "${root_store_password='yes'}" -# Prompting for something interactive has potential for mayhem -# with users running under the API... Don't default to "yes" -: "${root_prompt_password='no'}" - -# Expire root password? Default to yes, but can be overridden from -# the environment variable -: "${root_expire_password='yes'}" - -# detect use under userns (unsupported) -for arg in "$@"; do - [ "${arg}" = "--" ] && break - if [ "${arg}" = "--mapped-uid" ] || [ "${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 - -# dnf package manager arguments -dnf_args=( --assumeyes --best --allowerasing --disablerepo=* --enablerepo=fedora --enablerepo=updates ) - -# This function is going to setup a minimal host-arch native Fedora bootstrap -# environment which will be used to create new containers on non-Fedora hosts. -# -bootstrap_fedora() -{ - local cache="${1}" - - local bootstrap="${cache}/bootstrap" - if [ -d "${bootstrap}" ] - then - echo "Existing Fedora bootstrap environment found. Testing ..." - if chroot_update_fedora "${bootstrap}" - then - CHROOT_DIR="${bootstrap}" - CHROOT_CMD="chroot ${CHROOT_DIR} " - - echo "Bootstrap environment appears to be functional." - return 0 - else - echo "Error: Bootstrap environment detected in ${bootstrap}" - echo "but appears to be non-functional. Please remove and restart." - return 1 - fi - fi - - echo "Setting up new Fedora ${FEDORA_RELEASE_DEFAULT} (${basearch}) bootstrap environment." - - [[ -d "${cache}" ]] || mkdir -p "${cache}" - - tmp_bootstrap_dir=$( mktemp -d --tmpdir="${cache}" bootstrap_XXXXXX ) - pushd "${tmp_bootstrap_dir}" >/dev/null - - mkdir squashfs liveos bootstrap - - # download the LiveOS squashfs image - if [ ! -f "${cache}/install.img" ] - then - local os_path="linux/releases/${FEDORA_RELEASE_DEFAULT}/Everything/${basearch}/os" - local image_path="images/install.img" - local ret=1 - - if [ -n "${rsync}" ] - then - echo "Syncing LiveOS squashfs image from ${FEDORA_RSYNC_URL} ... " - rsync --archive --info=progress "${FEDORA_RSYNC_URL}/${os_path}/${image_path}" . - ret=$? - else - if [ -z "${mirror}" ] - then - get_mirrors "${FEDORA_RELEASE_DEFAULT}" "${basearch}" || return $? - else - local mirror_url="${mirror}/${os_path}" - fi - for url in ${mirror:-${mirror_urls}} - do - echo "Downloading LiveOS squashfs image from ${url} ... " - curl --silent --show-error --fail --remote-name "${url}/${image_path}" - ret=$? - if [ ${ret} -ne 0 ] - then - continue - else - break - fi - done - fi - - if [ "${ret}" != 0 ] || [ ! -s install.img ] - then - echo "Error: Download of squashfs image failed." - return 1 - fi - mv install.img "${cache}/" - else - echo "Using cached LiveOS squashfs image." - fi - - echo "Mounting LiveOS squashfs file system." - if ! mount -o loop -t squashfs "${cache}/install.img" squashfs/ - then - echo " -Error: Mount of LiveOS squashfs image failed --------------------------------------------- -You must have squashfs support available to mount image. LiveOS image is now -cached. Process may be rerun without penalty of downloading LiveOS again. If -LiveOS is corrupt, remove ${cache}/install.img -" - return 1 - fi - - # mount contained LiveOS - if ! mount -o loop squashfs/LiveOS/rootfs.img liveos - then - echo " -Error: Mount of LiveOS stage0 rootfs image failed -------------------------------------------------- -LiveOS download may be corrupt. Remove ${cache}/LiveOS -to force a new download. -" - return 1 - fi - - echo "Copying LiveOS content to bootstrap environment ... " - if ! rsync --archive --acls --hard-links --sparse liveos/. bootstrap/ - then - echo "Error: Build of bootstrap environment failed." - echo "Keeping directory ${tmp_bootstrap_dir} for your investigation." - exit 1 - fi - - # unmount liveos mounts - we're done with liveos at this point - umount liveos - umount squashfs - - # customize bootstrap rootfs - pushd bootstrap >/dev/null - - # setup repositories in bootstrap chroot - CHROOT_DIR="$(pwd)" - CHROOT_CMD="chroot ${CHROOT_DIR} " - INSTALL_ROOT="/" - if ! setup_repositories "${cache}" "${basearch}" "${FEDORA_RELEASE_DEFAULT}" "${mirror}" - then - echo "Error: Failed to configure repositories in ${CHROOT_DIR}${INSTALL_ROOT}" - exit 1 - fi - if [ -n "${mirror}" ] - then - set_dnf_mirror_url ./etc/yum.repos.d/fedora*.repo - fi - - # make sure /etc/resolv.conf is up to date in the chroot - cp /etc/resolv.conf ./etc/ - - # verify bootstrap chroot by running a dnf update - chroot_update_fedora "$(pwd)" - ret=$? - - popd >/dev/null - - if [ "${ret}" != 0 ] - then - echo "Error: Build of bootstrap environment failed." - echo "Keeping directory ${tmp_bootstrap_dir} for your investigation." - return 1 - fi - - mv bootstrap "${cache}" - - popd >/dev/null - rm -rf "${tmp_bootstrap_dir}" - - CHROOT_DIR="${bootstrap}" - CHROOT_CMD="chroot ${CHROOT_DIR} " - - echo "Fedora bootstrap environment successfully created." - return 0 -} - -chroot_mounts() -{ - test -n "${1}" && local chroot="${1}" || return 1 - - mount -t proc proc "${chroot}/proc" && - mount -o bind /dev "${chroot}/dev" -} - -chroot_umounts() -{ - test -n "${1}" && local chroot="${1}" || return 1 - - umount "${chroot}/proc" && - umount "${chroot}/dev" -} - -clean_cache() -{ - local cache="${1}" - - test ! -e "${cache}" && return 0 - - # lock, so we won't purge while someone is creating a repository - ( - if ! flock -x 9 - then - echo "Error: Cache repository is busy." - exit 1 - fi - - echo -n "Purging the Fedora bootstrap and download cache ... " - rm --preserve-root --one-file-system -rf "${cache}" && echo "Done." || exit 1 - - exit 0 - - ) 9>"${local_state_dir}/lock/subsys/lxc-fedora" - - return $? -} - -# Customize container rootfs -# -configure_fedora() -{ - local rootfs="${1}" - local release="${2}" - local utsname="${3}" - - # disable selinux - mkdir -p "${rootfs}/selinux" - echo 0 > "${rootfs}/selinux/enforce" - - # also kill it in the /etc/selinux/config file if it's there... - if [ -f "${rootfs}/etc/selinux/config" ] - then - sed -i '/^SELINUX=/s/.*/SELINUX=disabled/' "${rootfs}/etc/selinux/config" - fi - - # nice catch from Dwight Engen in the Oracle template. - # wantonly plagerized here with much appreciation. - if [ -f "${rootfs}/usr/sbin/selinuxenabled" ] - then - rm -f "${rootfs}/usr/sbin/selinuxenabled" - ln -s /bin/false "${rootfs}/usr/sbin/selinuxenabled" - fi - - # set hostname - echo "${utsname}" > "${rootfs}/etc/hostname" - - # set default localtime to the host localtime if not set... - if [ -e /etc/localtime ] && [ ! -e "${rootfs}/etc/localtime" ] - then - # if /etc/localtime is a symlink, this should preserve it. - cp -a /etc/localtime "${rootfs}/etc/localtime" - fi - - # set minimal hosts - cat < "${rootfs}/etc/hosts" -127.0.0.1 localhost.localdomain localhost ${utsname} -::1 localhost6.localdomain6 localhost6 -EOF - - # setup console and tty[1-4] for login. note that /dev/console and - # /dev/tty[1-4] will be symlinks to the ptys /dev/lxc/console and - # /dev/lxc/tty[1-4] so that package updates can overwrite the symlinks. - # lxc will maintain these links and bind mount ptys over /dev/lxc/* - # since lxc.tty.dir is specified in the config. - - # allow root login on console, tty[1-4], and pts/0 for libvirt - cat <> "${rootfs}/etc/securetty" -# LXC (Linux Containers) -lxc/console -lxc/tty1 -lxc/tty2 -lxc/tty3 -lxc/tty4 -# For libvirt/Virtual Machine Monitor -pts/0 -EOF - - if [ "${root_display_password}" = yes ] - then - echo "Setting root password to '$root_password'" - fi - if [ "${root_store_password}" = yes ] - then - touch "${path}/tmp_root_pass" - chmod 600 "${path}/tmp_root_pass" - echo "${root_password}" > "${path}/tmp_root_pass" - echo "Storing root password in '${path}/tmp_root_pass'" - fi - - echo "root:$root_password" | chroot "${rootfs}" chpasswd - - if [ "${root_expire_password}" = yes ] - then - # also set this password as expired to force the user to change it! - chroot "${rootfs}" passwd -e root - fi - - chroot_mounts "${rootfs}" - - # always make sure /etc/resolv.conf is up to date in the target! - cp /etc/resolv.conf "${rootfs}/etc/" - - # rebuild the rpm database based on the target rpm version... - rm -f "${rootfs}"/var/lib/rpm/__db* - chroot "${rootfs}" rpm --rebuilddb - - chroot_umounts "${rootfs}" - - # default systemd target - chroot "${rootfs}" ln -s /lib/systemd/system/multi-user.target \ - /etc/systemd/system/default.target - - # enable networking via systemd-networkd - test -d "${rootfs}/etc/systemd/network" || mkdir "${rootfs}/etc/systemd/network" - cat < "${rootfs}/etc/systemd/network/eth0.network" -[Match] -Name=eth0 - -[Network] -DHCP=both -EOF - mkdir -p "${rootfs}/etc/systemd/system/socket.target.wants" - chroot "${rootfs}" ln -s /usr/lib/systemd/system/systemd-networkd.socket \ - /etc/systemd/system/socket.target.wants/systemd-networkd.socket - chroot "${rootfs}" ln -s /usr/lib/systemd/system/systemd-networkd.service \ - /etc/systemd/system/multi-user.target.wants/systemd-networkd.service - mkdir -p "${rootfs}/etc/systemd/system/network-online.target.wants" - chroot "${rootfs}" ln -s /usr/lib/systemd/system/systemd-networkd-wait-online.service \ - /etc/systemd/system/network-online.target.wants/systemd-networkd-wait-online.service - - # disable traditional network init - chroot "${rootfs}" chkconfig network off - - # enable systemd-resolved - rm -f "${rootfs}/etc/resolv.conf" - chroot "${rootfs}" ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf - chroot "${rootfs}" ln -s /usr/lib/systemd/system/systemd-resolved.service \ - /etc/systemd/system/multi-user.target.wants/systemd-resolved.service - - # if desired, prevent systemd from over-mounting /tmp with tmpfs - if [ "${masktmp}" -eq 1 ] - then - chroot "${rootfs}" ln -s /dev/null /etc/systemd/system/tmp.mount - fi - - return 0 -} - -copy_configuration() -{ - local rootfs="${1}" - local config="${2}" - local utsname="${3}" - - # include configuration from default.conf if available - grep -q "^lxc." "${lxc_default_conf}" > "${config}" 2>/dev/null - - grep -q "^lxc.rootfs.path" "${config}" 2>/dev/null || echo " -lxc.rootfs.path = ${rootfs} -" >> "${config}" - - # The following code is to create static MAC addresses for each - # interface in the container. This code will work for multiple - # interfaces in the default config. It will also strip any - # hwaddr stanzas out of the default config since we can not share - # MAC addresses between containers. - mv "${config}" "${config}.orig" - - local line key - while read -r line - do - # This should catch variable expansions from the default config... - if expr "${line}" : '.*\$' > /dev/null 2>&1 - then - line=$(eval "echo \"${line}\"") - fi - - # There is a tab and a space in the regex bracket below! - # Seems that \s doesn't work in brackets. - key=$(expr "${line}" : '\s*\([^ ]*\)\s*=') - - if [ "${key}" != "lxc.net.0.hwaddr" ] - then - echo "${line}" >> "${config}" - - if [ "${key}" == "lxc.net.0.link" ] - then - echo "lxc.net.0.hwaddr = $(create_hwaddr)" >> "${config}" - fi - fi - done < "${config}.orig" - rm -f "${config}.orig" - - if [ -e "${lxc_template_config}/fedora.common.conf" ] - then - echo " -# Include common configuration -lxc.include = ${lxc_template_config}/fedora.common.conf -" >> "${config}" - fi - - cat <> "${path}/config" -# Container specific configuration -lxc.arch = ${basearch} -lxc.uts.name = ${utsname} - -# When using LXC with apparmor, uncomment the next line to run unconfined: -#lxc.apparmor.profile = unconfined - -# example simple networking setup, uncomment to enable -#lxc.net.0.type = ${lxc_network_type} -#lxc.net.0.flags = up -#lxc.net.0.link = ${lxc_network_link} -#lxc.net.0.name = eth0 -# Additional example for veth network type -# static MAC address, -#lxc.net.0.hwaddr = $(create_hwaddr) -# persistent veth device name on host side -# Note: This may potentially collide with other containers of same name! -#lxc.net.0.veth.pair = v-${name}-e0 -EOF - - if [ $? -ne 0 ] - then - echo "Failed to add configuration" - return 1 - fi - - return 0 -} - -copy_fedora() -{ - local cache="${1}" - local rootfs="${2}" - echo -n "Copying ${cache} to ${rootfs} ... " - - mkdir -p "${rootfs}" && - rsync --archive --hard-links --sparse --acls --xattrs "${cache}/" "${rootfs}/" && - echo || return 1 - - return 0 -} - -# Generate a random hardware (MAC) address composed of FE followed by -# 5 random bytes... -# -create_hwaddr() -{ - openssl rand -hex 5 | sed -e 's/\(..\)/:\1/g; s/^/fe/' -} - -# Make sure a fully functional rootfs of the requested release and architecture -# will be setup in the given cache directory. If this is a Fedora host the -# commands will run natively otherwise in a minimal Fedora bootstrap chroot. -# -download_fedora() -{ - local cache_rootfs="${1}" - local setup_rootfs="${cache_rootfs%%/rootfs}/partial" - - # suppress errors due to unknown locales - LC_ALL=C - LANG=en_US - - echo "Downloading ${basearch} rootfs for Fedora ${release} ..." - - # The following variables are going to be overwritten if the rootfs setup - # is run in a separate boostrap environment (can not build natively). - # These are the defaults for the non-boostrap (native) mode. - CHROOT_DIR= - CHROOT_CMD= - INSTALL_ROOT=${setup_rootfs} - - if [ ! "${is_fedora}" ] || [ "${fedora_host_ver}" -lt "${FEDORA_VERSION_MINIMAL}" ] - then - # if this is not a supported Fedora host, use minimal bootstrap chroot - echo "Non-Fedora host detected. Checking for bootstrap environment ... " - if ! bootstrap_fedora "${cache}" - then - echo "Error: Fedora Bootstrap setup failed" - return 1 - fi - echo "Using bootstrap environment at ${CHROOT_DIR}" - fi - - if ! mkdir -p "${setup_rootfs}" - then - echo "Error: Failed to create '${setup_rootfs}' directory." - return 1 - fi - - trap revert_rootfs SIGHUP SIGINT SIGTERM - - mkdir -p "${setup_rootfs}/var/lib/rpm" - - # if the setup is going to be run in a chroot, mount the related file systems - if [ -n "${CHROOT_DIR}" ] - then - chroot_mounts "${CHROOT_DIR}" - - # make sure rootfs is available in bootstrap chroot - INSTALL_ROOT="/run/install" - test -d "${CHROOT_DIR}${INSTALL_ROOT}" || mkdir -p "${CHROOT_DIR}${INSTALL_ROOT}" - mount -o bind "${setup_rootfs}" "${CHROOT_DIR}${INSTALL_ROOT}" - fi - - if ! setup_repositories "${cache}" "${basearch}" "${release}" "${mirror}" - then - echo "Error: Failed to configure repositories in ${CHROOT_DIR}${INSTALL_ROOT}" - revert_rootfs >/dev/null - return 1 - fi - - # Unforunately "${CHROOT_DIR}${INSTALL_ROOT}/dnf.conf" - if [ -n "${mirror}" ] - then - set_dnf_mirror_url "${CHROOT_DIR}${INSTALL_ROOT}/dnf.conf" - fi - - # install minimal container file system - local pkg_list="dnf initscripts passwd vim-minimal openssh-server openssh-clients dhclient rootfiles policycoreutils fedora-release fedora-repos" - if ! ${CHROOT_CMD}dnf --installroot "${INSTALL_ROOT}" \ - --config="${INSTALL_ROOT}/dnf.conf" \ - --releasever "${release}" \ - ${dnf_args[@]} \ - install ${pkg_list} - then - echo "Error: Failed to setup the rootfs in ${CHROOT_DIR}${INSTALL_ROOT}." - revert_rootfs >/dev/null - return 1 - fi - - unmount_installroot - - # from now on we'll work in the new rootfs - chroot_mounts "${setup_rootfs}" - - # It might happen, that the dnf used above will write an incompatible - # RPM database for the version running in the rootfs. Rebuild it. - echo "Fixing up RPM databases" - rm -f "${setup_rootfs}"/var/lib/rpm/__db* - chroot "${setup_rootfs}" rpm --rebuilddb - - # Restrict locale for installed packages to en_US to shrink image size - # following: https://pagure.io/fedora-kickstarts/blob/master/f/fedora-cloud-base.ks - echo "Cleanup locales and language files ..." - find "${setup_rootfs}/usr/share/locale" -mindepth 1 -maxdepth 1 -type d \ - -not -name "${LANG}" -exec rm -rf {} + - - chroot "${setup_rootfs}" localedef --list-archive | grep -v ^"${LANG}" | xargs \ - chroot "${setup_rootfs}" localedef --delete-from-archive - - mv -f "${setup_rootfs}/usr/lib/locale/locale-archive" \ - "${setup_rootfs}/usr/lib/locale/locale-archive.tmpl" - chroot "${setup_rootfs}" build-locale-archive - - echo "%_install_langs C:en:${LANG}:${LANG}.UTF-8" > "${setup_rootfs}/etc/rpm/macros.image-language-conf" - - chroot_umounts "${setup_rootfs}" - - # reset traps - trap SIGHUP - trap SIGINT - trap SIGTERM - - # use generated rootfs as future cache - mv "${setup_rootfs}" "${cache_rootfs}" - - echo "Download of Fedora rootfs complete." - return 0 -} - -# Query the Fedora mirrorlist for several HTTPS mirrors -# -get_mirrors() -{ - local release="${1}" - local mirror_arch="${2}" - - for trynumber in 1 2 3 4 - do - [ "${trynumber}" != 1 ] && echo -n "Trying again ... " - - # choose some mirrors by parsing directory index - mirror_urls=$(curl --silent --show-error --fail "${MIRRORLIST_URL}?repo=fedora-${release}&arch=${mirror_arch}" | sed '/^https:/!d' | sed '2,6!d') - - # shellcheck disable=SC2181 - if [ $? -eq 0 ] && [ -n "${mirror_urls}" ] - then - break - fi - - echo "Warning: Failed to get a mirror on try ${trynumber}." - sleep 3 - done - - if [ -z "${mirror_urls}" ] - then - echo "Error: Failed to retrieve Fedora mirror URL. Please use '-m MIRROR' option." - return 1 - fi - - return 0 -} - -# Install a functional Fedora rootfs into the container root -# -install_fedora() -{ - local rootfs="${1}" - local cache="${2}" - local cache_rootfs="${cache}/${release}-${basearch}/rootfs" - - mkdir -p "${local_state_dir}/lock/subsys/" - ( - if ! flock -x 9 - then - echo "Error: Cache repository is busy." - return 1 - fi - - echo "Checking cache download in ${cache_rootfs} ... " - if [ ! -e "${cache_rootfs}" ] - then - if ! download_fedora "${cache_rootfs}" - then - echo "Error: Failed to download Fedora ${release} (${basearch})" - return 1 - fi - else - echo "Cache found at ${cache_rootfs}. Updating ..." - if ! chroot_update_fedora "${cache_rootfs}" - then - echo "Failed to update cached rootfs, continuing with previously cached version." - else - echo "Fedora update finished." - fi - fi - - trap revert_container SIGHUP SIGINT SIGTERM - - if ! copy_fedora "${cache_rootfs}" "${rootfs}" - then - echo "Error: Failed to copy rootfs" - return 1 - fi - - chroot_mounts "${rootfs}" - - # install additional user provided packages - if [ -n "${packages}" ] - then - # always make sure /etc/resolv.conf is up to date in the target! - cp /etc/resolv.conf "${rootfs}/etc/" - - echo "Installing user requested RPMs: ${packages}" - if ! chroot "${rootfs}" dnf install ${dnf_args[@]} $(tr ',' ' ' <<< "${packages}") - then - echo "Error: Installation of user provided packages failed." - echo "Cleaning up ... " - sleep 3 # wait for all file handles to properly close - chroot_umounts "${setup_rootfs}" - return 1 - fi - fi - - # cleanup dnf cache in new container - chroot "${rootfs}" dnf clean all - - sleep 3 # wait for all file handles to properly close - chroot_umounts "${rootfs}" - - return 0 - ) 9>"${local_state_dir}/lock/subsys/lxc-fedora" - - return $? -} - -# Cleanup partial container -# -revert_container() -{ - echo "Interrupted, so cleaning up ..." - lxc-destroy -n "${name}" 2>/dev/null - # maybe was interrupted before copy config, try to prevent some mistakes - if [ -d "${path}" ] && - [ "${path}" != "/" ] && [ "${path}" != "/tmp" ] && [ "${path}" != "/bin" ] - then - rm -rf "${path}" - fi - echo "Exiting ..." - exit 1 -} - -# Cleanup partial rootfs cache -# -revert_rootfs() -{ - echo "Interrupted, so cleaning up ..." - unmount_installroot - rm -rf "${setup_rootfs}" - echo "Exiting ..." - exit 1 -} - -# Set dnf repository mirror in given repo files -# -set_dnf_mirror_url() -{ - sed -i -e 's/^\(metalink=.*\)$/#\1/g' "${@}" - sed -i -e '/baseurl/ s|^#||g' "${@}" - sed -i -e "/baseurl/ s|http://download.fedoraproject.org/pub/fedora|${mirror}|g" "${@}" -} - -# Setup dnf repository configuration. It can be run in a chroot by specifying -# $CHROOT_DIR (chroot directory) and $CHROOT_CMD (chroot command) and/or -# with an alternative RPM install root defined in $INSTALL_ROOT. -# -setup_repositories() -{ - local cache="${1}" - local target_arch="${2}" - local release="${3}" - local mirror="${4}" - - # download repository packages if not found in cache - pushd "${cache}" >/dev/null - if [ -z "$(ls -1 ./fedora-release-${release}*.noarch.rpm 2>/dev/null)" ] || - [ -z "$(ls -1 ./fedora-repos-${release}*.noarch.rpm 2>/dev/null)" ] - then - # if no mirror given, get an appropriate mirror from the mirror list - if [ -z "${mirror}" ] - then - get_mirrors "${release}" "${target_arch}" || return $? - else - # construct release-specific mirror url - mirror="${mirror}/linux/releases/${release}/Everything/${target_arch}/os" - fi - - for mirror_url in ${mirror:-${mirror_urls}} - do - local release_url="${mirror_url}/Packages/f" - - for pkg in fedora-release-${release} fedora-repos-${release} - do - test -n "$(ls -1 ./${pkg}*.noarch.rpm 2>/dev/null)" && continue - - # query package name by parsing directory index - echo "Requesting '${pkg}' package version from ${release_url}." - pkg_name=$(curl --silent --show-error --fail "${release_url}/" | sed -n -e "/${pkg}/ s/.*href=\"\(${pkg}-.*\.noarch\.rpm\)\">.*/\1/p" | tail -1) - - # shellcheck disable=SC2181 - if [ $? -ne 0 ] || [ -z "${pkg_name}" ] - then - echo "Error: Failed to get '${pkg}' version from ${release_url}/." - continue - fi - - echo "Downloading '${release_url}/${pkg_name} ... " - if ! curl --silent --show-error --fail --remote-name "${release_url}/${pkg_name}" - then - echo "Error: Package download failed." - continue - fi - done - - # if we have both packages continue - if [ -z "$(ls -1 ./fedora-release-${release}*.noarch.rpm 2>/dev/null)" ] || - [ -z "$(ls -1 ./fedora-repos-${release}*.noarch.rpm 2>/dev/null)" ] - then - break - fi - done - fi - - # copy packages to chroot file system - if [ -n "${CHROOT_DIR}" ] - then - cp ./fedora-release-${release}*.noarch.rpm "${CHROOT_DIR}" && - cp ./fedora-repos-${release}*.noarch.rpm "${CHROOT_DIR}" - else - local pkgdir="${cache}" - fi - - # use '--nodeps' to work around 'fedora-release-24-*' bash dependency - ${CHROOT_CMD}rpm --root "${INSTALL_ROOT}" -ivh --nodeps "${pkgdir}"/{fedora-release-${release}*.noarch.rpm,fedora-repos-${release}*.noarch.rpm} - local ret=$? - - # dnf will take $basearch from host, so force the arch we want - sed -i "s|\$basearch|${target_arch}|" ${CHROOT_DIR}${INSTALL_ROOT}/etc/yum.repos.d/* - - popd >/dev/null - - if [ "${ret}" -ne 0 ] - then - echo "Failed to setup repositories in ${CHROOT_DIR}${INSTALL_ROOT}" - exit 1 - fi - - # cleanup installed packages - if [ -n "${CHROOT_DIR}" ] - then - # shellcheck disable=SC2086 - rm -f "${CHROOT_DIR}"/{fedora-release-${release}*.noarch.rpm,fedora-repos-${release}*.noarch.rpm} - fi - - return 0 -} - -# Run dnf update in the given chroot directory. -# -chroot_update_fedora() -{ - local chroot="${1}" - chroot_mounts "${chroot}" - - # always make sure /etc/resolv.conf is up to date in the target! - cp /etc/resolv.conf "${chroot}/etc/" - - chroot "${chroot}" dnf -y update - local ret=$? - - sleep 3 # wait for all file handles to properly close - - chroot_umounts "${chroot}" - - return ${ret} -} - -# Unmount installroot after bootstrapping or on error. -# -unmount_installroot() { - if [ -n "${CHROOT_DIR}" ] - then - sleep 3 # wait for all file handles to properly close - chroot_umounts "${CHROOT_DIR}" 2>/dev/null - umount "${CHROOT_DIR}${INSTALL_ROOT}" 2>/dev/null - fi -} - -usage() -{ - cat </dev/null 2>&1 - then - needed_pkgs="${pkg} ${needed_pkgs}" - fi -done -if [ -n "${needed_pkgs}" ] -then - echo "Error: Missing command(s): ${needed_pkgs}" - exit 1 -fi - -if [ "$(id -u)" != "0" ] -then - echo "This script should be run as 'root'" - exit 1 -fi - -# cleanup cache if requested -cache="${LXC_CACHE_PATH}/fedora" -if [ -n "${clean}" ] -then - clean_cache "${cache}" || exit 1 - exit 0 -fi - -# set container directory -if [ -z "${path}" ] -then - path="${lxc_path}/${name}" -fi - -# set container rootfs and configuration path -config="${path}/config" -if [ -z "${rootfs}" ] -then - # check for 'lxc.rootfs.path' passed in through default config by lxc-create - if grep -q '^lxc.rootfs.path' "${config}" 2>/dev/null - then - rootfs=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' "${config}") - else - rootfs="${path}/rootfs" - fi -fi - -# set release if not given -if [ -z "${release}" ] -then - if [ "${is_fedora}" ] && [ -n "${fedora_host_ver}" ] - then - echo "Detected Fedora ${fedora_host_ver} host. Set release to ${fedora_host_ver}." - release="${fedora_host_ver}" - else - echo "This is not a Fedora host or release is missing, defaulting release to ${FEDORA_RELEASE_DEFAULT}." - release="${FEDORA_RELEASE_DEFAULT}" - fi -fi -if [ "${release}" -lt "${FEDORA_RELEASE_MIN}" ] -then - echo "Error: Fedora release ${release} is not supported. Set -R at least to ${FEDORA_RELEASE_MIN}." - exit 1 -fi - -# bootstrap rootfs and copy to container file system -if ! install_fedora "${rootfs}" "${cache}" -then - echo "Error: Failed to create Fedora container" - exit 1 -fi - -# customize container file system -if ! configure_fedora "${rootfs}" "${release}" "${utsname}" -then - echo "Error: Failed to configure Fedora container" - exit 1 -fi - -# create container configuration (will be overwritten by newer lxc-create) -if ! copy_configuration "${rootfs}" "${config}" "${utsname}" -then - echo "Error: Failed write container configuration file" - exit 1 -fi - -if [ -n "${clean}" ]; then - clean || exit 1 - exit 0 -fi - -echo "Successfully created container '${name}'" - -if [ "${root_display_password}" = "yes" ] -then - echo "The temporary password for root is: '$root_password' - -You may want to note that password down before starting the container. -" -fi - -if [ "${root_store_password}" = "yes" ] -then - echo "The temporary root password is stored in: - - '${config}/tmp_root_pass' -" -fi - -if [ "${root_prompt_password}" = "yes" ] -then - echo "Invoking the passwd command in the container to set the root password. - - chroot ${rootfs} passwd -" - chroot "${rootfs}" passwd -else - if [ "${root_expire_password}" = "yes" ] - then - if ( mountpoint -q -- "${rootfs}" ) - then - echo "To reset the root password, you can do: - - lxc-start -n ${name} - lxc-attach -n ${name} -- passwd - lxc-stop -n ${name} -" - else - echo " -The root password is set up as expired and will require it to be changed -at first login, which you should do as soon as possible. If you lose the -root password or wish to change it without starting the container, you -can change it from the host by running the following command (which will -also reset the expired flag): - - chroot ${rootfs} passwd -" - fi - fi -fi - -# vim: set ts=4 sw=4 expandtab: diff --git a/templates/lxc-gentoo.in b/templates/lxc-gentoo.in deleted file mode 100644 index 950f17c73..000000000 --- a/templates/lxc-gentoo.in +++ /dev/null @@ -1,833 +0,0 @@ -#!/bin/bash - -# -# LXC template for gentoo -# -# Author: Guillaume Zitta -# -# Widely inspired from lxc-gentoo script at https://github.com/globalcitizen/lxc-gentoo -# -# this version is reworked with : -# - out of the lxc-create compat -# - vanilla gentoo config -# - ready to use cache -# - -# 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 - -# Ensure strict root's umask doesen't render the VM unusable -umask 022 - -LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@" - -################################################################################ -# Various helper functions -################################################################################ - -# param: $1: the name of the lock -# param: $2: the timeout for the lock -# The rest contain the command to execute and its parameters -execute_exclusively() -{ - mkdir -p @LOCALSTATEDIR@/lock/subsys/ - - local lock_name="$1" - local timeout="$2" - shift 2 - - { - printf "Attempting to obtain an exclusive lock (timeout: %s sec) named \"%s\"...\n" "${timeout}" "$lock_name" - - flock -x -w "${timeout}" 50 - - if [[ $? -ne 0 ]]; then - printf " => unable to obtain lock, aborting.\n" - return 2 - else - printf " => done.\n" - fi - - printf " => Executing \"%s\"\n" "$*" - "$@" - retval=$? - } 50> "@LOCALSTATEDIR@/lock/subsys/lxc-gentoo-${lock_name}" - return $retval -} - -# a die function is always a good idea -die() -{ - printf "\n[the last exit code leading to this death was: %s ]\n" "$?" - local retval="$1" - shift 1 - printf "$@" - exit "$retval" -} - -# gentoo arch/variant detection -set_default_arch() -{ - printf "### set_default_arch: default arch/variant autodetect...\n" - arch=$(uname -m) - if [[ $arch =~ i.86 ]]; then - arch="x86" - variant="x86" - elif [[ $arch == "x86_64" ]]; then - arch="amd64" - variant="amd64" - elif [[ $arch =~ arm.* ]]; then - arch="arm" - variant="armv7a" - else - #who knows, it may work... - printf " => warn: unexpected arch:${arch} let me knows if it works :)\n" - variant="${arch}" - fi - printf " => Got: arch=%s variant=%s\n" "${arch}" "${variant}" -} - -store_user_message() -{ - user_message="${user_message}=> $@\n" -} - -################################################################################ -# CACHE Preparation -################################################################################ -# during setup cachedir is $cacheroot/partial-$arch-$variant -# at the end, it will be $cacheroot/rootfs-$arch-$variant - -cache_setup(){ - partialfs="${cacheroot}/partial-${arch}-${variant}" - - #if cache exists and flush not needed, return - [[ -d "${cachefs}" && -z "${flush_cache}" ]] && return 0 - - printf "###### cache_setup(): doing cache preparation\n" - local retval=1 - - #clean from failed previous run - rm -rf "${partialfs}" - mkdir -p "${partialfs}" - - #let's go - cache_precheck && \ - cache_stage3 && \ - cache_portage && \ - cache_inittab && \ - cache_net && \ - cache_dev && \ - cache_openrc && \ - cache_locale && \ - rm -rf "${cachefs}" && \ - mv "${partialfs}" "${cachefs}" && \ - printf "###### cache_setup: Cache should be ready\n" - - return $? -} - -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 SEPARATORS, THIS IS *VERY* BAD!\n" "${cacheroot}" -} - -#get latest stage3 tarball -cache_stage3() -{ - printf "### cache_stage3(): stage3 cache deployment...\n" - - if [ -z "${tarball}" ]; then - #variables init - local stage3_baseurl="${mirror}/releases/${arch}/autobuilds" - - # get latest-stage3....txt file for subpath - local stage3_pointer="${stage3_baseurl}/latest-stage3-${variant}.txt" - - printf "Determining path to latest Gentoo %s (%s) stage3 archive...\n" "${arch}" "${variant}" - printf " => downloading and processing %s\n" "${stage3_pointer}" - - local stage3_latest_tarball=$(wget -q -O - "${stage3_pointer}" | tail -n1 | cut -d' ' -f1) \ - || die 6 "Error: unable to fetch\n" - - printf " => Got: %s\n" "${stage3_latest_tarball}" - - printf "Downloading/untarring the actual stage3 tarball...\n" - - compressor="j" - if echo ${stage3_latest_tarball} | grep ".xz$"; then - compressor="J" - fi - - wget -O - "${stage3_baseurl}/${stage3_latest_tarball}" \ - | tar -x${compressor}pf - --numeric-owner -C "${partialfs}" \ - || die 6 "Error: unable to fetch or untar\n" - printf " => extracted to: %s\n" "${partialfs}" - else - printf "Extracting the stage3 tarball...\n" - tar -xpf "${tarball}" --numeric-owner -C "${partialfs}" \ - || die 6 "unable to untar ${tarball} to ${partialfs}" - fi - - #check if it chroots - printf "chroot test..." - chroot ${partialfs} /bin/true || die 1 "Error: chroot %s /bin/true, failed" "${partialfs}" - printf " OK\n" - printf " => stage3 cache extracted in : %s\n" "${partialfs}" - return 0 -} - -cache_portage() -{ - printf "### cache_portage: caching portage tree tarball...\n" - [[ -z "${flush_cache}" && -f "${portage_cache}" ]] && return 0 - - rm -f ${portage_cache} - - printf "Downloading Gentoo portage (software build database) snapshot...\n" - execute_exclusively portage 60 wget -O "${portage_cache}" "${mirror}/snapshots/portage-latest.tar.bz2" \ - || die 6 "Error: unable to fetch\n" - printf " => done.\n" -} - -# custom inittab -cache_inittab() -{ - printf "### cache_inittab: tuning inittab...\n" - - INITTAB="${partialfs}/etc/inittab" - - [[ -w "$INITTAB" ]] || die 1 "Error: $INITTAB is not writeable" - - # create console - echo "# Lxc main console" >> "$INITTAB" - echo "1:12345:respawn:/sbin/agetty -a root --noclear 115200 console linux" >> "$INITTAB" - - # finally we add a pf line to enable clean shutdown on SIGPWR (issue 60) - echo "# clean container shutdown on SIGPWR" >> "$INITTAB" - echo "pf:12345:powerwait:/sbin/halt" >> "$INITTAB" - - # we also blank out /etc/issue here in order to prevent delays spawning login - # caused by attempts to determine domainname on disconnected containers - sed -i 's/[\][Oo]//g' "${partialfs}/etc/issue" -} - -cache_net() -{ - printf "### cache_net: doing some useful net tuning...\n" - # useful for chroot - # /etc/resolv.conf - grep -i 'search ' /etc/resolv.conf > "${partialfs}/etc/resolv.conf" - grep -i 'nameserver ' /etc/resolv.conf >> "${partialfs}/etc/resolv.conf" - - # fix boot-time interface config wipe under aggressive cap drop - # (openrc 0.9.8.4 ~sep 2012 - https://bugs.gentoo.org/show_bug.cgi?id=436266) - # initial warkaround was: sed -i -e 's/^#rc_nostop=""/rc_nostop="net.eth0 net.lo"/' "${partialfs}/etc/rc.conf" - # but this one does not depends on interfaces names - echo 'rc_keyword="-stop"' >> "${partialfs}/etc/conf.d/net" -} - -cache_dev() -{ - printf "### cache_dev(): /dev tuning...\n" - - #Wait for https://bugs.gentoo.org/show_bug.cgi?id=496054 - mkdir "${partialfs}/dev/pts" - mkdir "${partialfs}/dev/shm" - mkdir "${partialfs}/dev/mqueue" - - mkdir -m 755 "${partialfs}/dev/net" - mknod -m 666 "${partialfs}/dev/net/tun" c 10 200 - - return 0 -} - -# fix openrc system -cache_openrc() -{ - printf "### cache_openrc(): doing openrc tuning\n" - - #Wait for https://bugs.gentoo.org/show_bug.cgi?id=496054 - chroot "${partialfs}" sed s/-lxc//g -i "/etc/init.d/devfs" - - return 0 -} - -cache_locale() -{ - printf "### cache_locale(): initiating minimale locale en_US.UTF-8 \n" - - echo "en_US.UTF-8 UTF-8" >> "${partialfs}/etc/locale.gen" - chroot "${partialfs}" locale-gen - - return 0 -} - -################################################################################ -# CONTAINER Preparation -################################################################################ - -container_setup() { - printf "##### container_setup(): starting container setup\n" - - #in most cases lxc-create should have provided a copy of default lxc.conf - #let's tag where template starts, or just create the files - echo '### lxc-gentoo template stuff starts here' >> "$path/config" - - #Determine rootfs - #If backingstore was specified, lxc.rootfs.path should be present or --rootfs did the rootfs var creation - if [ -z "${rootfs}" ]; then - rootfs=`awk -F= '$1 ~ /^lxc.rootfs.path/ { print $2 }' "$path/config" 2>/dev/null` - if [ -z "${rootfs}" ]; then - #OK it's default - rootfs="${path}/rootfs" - fi - fi - store_user_message "rootfs of container is : ${rootfs}" - store_user_message "config of container is : ${path}/config" - - container_precheck && \ - container_rootfs && \ - container_consoles && \ - container_tz && \ - container_portage && \ - container_net && \ - container_hostname && \ - container_auth && \ - container_sshd && \ - container_conf - if [ $? -ne 0 ]; then - die 1 "container_setup(): one step didn't complete, sorry\n" - fi - - printf "###### container_setup(): container should be ready to start!\n" - printf "\n\n" - printf "You could now use you container with: lxc-start -n %s\n" "${name}" - printf "little things you should know about your container:\n" - printf "${user_message}" - return 0 -} - -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 SEPARATORS, THIS IS *VERY* BAD!\n" "${name}" - - [[ -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 SEPARATORS, THIS IS *VERY* BAD!\n" "${cachefs}" - - # check if the rootfs already exists - [[ -d "${rootfs}/etc" ]] && die 18 "Error: \$rootfs (%s) already exists!" "${rootfs}" - - # check cache - [[ ! -d "${cachefs}/etc" ]] && die 1 "Error: \$cachefs (%s) not found!" "${cachefs}" - - return 0 -} - -container_rootfs() -{ - printf "#### container_rootfs(): copying rootfs %s from cache %s ...\n" "${rootfs}" "${cachefs}" - tar -c -f - --numeric-owner -C "${cachefs}" . \ - | tar -x -p -f - --numeric-owner -C "${rootfs}" \ - || die 1 "Error: cache copy to rootfs failed" - - printf "chroot test..." - chroot "${rootfs}" /bin/true || die 1 "Error: 'chroot %s /bin/true' failed" - printf " OK\n" - - printf " => done\n" - return 0 -} - -container_consoles() { - printf "#### container_consoles(): setting container consoles ...\n" - - # disable unwanted ttys - if [[ ${tty} < 6 ]]; then - local mindis=$(( ${tty} + 1 )) - sed -i "s/^c[${mindis}-6]/#&/" "${rootfs}/etc/inittab" - fi - printf " => main console + ${tty} ttys\n" - - if [[ -z "${autologin}" ]]; then - sed 's/agetty -a root/agetty/' -i "${rootfs}/etc/inittab" - elif [[ "${user}" != "root" ]]; then - sed "s/agetty -a root/agetty -a ${user}/" -i "${rootfs}/etc/inittab" - printf " => Autologin on main console for %s enabled\n" "${user}" - [[ -z "${forced_password}" ]] && unset password - store_user_message "${user} has autologin on main console" - else - printf " => Autologin on main console for root enabled\n" - [[ -z "${forced_password}" ]] && unset password - store_user_message "${user} has autologin on main console" - fi - printf " => done\n" -} - -container_tz() -{ - printf "#### container_tz(): setting container timezone ...\n" - - #let's try to copy it from host - if [ -L "/etc/localtime" ]; then - #host has a symlink - #let see if we can reproduct symlink - target=$(readlink /etc/localtime) - if [[ "$target" != "" ]]; then - if [ -f "${rootfs}/${target}" ]; then - #same target exists in container - chroot "${rootfs}" ln -sf "${target}" "/etc/localtime" - printf " => host symlink reproducted in container : %s\n" "${target}" - store_user_message "timezone copyed from host" - return 0 - fi - fi - fi - - if [ -e /etc/localtime ]; then - # duplicate host timezone - cat /etc/localtime > "${rootfs}/etc/localtime" - printf " => host localtime copyed to container\n" - store_user_message "timezone was staticly copyed from host" - else - # otherwise set up UTC - chroot "${rootfs}" ln -sf /usr/share/zoneinfo/UTC /etc/localtime - printf " => fallback: fixed to UTC\n" - store_user_message "timezone was fixed to UTC" - fi -} - - -container_portage() -{ - printf "#### container_portage(): setting container portage... \n" - - #default entry for conf - portage_mount="#container set with private portage tree, no mount here" - - printf "Warnings are normal here, don't worry\n" - #container repos detection - if chroot ${rootfs} portageq get_repo_path / gentoo > /dev/null ; then - portage_container="$(chroot ${rootfs} portageq get_repo_path / gentoo)" - else - die 1 "Failed to figure out container portage tree location with portageq get_repo_path / gentoo\n" - fi - - if [[ -n "${private_portage}" ]]; then - container_private_portage - return 0 - fi - - if [ -z "${portage_dir}" ]; then - #gentoo host detection - printf "trying to guess portage_dir from host...\n" - portage_dir="$(portageq get_repo_path / gentoo 2>/dev/null)" - if [ ! -d "${portage_dir}/profiles" ]; then - printf " => host portage detection failed (not gentoo host), fallback to private portage tree\n" - container_private_portage - return 0 - fi - else - if [ ! -d "${portage_dir}/profiles" ]; then - die 1 "specified portage_dir (%s) does not contains profiles, is it a portage tree ?\n" "${portage_dir}" - fi - fi - - printf "trying to guess portage distfiles dir from host ...\n" - portage_distfiles_dir="$(portageq distdir 2>/dev/null)" - if [ ! -d "${portage_distfiles_dir}" ]; then - portage_distfiles_dir="${portage_dir}/distfiles" - fi - - # if we are here, we have shared portage_dir - #ensure dir exists - chroot "${rootfs}" mkdir ${portage_container} - portage_mount="#container set with shared portage -lxc.mount.entry=${portage_dir} ${portage_container/\//} none ro,bind 0 0 -lxc.mount.entry=${portage_distfiles_dir} ${portage_container/\//}/distfiles none rw,bind 0 0 -#If you use eix, you should uncomment this -#lxc.mount.entry=/var/cache/eix var/cache/eix none ro,bind 0 0" - store_user_message "container has a shared portage from host's ${portage_dir} to ${portage_container/\//}" - #Let's propose binary packages - cat <<- EOF >> "${rootfs}/etc/portage/make.conf" -# enable this to store built binary packages -#FEATURES="\$FEATURES buildpkg" - -# enable this to use built binary packages -#EMERGE_DEFAULT_OPTS="\${EMERGE_DEFAULT_OPTS} --usepkg" - -# enable and *tune* this kind of entry to slot binaries, specialy if you use multiples archs and variants -#PKGDIR="\${PKGDIR}/amd64 -#or PKGDIR="\${PKGDIR}/hardened" -EOF - printf " => portage stuff done, see /etc/portage/make.conf for additional tricks\n" - -} - -container_private_portage() -{ - #called from container_portage() do not call directly from container_setup - printf "# untaring private portage to %s from %s ... \n" "${rootfs}/${portage_container}" "${portage_cache}" - mkdir -p "${rootfs}/${portage_container}" - execute_exclusively portage 60 \ - tar -xp --strip-components 1 -C "${rootfs}/${portage_container}" \ - -f "${portage_cache}" --numeric-owner \ - || die 2 "Error: unable to extract the portage tree.\n" - store_user_message "container has its own portage tree at ${portage_container}" - printf "=> done\n" -} - -#helper func for container_genconf_net() -nic_write() -{ - #display with gentoo's confd.net format - echo "config_${nic_name}=\"${nic_conf}\"" - #add to managed list - [[ "${nic_conf}" == "dhcp" ]] && nic_managed="${nic_managed} ${nic_name}" - [[ "${nic_conf}" == "null" ]] && nic_unmanaged="${nic_unmanaged} ${nic_name}" - [[ -z "${nic_hwaddr}" && ${nic_type} == "veth" ]] && nic_wo_hwaddr="${nic_wo_hwaddr} ${nic_name}" - nic_writed=1 -} - -#Analyse lxc.conf and print conf.d/net content -container_conf_net() -{ - local file=${1} - [[ -z "${nic_last}" ]] && nic_last=-1 - [[ -z "${nic_named}" ]] && nic_named=0 - OLDIFS=$IFS - IFS=" -" - #let's do some drity bash things to parse lxc network conf - for line in $( sed -r "s/[ ]*=[ ]*/_real_ugly_sep_42_/" "${file}" ); do - key=$(echo "${line}" | sed 's/_real_ugly_sep_42_.*$//') - value=$(echo "${line}" | sed 's/^.*_real_ugly_sep_42_//') - - #new nic ! - if [[ "${key}" == "lxc.net.0.type" ]]; then - #we don't know what to do with it. - [[ "${value}" == "empty" ]] && continue - - #write conf from previous loops - [[ "${nic_writed}" == "0" ]] && nic_write - - #init defaults - let nic_last=nic_last+1 - - nic_writed=0 - #if 1 named between 2 not named: last is eth1 - #=> Number is ID munis number of named NIC before - nic_name="eth$(( ${nic_last} - ${nic_named} ))" - nic_conf="dhcp" - nic_type="${value}" - fi - - if [[ "${key}" == "lxc.net.0.hwaddr" ]]; then - nic_hwaddr=1 - fi - - if [[ "${key}" =~ ^lxc.net.0.ipv(4|6) ]]; then - #tell openrc to not manage this NIC as LXC set there address - nic_conf="null" - fi - if [[ "${key}" =~ ^lxc.net.0.name ]]; then - nic_name="${value}" - let nic_named=nic_named+1 - fi - if [[ "${key}" == "lxc.include" ]]; then - #recursive into include - container_conf_net "${value}" - fi - done - #write conf from previous loops - [[ "${nic_writed}" == "0" ]] && nic_write - IFS=$OLDIFS -} - -container_net() -{ - printf "container_net(): setting container network conf... \n" - - #Analyse network configuration in config - container_conf_net "$path/config" >> "${rootfs}/etc/conf.d/net" - - # found how much nic finally have - nic_count=$(( ${nic_last} + 1 )) - - # unless openrc manage a nic, we now have to force openrc to automatic - # provision of the 'net' dep. If we do not, network dependent services - # will fail to load - if [[ -z "${nic_managed}" ]]; then - #tell openrc that lxc already did the work - echo 'rc_provide="net"' >> "${rootfs}/etc/rc.conf" - fi - - #No NIC ? - if [[ ${nic_count} == 0 ]]; then - #If no Nic, no need to continue - bridge=$(brctl show | awk 'NR==2 {print $1}') - if [[ "${bridge}" != "" ]]; then - store_user_message "No network interface for this container -It's a pitty, you have bridge, ${bridge}. -If it is for Lxc, use it next time by adding this to your default.conf : -lxc.net.0.type = veth -lxc.net.0.link = ${bridge} -lxc.net.0.flags = up -lxc.net.0.hwaddr = fe:xx:xx:xx:xx:xx" - return 0 - else - store_user_message "No network interface for this container" - return 0 - fi - fi - - #For each openrc managed nic, activate - sys_nic_index=1 - for nic in ${nic_managed} - do - chroot "${rootfs}" ln -s net.lo "/etc/init.d/net.${nic}" - chroot "${rootfs}" rc-update add net.${nic} default - #fake sysfs for openrc, in case settings does not provide it - mkdir -p "${rootfs}/sys/class/net/${nic}" - echo ${sys_nic_index} > "${rootfs}/sys/class/net/${nic}/ifindex" - echo up > "${rootfs}/sys/class/net/${nic}/operstate" - let sys_nic_index=sys_nic_index+1 - done - - #Warn about dynamic hwaddr - if [[ -n "${nic_wo_hwaddr}" ]]; then - store_user_message "Warning, these veth NIC don't have fixed hwaddr : -${nic_wo_hwaddr} - -see http://lists.linuxcontainers.org/pipermail/lxc-devel/2013-December/006736.html -and man lxc.conf" - fi - - printf " => network conf done.\n" -} - -# custom hostname -container_hostname() -{ - printf "#### container_hostname(): setting hostname... \n" - printf "hostname=\"%s\"\n" "${name}" > "${rootfs}/etc/conf.d/hostname" - printf " => done.\n" -} - -container_auth() -{ - printf "#### container_auth(): setting authentification... \n" - if [[ "${user}" != "root" ]]; then - printf " non root user requested, creating... \n" - chroot "${rootfs}" useradd --create-home -s /bin/bash "${user}" || die 1 "failed to create user ${user}" - printf " => user %s created\n" "${user}" - fi - store_user_message "Connection user is ${user}" - #Home of user - auth_home=$(chroot "${rootfs}" getent passwd "${user}" | cut -d : -f 6) - if [[ -r "${auth_key}" ]]; then - printf " deploying auth_key %s for user %s ...\n" "${auth_key}" "${user}" - mkdir -p "${rootfs}/${auth_home}/.ssh" - cat "${auth_key}" >> "${rootfs}/${auth_home}/.ssh/authorized_keys" - chroot "${rootfs}" chown "${user}:" "${auth_home}/.ssh/authorized_keys" - printf " => inserted public key in %s/.ssh/authorized_keys\n" "${auth_home}" - [[ -z "${forced_password}" ]] && unset password - store_user_message "${user} has the ssh key you gave us" - fi - - if [[ -n "${password}" ]]; then - printf " setting password for %s ...\n" "${user}" - echo "${user}:${password}" | chroot "${rootfs}" chpasswd || die 1 "failed to change password" - printf " => done. if you didn't specify , default is 'toor'\n" - if [[ -n "${forced_password}" ]]; then - store_user_message "${user} has the password you give for him" - fi - fi - - printf " => done.\n" -} - -container_sshd() { - printf "#### container_sshd(): enabling sshd... \n" - - chroot "${rootfs}" rc-update add sshd || die 1 "failed to enable sshd\n" - - printf " => done.\n" -} - -################################################################################ -# lxc configuration files -################################################################################ - -container_conf() -{ - printf "container_configuration(): making lxc configuration file... \n" - - #at this point if there - conf_file="${path}/config" - - # if there is exactly one veth network entry, make sure it has an - # associated hwaddr. - nics=`grep -e '^lxc\.net\.0\.type[ \t]*=[ \t]*veth' ${conf_file} | wc -l` - if [ $nics -eq 1 ]; then - grep -q "^lxc.net.0.hwaddr" ${conf_file} || sed -i -e "/^lxc\.net\.0\.type[ \t]*=[ \t]*veth/a lxc.net.0.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')" ${conf_file} - fi - - if grep -q "^lxc.rootfs.path" "${conf_file}" ; then - #lxc-create already provided one - conf_rootfs_line="" - else - conf_rootfs_line="lxc.rootfs.path = $(readlink -f "${rootfs}")" - fi - if [[ "${arch}" == "x86" || "${arch}" == "amd64" ]]; then - local conf_arch_line="lxc.arch = ${arch}" - else - local conf_arch_line="# lxc.arch = ${arch}" - fi - - cat <<- EOF >> "${conf_file}" -# sets container architecture -# If desired architecture != amd64 or x86, then we leave it unset as -# LXC does not oficially support anything other than x86 or amd64. -${conf_arch_line} - -# set the hostname -lxc.uts.name = ${name} -lxc.tty.max = ${tty} - -${conf_rootfs_line} -${portage_mount} -${conf_sysfs} -${conf_mounts} - -lxc.include = ${LXC_TEMPLATE_CONFIG}/gentoo.${settings}.conf -EOF - printf " => done.\n" -} - -usage() -{ - cat <] [-v|--variant ] [-P|--private-portage] [--portage-dir ] [-t|--tarball ] - [-F|--flush-cache] [-c|--cache-only] [-u|--user ] [-w|--password ] [--autologin] [-S|--auth-key ] - [-s|--settings ] [-m|--mirror ] [--tty ] - -arch: the container architecture (e.g. amd64): defaults to host arch (currently: '${arch}') - If you choose one that needs emulation - tested: amd64, x86 - You could try any other gentoo arch, why not... - -variant: gentoo's Architecture variant as of dec 2013 : (currently: '${variant}') - for amd64 arch: amd64 (default), amd64-hardened+nomultilib, amd64-hardened, amd64-nomultilib, x32 - for x86 arch: i686 (default), i486, i686-hardened - for arm arch: armv7a (default), armv7a_hardfp, armv6j, armv6j_hardfp, armv5tel, armv4tl - -private-portage: by default, /usr/portage is mount-binded with host one if exists (currently: '${private_portage}') - this force container to have his own copy - -portage-dir: portage dir used for shared portage - by default the host on if any (currently: '${portage_dir}') - -tarball: force usage of local stage3 archive (currently: '${arch}') - If empty, latest will be downloaded - -flush-cache: do like there is no previous cache - -cache-only: just ensure cache is present - if cache exists and "flush-cache" not specified, does nothing - -user: user used in auth oriented options (currently: '${user}') - -password: password for user (currently: '${password}') - if default, usage of auth-key will disable password setting - -autologin: enable autologin for user (currently: '${autologin}') - This unset default password setting - -auth-key: SSH Public key file to inject into container for user (currently: '${auth_key}') - This unset default password setting - -settings: choose common configuration (currently: '${settings}') - see ${LXC_TEMPLATE_CONFIG}/gentoo.*.conf - Available settings: - $(ls -1 ${LXC_TEMPLATE_CONFIG}/gentoo.*.conf | xargs basename -a -s .conf | sed 's/^gentoo.//') - -mirror: gentoo mirror for download (currently: '${mirror}') - -tty: number of tty (6 max) (currently: '${tty}') -EOF - exit 0 -} - -#some overridable defaults -set_default_arch - -mirror="http://distfiles.gentoo.org" -user="root" -tty=1 -settings="common" -options=$(getopt -o hp:n:a:FcPv:t:S:u:w:s:m: -l help,rootfs:,path:,name:,arch:,flush-cache,cache-only,private-portage,variant:,portage-dir:,tarball:,auth-key:,user:,autologin,password:,settings:,mirror:,tty: -- "$@") - -eval set -- "$options" - -while true -do - case "$1" in - -h|--help) usage $0 && exit 0;; - --rootfs) rootfs=$2; shift 2;; - -p|--path) path=$2; shift 2;; - -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; shift 1;; - -P|--private-portage) private_portage=1; shift 1;; - -v|--variant) variant=$2; shift 2;; - --portage-dir) portage_dir=$2; shift 2;; - -t|--tarball) tarball=$2; shift 2;; - -S|--auth-key) auth_key=$2; shift 2;; - -u|--user) user=$2; shift 2;; - -w|--password) forced_password=1; password=$2; shift 2;; - -s|--settings) settings=$2; shift 2;; - -m|--mirror) mirror=$2; shift 2;; - --container-cache) containercache=$2; shift 2;; - --tty) [[ $2 -lt 6 ]] && tty=$2; shift 2;; - --autologin) autologin=1; shift 1;; - --) shift 1; break ;; - *) break ;; - esac -done - -# Allow the cache path to be set by environment variable -cacheroot="${LXC_CACHE_PATH:-"@LOCALSTATEDIR@/cache/lxc"}/gentoo" -portage_cache="${cacheroot}/portage.tbz" -cachefs="${cacheroot}/rootfs-${arch}-${variant}" - -alias wget="wget --timeout=8 --read-timeout=15 -c -t10 -nd" - -do_all() { - cache_setup - if [ -z "${cache_only}" ]; then - container_setup - fi -} - -execute_exclusively "cache-${arch}-${variant}" 60 do_all diff --git a/templates/lxc-openmandriva.in b/templates/lxc-openmandriva.in deleted file mode 100644 index 2761cd509..000000000 --- a/templates/lxc-openmandriva.in +++ /dev/null @@ -1,484 +0,0 @@ -#!/bin/bash - -# -# template script for generating openmandriva container for LXC -# - -# -# lxc: linux Container library - -# Authors: -# Alexander Khryukin -# Vokhmin Alexey V - -# 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 -# - -# 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 - -#Configurations -#distro=cooker -hostarch=$(uname -m) -# Allow the cache base to be set by environment variable -cache_base="${LXC_CACHE_PATH:-@LOCALSTATEDIR@/cache/lxc/openmandriva/$arch}" -default_path=@LXCPATH@ -default_profile=default -lxc_network_type=veth -lxc_network_link=br0 - -# is this openmandriva? -[ -f /etc/mandriva-release ] && is_openmandriva=true - -configure_openmandriva() -{ -mkdir -p ${rootfs_path}/etc/sysconfig/network-scripts/ - - # configure the network using the dhcp - cat < ${rootfs_path}/etc/sysconfig/network-scripts/ifcfg-eth0 -DEVICE=eth0 -ONBOOT=yes -BOOTPROTO=dhcp -NM_CONTROLLED=no -HOSTNAME=${utsname} -EOF - - # set the hostname - cat < ${rootfs_path}/etc/sysconfig/network -NETWORKING=yes -HOSTNAME=${utsname} -EOF - -echo "${utsname}" > ${rootfs_path}/etc/hostname - - # set minimal hosts - cat < $rootfs_path/etc/hosts -127.0.0.1 localhost.localdomain localhost $utsname -::1 localhost6.localdomain6 localhost6 -EOF -} - -populate_dev() -{ - echo -n "Create devices in /dev/" - dev_path="${rootfs_path}/dev" - rm -rf $dev_path - mkdir -p $dev_path - mknod -m 666 ${dev_path}/null c 1 3 - mknod -m 666 ${dev_path}/zero c 1 5 - mknod -m 666 ${dev_path}/random c 1 8 - mknod -m 666 ${dev_path}/urandom c 1 9 - mkdir -m 755 ${dev_path}/pts - mkdir -m 1777 ${dev_path}/shm - mknod -m 666 ${dev_path}/tty c 5 0 - mknod -m 666 ${dev_path}/tty0 c 4 0 - mknod -m 666 ${dev_path}/tty1 c 4 1 - mknod -m 666 ${dev_path}/tty2 c 4 2 - mknod -m 666 ${dev_path}/tty3 c 4 3 - mknod -m 666 ${dev_path}/tty4 c 4 4 - mknod -m 600 ${dev_path}/console c 5 1 - mknod -m 666 ${dev_path}/full c 1 7 - mknod -m 600 ${dev_path}/initctl p - mknod -m 666 ${dev_path}/ptmx c 5 2 - mkdir -m 755 ${dev_path}/net - mknod -m 666 ${dev_path}/net/tun c 10 200 - -} - -set_guest_root_password() -{ - [ -z "$root_password" ] && return # pass is empty, abort - - echo " - setting guest root password.." - echo "root passwd is: $root_password" - echo "root:$root_password" | chroot "$rootfs_path" chpasswd - echo "done." -} - -create_chroot_openmandriva() -{ - # check the mini openmandriva was not already downloaded - INSTALL_ROOT=$cache/cache - mkdir -p $INSTALL_ROOT - if [ $? -ne 0 ]; then - echo "Failed to create '$INSTALL_ROOT' directory" - return 1 - fi - # package list to install - PKG_LIST="basesystem-minimal locales locales-en initscripts urpmi cronie dhcp-client kbd" - # download a mini openmandriva into a cache - echo "Downloading openmandriva minimal ..." - URPMI="/usr/sbin/urpmi.addmedia --urpmi-root $INSTALL_ROOT main http://abf.rosalinux.ru/downloads/$release/repository/$arch/main/release" - echo $URPMI - URPMI_BASE="/usr/sbin/urpmi --no-suggests --no-verify-rpm --ignorearch --root $INSTALL_ROOT --urpmi-root $INSTALL_ROOT --auto $PKG_LIST" - $URPMI - $URPMI_BASE - # We're splitting the old loop into two loops plus a directory retrival. - # First loop... Try and retrive a mirror list with retries and a slight - # delay between attempts... - if [ $? -ne 0 ]; then - echo "Failed to download the rootfs, aborting." - return 1 - fi - - mv "$INSTALL_ROOT" "$cache/rootfs" - echo "Download complete." - - return 0 - -} - -copy_openmandriva() -{ - - echo -n "Copying rootfs to $rootfs_path ..." - mkdir -p $rootfs_path - rsync -SHaAX $cache/rootfs/ $rootfs_path/ - return 0 -} - -update_openmandriva() -{ - echo "automated update in progress..." - urpmi --root $cache/rootfs --urpmi-root $cache/rootfs --auto --auto-update --ignorearch -} - -configure_openmandriva_systemd() -{ - chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/proc-sys-fs-binfmt_misc.automount - chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/systemd-udevd.service - chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/systemd-udevd-control.socket - chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/systemd-udevd-kernel.socket - # remove numlock service - # KDGKBLED: Inappropriate ioctl for device - rm -f ${rootfs_path}/etc/systemd/system/getty@.service.d/enable-numlock.conf - - unlink ${rootfs_path}/etc/systemd/system/default.target - chroot ${rootfs_path} ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target - sed -i 's!ConditionPathExists=/dev/tty0!ConditionPathExists=|/dev/tty0\nConditionVirtualization=|lxc!' \ - ${rootfs_path}/lib/systemd/system/getty\@.service -} - - -install_openmandriva() -{ - mkdir -p @LOCALSTATEDIR@/lock/subsys/ - ( - flock -x 9 - if [ $? -ne 0 ]; then - echo "Cache repository is busy." - return 1 - fi - - echo "Checking cache download in $cache/rootfs ... " - if [ ! -e "$cache/rootfs" ]; then - echo $cache/rootfs - create_chroot_openmandriva - if [ $? -ne 0 ]; then - echo "Failed to download 'openmandriva basesystem-minimal'" - return 1 - fi - else - echo "Cache found. Updating..." - update_openmandriva - if [ $? -ne 0 ]; then - echo "Failed to update 'openmandriva base', continuing with last known good cache" - else - echo "Update finished" - fi - fi - - echo "Copy $cache/rootfs to $rootfs_path ... " - copy_openmandriva - if [ $? -ne 0 ]; then - echo "Failed to copy rootfs" - return 1 - fi - return 0 - ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-openmandriva - - return $? -} - -copy_configuration() -{ - - mkdir -p $config_path - grep -q "^lxc.rootfs.path" $config_path/config 2>/dev/null || echo "lxc.rootfs.path = $rootfs_path" >> $config_path/config - cat <> $config_path/config -lxc.uts.name = $name -lxc.tty.max = 4 -lxc.pty.max = 1024 -lxc.cap.drop = sys_module mac_admin mac_override sys_time -lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed - -# When using LXC with apparmor, uncomment the next line to run unconfined: -#lxc.apparmor.profile = unconfined - -#networking -lxc.net.0.type = $lxc_network_type -lxc.net.0.flags = up -lxc.net.0.link = $lxc_network_link -lxc.net.0.name = eth0 -lxc.net.0.mtu = 1500 -EOF -if [ ! -z ${ipv4} ]; then - cat <> $config_path/config -lxc.net.0.ipv4.address = $ipv4 -EOF -fi -if [ ! -z ${gw} ]; then - cat <> $config_path/config -lxc.net.0.ipv4.gateway = $gw -EOF -fi -if [ ! -z ${ipv6} ]; then - cat <> $config_path/config -lxc.net.0.ipv6.address = $ipv6 -EOF -fi -if [ ! -z ${gw6} ]; then - cat <> $config_path/config -lxc.net.0.ipv6.gateway = $gw6 -EOF -fi - cat <> $config_path/config -#cgroups -lxc.cgroup.devices.deny = a -# /dev/null and zero -lxc.cgroup.devices.allow = c 1:3 rwm -lxc.cgroup.devices.allow = c 1:5 rwm -# consoles -lxc.cgroup.devices.allow = c 5:1 rwm -lxc.cgroup.devices.allow = c 5:0 rwm -lxc.cgroup.devices.allow = c 4:0 rwm -lxc.cgroup.devices.allow = c 4:1 rwm -# /dev/{,u}random -lxc.cgroup.devices.allow = c 1:9 rwm -lxc.cgroup.devices.allow = c 1:8 rwm -lxc.cgroup.devices.allow = c 136:* rwm -lxc.cgroup.devices.allow = c 5:2 rwm -# rtc -lxc.cgroup.devices.allow = c 10:135 rwm -EOF - - if [ $? -ne 0 ]; then - echo "Failed to add configuration" - return 1 - fi - - return 0 -} - -clean() -{ - - if [ ! -e $cache ]; then - exit 0 - fi - - # lock, so we won't purge while someone is creating a repository - ( - flock -x 9 - if [ $? != 0 ]; then - echo "Cache repository is busy." - exit 1 - fi - - echo -n "Purging the download cache for OpenMandriva-$release..." - rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1 - exit 0 - ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-openmandriva -} - -usage() -{ - cat < - [-p|--path=] [-c|--clean] [-R|--release=] - [-4|--ipv4=] [-6|--ipv6=] - [-g|--gw=] [-d|--dns=] - [-P|--profile=] [--rootfs=] - [-A|--arch=] - [-h|--help] -Mandatory args: - -n,--name container name, used to as an identifier for that container from now on -Optional args: - -p,--path path to where the container rootfs will be created, defaults to @LXCPATH@. The container config will go under @LXCPATH@ in that case - -c,--clean clean the cache - -R,--release openmandriva2013.0/cooker/rosa2012.1 release for the new container. if the host is OpenMandriva, then it will default to the host's release. - -4,--ipv4 specify the ipv4 address to assign to the virtualized interface, eg. 192.168.1.123/24 - -6,--ipv6 specify the ipv6 address to assign to the virtualized interface, eg. 2003:db8:1:0:214:1234:fe0b:3596/64 - -g,--gw specify the default gw, eg. 192.168.1.1 - -G,--gw6 specify the default gw, eg. 2003:db8:1:0:214:1234:fe0b:3596 - -d,--dns specify the DNS server, eg. 192.168.1.2 - -P,--profile Profile name is the file name in /etc/lxc/profiles contained packages name for install to cache. - -A,--arch Define what arch the container will be [i586,x86_64,armv7l,armv7hl] - ---rootfs rootfs path - -h,--help print this help -EOF - return 0 -} - -options=$(getopt -o hp:n:P:cR:4:6:g:d:A -l help,rootfs:,path:,name:,profile:,clean:,release:,ipv4:,ipv6:,gw:,dns:,arch: -- "$@") -if [ $? -ne 0 ]; then - usage $(basename $0) - exit 1 -fi -eval set -- "$options" - -release=${release:-"cooker"} -if [ -f /etc/lsb-release ]; then - . /etc/lsb-release - if [ "$DISTRIB_ID" = "OpenMandrivaLinux" ]; then - release=openmandriva2013.0 - elif [ "$DISTRIB_ID" = "RosaDesktop.Fresh" ]; then - release=rosa2012.1 - else - echo "This is not an OpenMandriva or ROSA release" - exit 1 - fi -fi - -while true -do - case "$1" in - -h|--help) usage $0 && exit 0;; - -p|--path) path=$2; shift 2;; - --rootfs) rootfs_path=$2; shift 2;; - -n|--name) name=$2; shift 2;; - -P|--profile) profile=$2; shift 2;; - -c|--clean) clean=1; shift 1;; - -R|--release) release=$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;; - -d|--dns) dns=$2; shift 2;; - --) shift 1; break ;; - *) break ;; - esac -done - -arch=${arch:-$hostarch} - -if [ ! -z "$clean" -a -z "$path" ]; then - clean || exit 1 - exit 0 -fi - -if [ -z "${utsname}" ]; then - utsname=${name} -fi - -type urpmi >/dev/null 2>&1 -if [ $? -ne 0 ]; then - echo "'urpmi' command is missing" - exit 1 -fi - -if [ -z "$path" ]; then - path=$default_path -fi - -if [ -z "$profile" ]; then - profile=$default_profile -fi - -if [ $hostarch = "i586" -a $arch = "x86_64" ]; then - echo "can't create x86_64 container on i586" - exit 1 -fi - -if [ -z "$ipv4" -a -z "$ipv6" ]; then - BOOTPROTO="dhcp" -else - BOOTPROTO="static" -fi - -if [ "$(id -u)" != "0" ]; then - echo "This script should be run as 'root'" - exit 1 -fi - -# check for 'lxc.rootfs.path' passed in through default config by lxc-create -if [ -z "$rootfs_path" ]; then - if grep -q '^lxc.rootfs.path' $path/config 2>/dev/null ; then - rootfs_path=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $path/config) - else - rootfs_path=$path/$name/rootfs - fi -fi - -config_path=$default_path/$name -cache=$cache_base/$release/$arch/$profile - -if [ ! -f $config_path/config ]; then - echo "A container with that name exists, chose a different name" - exit 1 -fi - -install_openmandriva -if [ $? -ne 0 ]; then - echo "failed to install openmandriva" - exit 1 -fi - -configure_openmandriva -if [ $? -ne 0 ]; then - echo "failed to configure openmandriva for a container" - exit 1 -fi - -# If the systemd configuration directory exists - set it up for what we need. -if [ -d ${rootfs_path}/etc/systemd/system ] -then - configure_openmandriva_systemd -fi - -populate_dev -if [ $? -ne 0 ]; then - echo "failed to populated /dev/ devices" - exit 1 -fi - -set_guest_root_password -if [ $? -ne 0 ]; then - echo "failed to configure password for chroot" - exit 1 -fi - -copy_configuration -if [ $? -ne 0 ]; then - echo "failed write configuration file" - exit 1 -fi - -if [ ! -z "$clean" ]; then - clean || exit 1 - exit 0 -fi -echo "container rootfs and config created" diff --git a/templates/lxc-opensuse.in b/templates/lxc-opensuse.in deleted file mode 100644 index c2480dd60..000000000 --- a/templates/lxc-opensuse.in +++ /dev/null @@ -1,557 +0,0 @@ -#!/bin/bash - -# -# template script for generating OpenSUSE container for LXC -# - -# -# lxc: linux Container library - -# Authors: -# Daniel Lezcano -# Frederic Crozat -# Michael H. Warfield -# Johannes Kastl -# Thomas Lamprecht - -# 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 - -# 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 - -if [ -x /usr/bin/obs-build ]; then - BUILD=/usr/bin/obs-build - export BUILD_DIR=/usr/lib/obs-build -else - BUILD=/usr/bin/build - export BUILD_DIR=/usr/lib/build -fi - -configure_opensuse() -{ - rootfs=$1 - hostname=$2 - - # set first network adapter as dhcp. This is the most common config. - cat < $rootfs/etc/sysconfig/network/ifcfg-eth0 -STARTMODE='auto' -BOOTPROTO='dhcp' -EOF - - # create empty fstab - touch $rootfs/etc/fstab - - # set the hostname - cat < $rootfs/etc/HOSTNAME -$hostname -EOF - # ensure /etc/hostname is available too - ln -s -f HOSTNAME $rootfs/etc/hostname - - # do not use hostname from HOSTNAME variable - cat <> $rootfs/etc/sysconfig/cron -unset HOSTNAME -EOF - - # set minimal hosts - cat < $rootfs/etc/hosts -127.0.0.1 localhost $hostname -EOF - - # disable yast->bootloader in container - cat < $rootfs/etc/sysconfig/bootloader -LOADER_TYPE=none -LOADER_LOCATION=none -EOF - - # set /dev/console as securetty - cat << EOF >> $rootfs/etc/securetty -console -EOF - - cat <> $rootfs/etc/sysconfig/boot -# disable root fsck -ROOTFS_FSCK="0" -ROOTFS_BLKDEV="/dev/null" -EOF - - - # remove pointless services in a container - ln -s /dev/null $rootfs/etc/systemd/system/proc-sys-fs-binfmt_misc.automount - ln -s /dev/null $rootfs/etc/systemd/system/console-shell.service - ln -s /dev/null $rootfs/etc/systemd/system/systemd-vconsole-setup.service - # enable getty and console services - sed -e 's/ConditionPathExists=.*//' $rootfs/usr/lib/systemd/system/getty@.service > $rootfs/etc/systemd/system/getty@.service - ln -s getty@.service $rootfs/etc/systemd/system/getty@tty1.service - mkdir -p $rootfs/etc/systemd/system/getty.target.wants/ - ln -s ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@console.service - ln -s -f ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@tty1.service - ln -s ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@tty2.service - ln -s ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@tty3.service - ln -s ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@tty4.service - - touch $rootfs/etc/sysconfig/kernel - - echo "Please change root-password !" - - return 0 -} - -download_opensuse() -{ - cache=$1 - arch=$2 - - if [ ! -x ${BUILD} ]; then - echo "Could not create openSUSE template :" - echo "you need to install \"build\" package" - return 1 - fi - - # check the mini opensuse was not already downloaded - mkdir -p "$cache/partial-$arch" - - if [ $? -ne 0 ]; then - echo "Failed to create '$cache/partial-$arch' directory" - return 1 - fi - - # download a mini opensuse into a cache - echo "Downloading opensuse minimal ..." - mkdir -p "$cache/partial-$arch-packages" - - oss_repo_url="http://download.opensuse.org/distribution/$DISTRO/repo/oss/" - if [[ $DISTRO == "tumbleweed" ]]; then - oss_repo_url="http://download.opensuse.org/$DISTRO/repo/oss/" - fi - zypper --quiet --root $cache/partial-$arch-packages --non-interactive ar "$oss_repo_url" repo-oss || return 1 - - update_repo_url="http://download.opensuse.org/update/$DISTRO/repo/oss" - # Leap update repos were rearranged - if [[ $DISTRO == "leap/4"* ]]; then - update_repo_url="http://download.opensuse.org/update/$DISTRO/oss/" - fi - # tumbleweed has no update repo - if [[ $DISTRO != "tumbleweed" ]]; then - zypper --quiet --root $cache/partial-$arch-packages --non-interactive ar "$update_repo_url" update || return 1 - fi - - zypper --quiet --root $cache/partial-$arch-packages --non-interactive --gpg-auto-import-keys update || return 1 - zypper --root $cache/partial-$arch-packages --non-interactive in --auto-agree-with-licenses --download-only zypper lxc patterns-openSUSE-base bash iputils sed tar rsyslog || return 1 - - cat > $cache/partial-$arch-packages/opensuse.conf << EOF -Preinstall: aaa_base bash coreutils diffutils -Preinstall: filesystem fillup glibc grep insserv-compat perl-base -Preinstall: libbz2-1 pam -Preinstall: permissions rpm sed tar libz1 libselinux1 -Preinstall: liblzma5 libcap2 libacl1 libattr1 -Preinstall: libpopt0 libelf1 -Preinstall: libpcre1 - -RunScripts: aaa_base - -Support: zypper -Support: patterns-openSUSE-base -Support: lxc -Support: ncurses-utils -Support: iputils -Support: udev -Support: netcfg -Support: hwinfo insserv-compat module-init-tools openSUSE-release openssh -Support: pwdutils sysconfig - -Ignore: rpm:suse-build-key,build-key -Ignore: systemd:systemd-presets-branding -EOF - - if [ $DISTRO = "13.2" ] - then - echo "Support: python3-base" >> $cache/partial-$arch-packages/opensuse.conf - fi - - if [[ $DISTRO == "tumbleweed" ]]; then - echo "Preinstall: liblua5_3 libncurses6 libreadline7" >> $cache/partial-$arch-packages/opensuse.conf - else - echo "Preinstall: liblua5_1 libncurses5 libreadline6" >> $cache/partial-$arch-packages/opensuse.conf - echo "Support: rpcbind" >> $cache/partial-$arch-packages/opensuse.conf - fi - - # dhcpcd is not in the default repos since Leap 42.1, neither in tumbleweed - if [[ $DISTRO != "leap/4"* ]] && [[ $DISTRO != "tumbleweed" ]]; then - echo "Support: dhcpcd" >> $cache/partial-$arch-packages/opensuse.conf - fi - - # Leap and tumbleweed doesn't seem to have iproute2 utils installed - if [[ $DISTRO == "leap/4"* ]] || [[ $DISTRO == "tumbleweed" ]]; then - echo "Support: net-tools iproute2" >> $cache/partial-$arch-packages/opensuse.conf - fi - - if [ "$arch" = "i686" ]; then - mkdir -p $cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/i686/ - for i in "$cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/i586/*" ; do - ln -s $i $cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/i686/ - done - mkdir -p $cache/partial-$arch-packages/var/cache/zypp/packages/update/i686 - for i in "$cache/partial-$arch-packages/var/cache/zypp/packages/update/i586/*" ; do - ln -s $i $cache/partial-$arch-packages/var/cache/zypp/packages/update/i686/ - done - fi - - # openSUSE 13.2 has no noarch directory in update - [ -d $cache/partial-$arch-packages/var/cache/zypp/packages/update/noarch ] || mkdir -p $cache/partial-$arch-packages/var/cache/zypp/packages/update/noarch - - repos=("--repository" "$cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/$arch" "--repository" "$cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/noarch") - if [[ $DISTRO != "tumbleweed" ]]; then # tumbleweed has no update repo - repos+=("--repository" "$cache/partial-$arch-packages/var/cache/zypp/packages/update/$arch" "--repository" "$cache/partial-$arch-packages/var/cache/zypp/packages/update/noarch") - fi - - CLEAN_BUILD=1 BUILD_ARCH="$arch" BUILD_ROOT="$cache/partial-$arch" BUILD_DIST="$cache/partial-$arch-packages/opensuse.conf" PATH="$PATH:$BUILD_DIR" $BUILD_DIR/init_buildsystem --clean --configdir $BUILD_DIR/configs --cachedir $cache/partial-$arch-cache ${repos[*]} || return 1 - - chroot $cache/partial-$arch /usr/bin/zypper --quiet --non-interactive ar "$oss_repo_url" repo-oss || return 1 - if [[ $DISTRO != "tumbleweed" ]]; then - chroot $cache/partial-$arch /usr/bin/zypper --quiet --non-interactive ar "$update_repo_url" update || return 1 - fi - -# really clean the image - rm -fr $cache/partial-$arch/{.build,.guessed_dist,.srcfiles*,installed-pkg} - rm -fr $cache/partial-$arch/dev -# make sure we have a minimal /dev - mkdir -p "$cache/partial-$arch/dev" - mknod -m 666 $cache/partial-$arch/dev/null c 1 3 - mknod -m 666 $cache/partial-$arch/dev/zero c 1 5 -# create mtab symlink - rm -f $cache/partial-$arch/etc/mtab - ln -sf /proc/self/mounts $cache/partial-$arch/etc/mtab - -# ensure /var/run and /run are symlinked - rm -fr $cache/partial-$arch/var/run - ln -s -f ../run $cache/partial-$arch/var/run - if [ $? -ne 0 ]; then - echo "Failed to download the rootfs, aborting." - return 1 - fi - - rm -fr "$cache/partial-$arch-packages" - mv "$1/partial-$arch" "$1/rootfs-$arch" - echo "Download complete." - - return 0 -} - -copy_opensuse() -{ - cache=$1 - arch=$2 - rootfs=$3 - - # make a local copy of the mini opensuse - echo "Copying rootfs to $rootfs ..." - mkdir -p $rootfs - rsync -SHaAX $cache/rootfs-$arch/ $rootfs/ || return 1 - return 0 -} - -install_opensuse() -{ - # Allow the cache base to be set by environment variable - cache="${LXC_CACHE_PATH:-@LOCALSTATEDIR@/cache/lxc/opensuse/$DISTRO}" - rootfs=$1 - mkdir -p @LOCALSTATEDIR@/lock/subsys/ - ( - flock -x 9 - if [ $? -ne 0 ]; then - echo "Cache repository is busy." - return 1 - fi - - echo "Checking cache download in $cache/rootfs-$arch ... " - if [ ! -e "$cache/rootfs-$arch" ]; then - download_opensuse $cache $arch - if [ $? -ne 0 ]; then - echo "Failed to download 'opensuse base'" - return 1 - fi - fi - - echo "Copy $cache/rootfs-$arch to $rootfs ... " - copy_opensuse $cache $arch $rootfs - if [ $? -ne 0 ]; then - echo "Failed to copy rootfs" - return 1 - fi - - return 0 - ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-opensuse - - return $? -} - -# Generate a random hardware (MAC) address composed of FE followed by -# 5 random bytes... -create_hwaddr() -{ - openssl rand -hex 5 | sed -e 's/\(..\)/:\1/g; s/^/fe/' -} - -copy_configuration() -{ - path=$1 - rootfs=$2 - name=$3 - - grep -q "^lxc.rootfs.path" $path/config 2>/dev/null || echo " -lxc.rootfs.path = $rootfs_path -" >> $path/config - - # The following code is to create static MAC addresses for each - # interface in the container. This code will work for multiple - # interfaces in the default config. It will also strip any - # hwaddr stanzas out of the default config since we can not share - # MAC addresses between containers. - # - # This code is largely mimiced from the Fedora Template. - mv $path/config $path/config.def - while read LINE - do - # This should catch variable expansions from the default config... - if expr "${LINE}" : '.*\$' > /dev/null 2>&1 - then - LINE=$(eval "echo \"${LINE}\"") - fi - - # There is a tab and a space in the regex bracket below! - # Seems that \s doesn't work in brackets. - KEY=$(expr "${LINE}" : '\s*\([^ ]*\)\s*=') - - if [[ "${KEY}" != "lxc.net.0.hwaddr" ]] - then - echo "${LINE}" >> $path/config - - if [[ "${KEY}" == "lxc.net.0.link" ]] - then - echo "lxc.net.0.hwaddr = $(create_hwaddr)" >> $path/config - fi - fi - done < $path/config.def - - rm -f $path/config.def - - if [ -e "@LXCTEMPLATECONFIG@/opensuse.common.conf" ]; then - echo " -# Include common configuration -lxc.include = @LXCTEMPLATECONFIG@/opensuse.common.conf -" >> $path/config - fi - - # Append things which require expansion here... - cat <> $path/config -lxc.arch = $arch -lxc.uts.name = $name - -lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed - -# When using LXC with apparmor, uncomment the next line to run unconfined: -lxc.apparmor.profile = unconfined - -# example simple networking setup, uncomment to enable -#lxc.net.0.type = $lxc_network_type -#lxc.net.0.flags = up -#lxc.net.0.link = $lxc_network_link -#lxc.net.0.name = eth0 -# Additional example for veth network type -# static MAC address, -#lxc.net.0.hwaddr = 00:16:3e:77:52:20 -# persistent veth device name on host side -# Note: This may potentially collide with other containers of same name! -#lxc.net.0.veth.pair = v-$name-e0 - -EOF - - if [ $? -ne 0 ]; then - echo "Failed to add configuration" - return 1 - fi - - return 0 -} - -clean() -{ - cache="${LXC_CACHE_PATH:-@LOCALSTATEDIR@/cache/lxc/opensuse}" - - if [ ! -e $cache ]; then - exit 0 - fi - - # lock, so we won't purge while someone is creating a repository - ( - flock -x 9 - if [ $? != 0 ]; then - echo "Cache repository is busy." - exit 1 - fi - - echo -n "Purging the download cache..." - rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1 - exit 0 - ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-opensuse -} - -usage() -{ - cat < -r|--release nn.n --clean -Please give the release as 13.1, 13.2 etc. -If no release is given, openSUSE Leap 42.2 is installed. -EOF - return 0 -} - -# Make arch a global. This may become configurable? -arch=$(uname -m) - -options=$(getopt -o hp:n:r:c -l help,rootfs:,path:,name:,release:,clean -- "$@") -if [ $? -ne 0 ]; then - usage $(basename $0) - exit 1 -fi -eval set -- "$options" - -while true -do - case "$1" in - -h|--help) usage $0 && exit 0;; - -p|--path) path=$2; shift 2;; - --rootfs) rootfs=$2; shift 2;; - -n|--name) name=$2; shift 2;; - -r|--release) DISTRO=$2; shift 2;; - -c|--clean) clean=1; shift 1;; - --) shift 1; break ;; - *) break ;; - esac -done - -if [ ! -z "$clean" -a -z "$path" ]; then - clean || exit 1 - exit 0 -fi - -type zypper > /dev/null -if [ $? -ne 0 ]; then - echo "'zypper' command is missing" - exit 1 -fi - -if [ -z "$path" ]; then - echo "'path' parameter is required" - exit 1 -fi - -if grep -q Harlequin /etc/os-release || grep -q Tumbleweed /etc/os-release ; then - BVER=`rpm -q --qf '%{version}\n' build` - if [ $? -ne 0 -o "$BVER" -lt "20141120" ]; then - echo "Building openSUSE containers with your version of the build package is broken. Please install the update to version 20141120 or newer." - exit 1 - fi -fi - -if [ -z "$DISTRO" ]; then - echo "" - echo "No release selected, using openSUSE Leap 42.2" - DISTRO="leap/42.2" -else - echo "" - case "$DISTRO" in - 13.1) - echo "Selected openSUSE 13.1" - ;; - - 13.2) - echo "Selected openSUSE 13.2" - ;; - - 42.1|leap/42.1|leap) - echo "Selected openSUSE Leap 42.1" - DISTRO="leap/42.1" - ;; - - 42.2|leap/42.2|422) - echo "Selected openSUSE Leap 42.2" - DISTRO="leap/42.2" - ;; - 42.3|leap/42.3|423) - echo "Selected openSUSE Leap 42.3" - DISTRO="leap/42.3" - ;; - tumbleweed|factory) - echo "Selected openSUSE Leap Tumbleweed" - DISTRO="tumbleweed" - ;; - - *) - echo "You have chosen an invalid release, quitting..." - exit 1 - ;; - esac -fi - - -if [ "$(id -u)" != "0" ]; then - echo "This script should be run as 'root'" - exit 1 -fi - -# detect rootfs -config="$path/config" -if [ -z "$rootfs" ]; then - if grep -q '^lxc.rootfs.path' $config 2>/dev/null ; then - rootfs=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $config) - else - rootfs=$path/rootfs - fi -fi - -install_opensuse $rootfs -if [ $? -ne 0 ]; then - echo "failed to install opensuse" - exit 1 -fi - -configure_opensuse $rootfs $name -if [ $? -ne 0 ]; then - echo "failed to configure opensuse for a container" - exit 1 -fi - -copy_configuration $path $rootfs $name -if [ $? -ne 0 ]; then - echo "failed write configuration file" - exit 1 -fi - -if [ ! -z "$clean" ]; then - clean || exit 1 - exit 0 -fi diff --git a/templates/lxc-oracle.in b/templates/lxc-oracle.in deleted file mode 100644 index afb690210..000000000 --- a/templates/lxc-oracle.in +++ /dev/null @@ -1,972 +0,0 @@ -#!/bin/sh -# -# Template script for generating Oracle Enterprise Linux container for LXC -# based on lxc-fedora, lxc-ubuntu -# -# Copyright © 2011 Wim Coekaerts -# Copyright © 2012 Dwight Engen -# -# Modified for Oracle Linux 5 -# Wim Coekaerts -# -# Modified for Oracle Linux 6,7 combined OL4,5,6 into one template script -# Dwight Engen -# -# 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 -# - -# 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 - -die() -{ - echo "failed: $1" - exit 1 -} - -is_btrfs_subvolume() -{ - if which btrfs >/dev/null 2>&1 && \ - btrfs subvolume list "$1" >/dev/null 2>&1; then - return 0 - fi - return 1 -} - -can_chcon() -{ - if which chcon >/dev/null 2>&1; then - selinuxenabled >/dev/null 2>&1 - return $? - fi - return 1 -} - -# fix up the container_rootfs -container_rootfs_patch() -{ - echo "Patching container rootfs $container_rootfs for Oracle Linux $container_release_major.$container_release_minor" - - # copy ourself into the container to be used to --patch the rootfs when - # yum update on certain packages is done. we do this here instead of in - # container_rootfs_configure() in case the patching done in this function - # is updated in the future, we can inject the updated version of ourself - # into older containers. - if [ $container_rootfs != "/" ]; then - cp -f `readlink -f $0` $container_rootfs/usr/bin/lxc-patch - if [ $container_release_major -lt "6" ]; then - mkdir -p $container_rootfs/usr/lib/yum-plugins - cp @DATADIR@/lxc/lxc-patch.py $container_rootfs/usr/lib/yum-plugins - fi - if [ $container_release_major -ge "6" ]; then - mkdir -p $container_rootfs/usr/share/yum-plugins - cp @DATADIR@/lxc/lxc-patch.py $container_rootfs/usr/share/yum-plugins - fi - mkdir -p $container_rootfs/etc/yum/pluginconf.d - cat < $container_rootfs/etc/yum/pluginconf.d/lxc-patch.conf -[main] -enabled=1 -packages=dbus,initscripts,iptables,openssh-server,setup,selinux-policy,readahead,udev,util-linux,util-linux-ng -EOF - fi - - if [ $container_release_major = "4" ]; then - # yum plugin type of TYPE_INTERFACE works in all releases but gives a - # deprecation warning on major > 4, so we default to TYPE_INTERACTIVE - # and fix it up here - sed -i 's|TYPE_INTERACTIVE|TYPE_INTERFACE|' $container_rootfs/usr/lib/yum-plugins/lxc-patch.py - if [ -f $container_rootfs/etc/yum.repos.d/ULN-Base.repo ]; then - mv $container_rootfs/etc/yum.repos.d/ULN-Base.repo \ - $container_rootfs/etc/yum.repos.d/ULN-Base.repo.lxc-disabled - fi - echo "plugins = 1" >>$container_rootfs/etc/yum.conf - fi - - # "disable" selinux in the guest. The policy in the container isn't - # likely to match the hosts (unless host == guest exactly) and the - # kernel can only be enforcing one policy. - # - # The OL 5 init honors /etc/selinux/config, but note that - # this doesnt actually disable it if it's enabled in the host, since - # libselinux::is_selinux_enabled() in the guest will check - # /proc/filesystems and see selinuxfs, thus reporting that it is on - # (ie. check the output of sestatus in the guest). We also replace - # /usr/sbin/selinuxenabled with a symlink to /bin/false so that init - # scripts (ie. mcstransd) that call that think selinux is disabled. - mkdir -p $container_rootfs/selinux - echo 0 > $container_rootfs/selinux/enforce - if [ -e $container_rootfs/etc/selinux/config ]; then - sed -i 's|SELINUX=enforcing|SELINUX=disabled|' $container_rootfs/etc/selinux/config - else - mkdir -p $container_rootfs/etc/selinux - echo "SELINUX=disabled" >$container_rootfs/etc/selinux/config - fi - sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*close|#session required pam_selinux.so close|' $container_rootfs/etc/pam.d/login - sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*open|#session required pam_selinux.so open|' $container_rootfs/etc/pam.d/login - sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*close|#session required pam_selinux.so close|' $container_rootfs/etc/pam.d/sshd - sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*open|#session required pam_selinux.so open|' $container_rootfs/etc/pam.d/sshd - - # setting /proc/$$/loginuid doesn't work under user namespace, which - # prevents logins from working - sed -i 's|session[ \t]*required[ \t]*pam_loginuid.so|#session required pam_loginuid.so|' $container_rootfs/etc/pam.d/sshd - sed -i 's|session[ \t]*required[ \t]*pam_loginuid.so|#session required pam_loginuid.so|' $container_rootfs/etc/pam.d/login - - if [ -f $container_rootfs/usr/sbin/selinuxenabled ]; then - mv $container_rootfs/usr/sbin/selinuxenabled $container_rootfs/usr/sbin/selinuxenabled.lxcorig - ln -s /bin/false $container_rootfs/usr/sbin/selinuxenabled - fi - - # ensure /dev/ptmx refers to the newinstance devpts of the container, or - # pty's will get crossed up with the hosts (https://lkml.org/lkml/2012/1/23/512) - rm -f $container_rootfs/dev/ptmx - ln -s pts/ptmx $container_rootfs/dev/ptmx - - # OL7 has systemd, no rc.sysinit - if [ $container_release_major = "7" ]; then - # with newer systemd (OL7.2), getty service include container-getty.service - # let that be the one who manage the getty service instead - if [ ! -f $container_rootfs/usr/lib/systemd/system/container-getty@.service ]; then - # from mhw in the fedora template: We do need to disable the - # "ConditionalPathExists=/dev/tty0" line or no gettys are started on - # the ttys in the container. Lets do it in an override copy of the - # service so it can still pass rpm verifies and not be automatically - # updated by a new systemd version. - sed -e 's/^ConditionPathExists=/#LXC ConditionPathExists=/' \ - < $container_rootfs/usr/lib/systemd/system/getty\@.service \ - > $container_rootfs/etc/systemd/system/getty\@.service - # Setup getty service on the 4 ttys we are going to allow in the - # default config. Number should match lxc.tty - ( cd $container_rootfs/etc/systemd/system/getty.target.wants - for i in 1 2 3 4 ; do ln -sf ../getty\@.service getty@tty${i}.service; done ) - # We only want to spawn a getty on /dev/console in lxc, libvirt-lxc - # symlinks /dev/console to /dev/tty1 - sed -i '/Before=getty.target/a ConditionVirtualization=lxc' $container_rootfs/usr/lib/systemd/system/console-getty.service - fi - - # disable some systemd services, set default boot, sigpwr target - rm -f $container_rootfs/usr/lib/systemd/system/sysinit.target.wants/kmod-static-nodes.service - chroot $container_rootfs systemctl -q disable graphical.target - chroot $container_rootfs systemctl -q enable multi-user.target - - # systemd in userns won't be able to set /proc/self/oom_score_adj which - # prevents the dbus service from starting - sed -i 's|^OOMScoreAdjust|#LXC OOMScoreAdjust|' $container_rootfs/usr/lib/systemd/system/dbus.service - return - fi - - # silence error in checking for selinux - sed -i 's|cat /proc/self/attr/current|cat /proc/self/attr/current 2>/dev/null|' $container_rootfs/etc/rc.sysinit - sed -i 's|cat /proc/self/attr/current|cat /proc/self/attr/current 2>/dev/null|' $container_rootfs/etc/rc.d/rc.sysinit - - # on ol4 pam_limits prevents logins when using user namespaces - if [ $container_release_major = "4" ]; then - sed -i 's|session[ \t]*required[ \t]*/lib/security/\$ISA/pam_limits.so|#session required /lib/security/$ISA/pam_limits.so|' $container_rootfs/etc/pam.d/system-auth - fi - - # avoid error in ol5 attempting to copy non-existent resolv.conf - if [ $container_release_major = "5" ]; then - sed -i 's|resolv.conf.predhclient|resolv.conf.predhclient 2>/dev/null|' $container_rootfs/sbin/dhclient-script - fi - - # disable interactive ovmd asking questions - if [ -f $container_rootfs/etc/sysconfig/ovmd ]; then - sed -i 's|INITIAL_CONFIG=yes|INITIAL_CONFIG=no|' $container_rootfs/etc/sysconfig/ovmd - fi - - # disable disabling of ipv4 forwarding and defrag on shutdown since - # we mount /proc/sys ro - if [ $container_release_major = "5" ]; then - sed -i 's|-f /proc/sys/net/ipv4/ip_forward|-w /proc/sys/net/ipv4/ip_forward|' $container_rootfs/etc/rc.d/init.d/network - sed -i 's|-f /proc/sys/net/ipv4/ip_always_defrag|-w /proc/sys/net/ipv4/ip_always_defrag|' $container_rootfs/etc/rc.d/init.d/network - fi - - # disable ipv6 on ol6 - rm -f $container_rootfs/etc/sysconfig/network-scripts/init.ipv6-global - - # remove module stuff for iptables it just shows errors that are not - # relevant in a container - if [ -f "$container_rootfs/etc/sysconfig/iptables-config" ]; then - sed -i 's|IPTABLES_MODULES=".*|IPTABLES_MODULES=""|' $container_rootfs/etc/sysconfig/iptables-config - sed -i 's|IPTABLES_MODULES_UNLOAD=".*|IPTABLES_MODULES_UNLOAD="no"|' $container_rootfs/etc/sysconfig/iptables-config - fi - - # disable readahead in the container - if [ $container_release_major = "6" -a -e $container_rootfs/etc/sysconfig/readahead ]; then - rm -f $container_rootfs/etc/init/readahead-collector.conf - rm -f $container_rootfs/etc/init/readahead-disable-services.conf - sed -i 's|READAHEAD="yes"|READAHEAD="no"|' $container_rootfs/etc/sysconfig/readahead - fi - - if [ $container_release_major = "4" ]; then - # enable fastboot always - sed -i 's|\[ -f /fastboot \]|/bin/true|' $container_rootfs/etc/rc.sysinit - sed -i 's|\[ -f /fastboot \]|/bin/true|' $container_rootfs/etc/rc.d/rc.sysinit - - # dont attempt to set kernel parameters - sed -i 's|action $"Configuring kernel parameters|# LXC action $"Configuring kernel parameters|' $container_rootfs/etc/rc.sysinit - sed -i 's|action $"Configuring kernel parameters|# LXC action $"Configuring kernel parameters|' $container_rootfs/etc/rc.d/rc.sysinit - sed -i 's|action $"Setting network parameters|# LXC action $"Setting network parameters|' $container_rootfs/etc/init.d/network 2>/dev/null - sed -i 's|action $"Setting network parameters|# LXC action $"Setting network parameters|' $container_rootfs/etc/init.d/NetworkManager 2>/dev/null - fi - - # no need to attempt to mount / - sed -i 's|mount -f /$|# LXC mount -f /|' $container_rootfs/etc/rc.sysinit - sed -i 's|mount -f /$|# LXC mount -f /|' $container_rootfs/etc/rc.d/rc.sysinit - sed -i 's|action \$"Remounting root filesystem|/bin/true # LXC action $"Remounting root filesystem|' $container_rootfs/etc/rc.sysinit - sed -i 's|action \$"Remounting root filesystem|/bin/true # LXC action $"Remounting root filesystem|' $container_rootfs/etc/rc.d/rc.sysinit - - # disable udev in the container - if [ $container_release_major = "4" ]; then - sed -i 's|\[ -x /sbin/start_udev \]|# LXC no udev|' $container_rootfs/etc/rc.sysinit - sed -i 's|\[ -x /sbin/start_udev \]|# LXC no udev|' $container_rootfs/etc/rc.d/rc.sysinit - else - sed -i 's|.sbin.start_udev||' $container_rootfs/etc/rc.sysinit - sed -i 's|.sbin.start_udev||' $container_rootfs/etc/rc.d/rc.sysinit - fi - - # disable nash raidautorun in the container since no /dev/md* - if [ $container_release_major = "4" -o $container_release_major = "5" ]; then - sed -i 's|echo "raidautorun /dev/md0"|echo ""|' $container_rootfs/etc/rc.sysinit - sed -i 's|echo "raidautorun /dev/md0"|echo ""|' $container_rootfs/etc/rc.d/rc.sysinit - fi - - # prevent rc.sysinit from attempting to loadkeys - if [ \( $container_release_major = "4" -o $container_release_major = "5" \) -a -e $container_rootfs/etc/sysconfig/keyboard ]; then - rm $container_rootfs/etc/sysconfig/keyboard - fi - - # dont use the hwclock, it messes up the host's time - if [ $container_release_major = "4" ]; then - sed -i 's|runcmd $"Syncing hardware clock|# LXC no hwclock runcmd $"Syncing hardware clock|' $container_rootfs/etc/rc.d/init.d/halt - else - sed -i 's|\[ -x /sbin/hwclock|\[ 0 -eq 1|' $container_rootfs/etc/rc.d/init.d/halt - fi - sed -i 's|^\[ -x /sbin/hwclock|\[ 0 -eq 1|' $container_rootfs/etc/rc.sysinit - sed -i 's|^\[ -x /sbin/hwclock|\[ 0 -eq 1|' $container_rootfs/etc/rc.d/rc.sysinit - sed -i 's|^/sbin/hwclock|# LXC /sbin/nohwclock|' $container_rootfs/etc/rc.sysinit - sed -i 's|^/sbin/hwclock|# LXC /sbin/nohwclock|' $container_rootfs/etc/rc.d/rc.sysinit - - # dont start lvm - if [ $container_release_major -lt "6" -a -f $container_rootfs/sbin/lvm.static ]; then - mv $container_rootfs/sbin/lvm.static $container_rootfs/sbin/lvm.static.lxc-disabled - fi - if [ $container_release_major = "6" ]; then - touch $container_rootfs/.nolvm - fi - - # fix assumptions that plymouth is available - sed -i 's|\[ "$PROMPT" != no \] && plymouth|[ "$PROMPT" != no ] \&\& [ -n "$PLYMOUTH" ] \&\& plymouth|' $container_rootfs/etc/rc.sysinit - sed -i 's|\[ "$PROMPT" != no \] && plymouth|[ "$PROMPT" != no ] \&\& [ -n "$PLYMOUTH" ] \&\& plymouth|' $container_rootfs/etc/rc.d/rc.sysinit - rm -f $container_rootfs/etc/init/plymouth-shutdown.conf - rm -f $container_rootfs/etc/init/quit-plymouth.conf - rm -f $container_rootfs/etc/init/splash-manager.conf - - # dont try to unmount /dev/lxc devices - sed -i 's|&& $1 !~ /^\\/dev\\/ram/|\&\& $2 !~ /^\\/dev\\/lxc/ \&\& $1 !~ /^\\/dev\\/ram/|' $container_rootfs/etc/init.d/halt - - # don't try to unmount swap - sed -i 's|\[ -f /proc/swaps \]|# LXC [ -f /proc/swaps ]|' $container_rootfs/etc/init.d/halt - - # sem_open(3) checks that /dev/shm is SHMFS_SUPER_MAGIC, so make sure to - # mount /dev/shm (normally done by dracut initrd) as tmpfs - if [ $container_release_major = "4" -o $container_release_major = "5" ]; then - grep -q "mount -t tmpfs tmpfs /dev/shm" $container_rootfs/etc/rc.sysinit - if [ $? -eq 1 ]; then - echo "mkdir -p /dev/shm && mount -t tmpfs tmpfs /dev/shm" >>$container_rootfs/etc/rc.sysinit - echo "mkdir -p /dev/shm && mount -t tmpfs tmpfs /dev/shm" >>$container_rootfs/etc/rc.d/rc.sysinit - fi - fi - if [ $container_release_major = "6" ]; then - sed -i 's|mount -n -o remount /dev/shm >/dev/null 2>&1$|mkdir -p /dev/shm \&\& mount -t tmpfs tmpfs /dev/shm # LXC|' $container_rootfs/etc/rc.sysinit - sed -i 's|mount -n -o remount /dev/shm >/dev/null 2>&1$|mkdir -p /dev/shm \&\& mount -t tmpfs tmpfs /dev/shm # LXC|' $container_rootfs/etc/rc.d/rc.sysinit - fi - - # there might be other services that are useless but the below set is a good start - # some of these might not exist in the image, so we silence chkconfig complaining - # about the service file not being found - for service in \ - acpid apmd auditd autofs cpuspeed dund gpm haldaemon hidd \ - ip6tables irqbalance iscsi iscsid isdn kdump kudzu \ - lm_sensors lvm2-monitor mdmonitor microcode_ctl \ - ntpd pcmcia postfix sendmail udev-post xfs ; - do - chroot $container_rootfs chkconfig 2>/dev/null $service off - done - - for service in rsyslog ; - do - chroot $container_rootfs chkconfig 2>/dev/null $service on - done -} - -container_rootfs_configure() -{ - container_rootfs_patch - echo "Configuring container for Oracle Linux $container_release_major.$container_release_minor" - - # configure the network to use dhcp. we set DHCP_HOSTNAME so the guest - # will report its name and be resolv'able by the hosts dnsmasq - cat < $container_rootfs/etc/sysconfig/network-scripts/ifcfg-eth0 -DEVICE=eth0 -BOOTPROTO=dhcp -ONBOOT=yes -HOSTNAME=$name -DHCP_HOSTNAME=\`hostname\` -NM_CONTROLLED=no -TYPE=Ethernet -EOF - - # set the hostname - if [ $container_release_major -ge "7" ]; then - # systemd honors /etc/hostname - echo "$name" >$container_rootfs/etc/hostname - fi - cat < $container_rootfs/etc/sysconfig/network -NETWORKING=yes -NETWORKING_IPV6=no -HOSTNAME=$name -EOF - - # set minimal hosts - echo "127.0.0.1 localhost $name" > $container_rootfs/etc/hosts - - # this file has to exist for libvirt/Virtual machine monitor to boot the container - touch $container_rootfs/etc/mtab - - # setup console and tty[1-4] for login. note that /dev/console and - # /dev/tty[1-4] will be symlinks to the ptys /dev/lxc/console and - # /dev/lxc/tty[1-4] so that package updates can overwrite the symlinks. - # lxc will maintain these links and bind mount ptys over /dev/lxc/* - # since lxc.tty.dir is specified in the config. - - # allow root login on console, tty[1-4], and pts/0 for libvirt - echo "# LXC (Linux Containers)" >>$container_rootfs/etc/securetty - echo "lxc/console" >>$container_rootfs/etc/securetty - for i in 1 2 3 4; do - echo "lxc/tty$i" >>$container_rootfs/etc/securetty - done - echo "# For libvirt/Virtual Machine Monitor" >>$container_rootfs/etc/securetty - for i in 0 1 2 3 4; do - echo "pts/$i" >>$container_rootfs/etc/securetty - done - - # prevent mingetty from calling vhangup(2) since it fails with userns - if [ -f $container_rootfs/etc/init/tty.conf ]; then - sed -i 's|mingetty|mingetty --nohangup|' $container_rootfs/etc/init/tty.conf - fi - - # create maygetty which only spawns a getty on the console when running - # under lxc, not libvirt-lxc which symlinks /dev/console to the same pty - # as /dev/tty1 - cat <$container_rootfs/sbin/maygetty -#!/bin/sh -if [ "\$container" = "lxc" ]; then - exec /sbin/mingetty \$@ -fi -exec sleep infinity -EOF - chmod 755 $container_rootfs/sbin/maygetty - - # start a getty on /dev/console, /dev/tty[1-4] - if [ $container_release_major = "4" -o $container_release_major = "5" ]; then - sed -i 's|mingetty|mingetty --nohangup|' $container_rootfs/etc/inittab - sed -i '/1:2345:respawn/i cns:2345:respawn:/sbin/maygetty --nohangup --noclear console' $container_rootfs/etc/inittab - sed -i '/5:2345:respawn/d' $container_rootfs/etc/inittab - sed -i '/6:2345:respawn/d' $container_rootfs/etc/inittab - fi - - if [ $container_release_major = "6" ]; then - cat < $container_rootfs/etc/init/console.conf -# console - getty -# -# This service maintains a getty on the console from the point the system is -# started until it is shut down again. - -start on stopped rc RUNLEVEL=[2345] -stop on runlevel [!2345] -env container - -respawn -exec /sbin/maygetty --nohangup --noclear /dev/console -EOF - fi - - # lxc-shutdown sends SIGPWR to init, OL4 and OL5 have SysVInit, just - # make it do shutdown now instead of delaying 2 minutes. OL6 uses - # upstart, so we create an upstart job to handle SIGPWR to shut down - # cleanly. We use "init 0" instead of shutdown -h now to avoid SELinux - # permission denied when upstart's shutdown tries to connect to the - # /com/ubuntu/upstart socket. - if [ $container_release_major = "4" -o $container_release_major = "5" ]; then - sed -i 's|pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; |pf::powerfail:/sbin/shutdown -f -h now "|' $container_rootfs/etc/inittab - elif [ $container_release_major = "6" ]; then - cat < $container_rootfs/etc/init/power-status-changed.conf -# power-status-changed - used to cleanly shut down the container -# -# This task is run whenever init receives SIGPWR -# Used to shut down the machine. - -start on power-status-changed - -exec init 0 -EOF - fi - - # start with a clean /var/log/messages - rm -f $container_rootfs/var/log/messages - - # set initial timezone as on host - if [ -f /etc/sysconfig/clock ]; then - . /etc/sysconfig/clock - if [ $container_release_major = "5" -o $container_release_major = "6" ]; then - echo ZONE=$ZONE > $container_rootfs/etc/sysconfig/clock - chroot $container_rootfs tzdata-update - else - ZONE="${ZONE// /_}" - chroot $container_rootfs ln -sf ../usr/share/zoneinfo/$ZONE /etc/localtime - fi - else - ZONE=`readlink /etc/localtime | sed -s "s/\.\.\/usr\/share\/zoneinfo\///g"` - if [ "$ZONE" ]; then - if [ $container_release_major = "5" -o $container_release_major = "6" ]; then - echo ZONE=$ZONE > $container_rootfs/etc/sysconfig/clock - chroot $container_rootfs tzdata-update - else - # if /etc/localtime is a symlink, this should preserve it. - cp -a /etc/localtime $container_rootfs/etc/localtime - fi - else - echo "Timezone in container is not configured. Adjust it manually." - fi - fi - - # add oracle user - chroot $container_rootfs useradd -m -s /bin/bash oracle - printf "Added container user:\033[1moracle\033[0m\n" - printf "Added container user:\033[1mroot\033[0m\n" -} - -# create the container's lxc config file -container_config_create() -{ - echo "Create configuration file $cfg_dir/config" - mkdir -p $cfg_dir || die "unable to create config dir $cfg_dir" - - echo "# Common configuration" >> $cfg_dir/config - if [ -e "@LXCTEMPLATECONFIG@/oracle.common.conf" ]; then - echo "lxc.include = @LXCTEMPLATECONFIG@/oracle.common.conf" >> $cfg_dir/config - fi - - cat <> $cfg_dir/config || die "unable to create $cfg_dir/config" -# Container configuration for Oracle Linux $container_release_major.$container_release_minor -lxc.arch = $arch -lxc.uts.name = $name -EOF - grep -q "^lxc.rootfs.path" $cfg_dir/config 2>/dev/null || echo "lxc.rootfs.path = $container_rootfs" >> $cfg_dir/config - - if [ $container_release_major != "4" ]; then - echo "lxc.cap.drop = sys_resource" >>$cfg_dir/config - fi - - # systemd services like logind and journald need these - if [ $container_release_major != "7" ]; then - echo "lxc.cap.drop = setfcap setpcap" >>$cfg_dir/config - fi - - echo "# Networking" >>$cfg_dir/config - # see if the default network settings were already specified - lxc_network_type=`grep '^lxc.net.0.type' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'` - if [ -z "$lxc_network_type" ]; then - echo "lxc.net.0.type = veth" >>$cfg_dir/config - lxc_network_type=veth - fi - - lxc_network_link=`grep '^lxc.net.0.link' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'` - if [ -z "$lxc_network_link" ]; then - echo "lxc.net.0.link = lxcbr0" >>$cfg_dir/config - lxc_network_link=lxcbr0 - fi - - lxc_network_hwaddr=`grep '^lxc.net.0.hwaddr' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'` - if [ -z "$lxc_network_hwaddr" ]; then - # generate a hwaddr for the container - # see http://sourceforge.net/tracker/?func=detail&aid=3411497&group_id=163076&atid=826303 - local hwaddr="00:16:3e:`dd if=/dev/urandom bs=8 count=1 2>/dev/null |od -t x8 | \ - head -n1 | awk '{print $2}' | cut -c1-6 | \ - sed 's/\(..\)/\1:/g; s/.$//'`" - echo "lxc.net.0.hwaddr = $hwaddr" >>$cfg_dir/config - fi - - lxc_network_flags=`grep '^lxc.net.0.flags' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'` - if [ -z "$lxc_network_flags" ]; then - echo "lxc.net.0.flags = up" >>$cfg_dir/config - fi - - cat <> $cfg_dir/config || die "unable to create $cfg_dir/config" -lxc.net.0.name = eth0 -lxc.net.0.mtu = 1500 -EOF -} - -container_rootfs_clone() -{ - if is_btrfs_subvolume $template_rootfs; then - # lxc-create already made $container_rootfs a btrfs subvolume, but - # in this case we want to snapshot the original subvolume so we we - # have to delete the one that lxc-create made - btrfs subvolume delete $container_rootfs - btrfs subvolume snapshot $template_rootfs $container_rootfs || die "btrfs clone template" - else - echo "Copying rootfs ..." - cp -axT $template_rootfs $container_rootfs || die "copy template" - fi -} - -container_rootfs_repo_create() -{ - echo "# LXC generated .repo file" >$1 - echo "[$2]" >>$1 - echo "name=Oracle Linux $container_release_major.$container_release_minor ($basearch)" >>$1 - echo "baseurl=$3/" >>$1 - echo "enabled=1" >>$1 - echo "skip_if_unavailable=1" >>$1 - - if [ "$4" != "" ]; then - echo "gpgkey=$yum_url/RPM-GPG-KEY-oracle-ol$container_release_major" >>$1 - echo "gpgcheck=1" >>$1 - else - echo "gpgcheck=0" >>$1 - fi -} - -container_rootfs_dev_create() -{ - # create required devices. note that /dev/console will be created by lxc - # or libvirt itself to be a symlink to the right pty. - # take care to not nuke /dev in case $container_rootfs isn't set - dev_path="$container_rootfs/dev" - if [ $container_rootfs != "/" -a -d $dev_path ]; then - rm -rf $dev_path - fi - mkdir -p $dev_path - if can_chcon; then - # ensure symlinks created in /dev have the right context - chcon -t device_t $dev_path - fi - mknod -m 666 $dev_path/null c 1 3 - mknod -m 666 $dev_path/zero c 1 5 - mknod -m 666 $dev_path/random c 1 8 - mknod -m 666 $dev_path/urandom c 1 9 - mkdir -m 755 $dev_path/pts - mkdir -m 1777 $dev_path/shm - mknod -m 666 $dev_path/tty c 5 0 - mknod -m 666 $dev_path/tty1 c 4 1 - mknod -m 666 $dev_path/tty2 c 4 2 - mknod -m 666 $dev_path/tty3 c 4 3 - mknod -m 666 $dev_path/tty4 c 4 4 - mknod -m 666 $dev_path/full c 1 7 - mknod -m 600 $dev_path/initctl p - - # set selinux labels same as host - if can_chcon; then - for node in null zero random urandom pts shm \ - tty tty0 tty1 tty2 tty3 tty4 full ; - do - chcon --reference /dev/$node $dev_path/$node 2>/dev/null - done - fi -} - -container_rootfs_create() -{ - if can_chcon; then - chcon --reference / $container_rootfs 2>/dev/null - fi - - cmds="rpm wget yum" - if [ $container_release_major -lt "6" ]; then - if [ $host_distribution = "Ubuntu" -o $host_distribution = "Debian" ]; then - db_dump_cmd="db5.1_dump" - fi - if [ $host_distribution = "OracleServer" -o \ - $host_distribution = "Fedora" ]; then - db_dump_cmd="db_dump" - fi - - cmds="$cmds $db_dump_cmd file" - fi - for cmd in $cmds; do - which $cmd >/dev/null 2>&1 - if [ $? -ne 0 ]; then - die "The $cmd command is required, please install it" - fi - done - - mkdir -p @LOCALSTATEDIR@/lock/subsys - ( - flock -x 9 - if [ $? -ne 0 ]; then - die "The template is busy." - fi - - echo "Yum installing release $container_release_major.$container_release_minor for $basearch" - - if [ -n "$repourl" ]; then - yum_url=$repourl - else - yum_url=http://public-yum.oracle.com - fi - if [ $container_release_major = "4" -o $container_release_major = "5" ]; then - latest_L="el" - latest_U="EL" - else - latest_L="ol" - latest_U="OL" - fi - - if [ -n "$baseurl" ]; then - # create .repo pointing at baseurl - repo="lxc-install" - mkdir -p $container_rootfs/etc/yum.repos.d - container_rootfs_repo_create \ - $container_rootfs/etc/yum.repos.d/lxc-install.repo $repo $baseurl - else - # get public-yum repo file - if [ $container_release_major = "4" ]; then - repofile=public-yum-el4.repo - elif [ $container_release_major = "5" ]; then - repofile=public-yum-el5.repo - elif [ $container_release_major = "6" ]; then - repofile=public-yum-ol6.repo - elif [ $container_release_major = "7" ]; then - repofile=public-yum-ol7.repo - else - die "Unsupported release $container_release_major" - fi - - mkdir -p $container_rootfs/etc/yum.repos.d - wget -q $yum_url/$repofile -O $container_rootfs/etc/yum.repos.d/$repofile - if [ $? -ne 0 ]; then - die "Unable to download repo file $yum_url/$repofile, release unavailable" - fi - - # yum will take $basearch from host, so force the arch we want - sed -i "s|\$basearch|$basearch|" $container_rootfs/etc/yum.repos.d/$repofile - - # replace url if they specified one - if [ -n "$repourl" ]; then - sed -i "s|baseurl=http://public-yum.oracle.com/repo|baseurl=$repourl/repo|" $container_rootfs/etc/yum.repos.d/$repofile - sed -i "s|gpgkey=http://public-yum.oracle.com|gpgkey=$repourl|" $container_rootfs/etc/yum.repos.d/$repofile - fi - - # disable all repos, then enable the repo for the version we are installing. - if [ $container_release_minor = "latest" ]; then - repo=$latest_L""$container_release_major"_"$container_release_minor - elif [ $container_release_major = "7" ]; then - repo="ol"$container_release_major"_u"$container_release_minor"_base" - elif [ $container_release_major = "6" ]; then - if [ $container_release_minor = "0" ]; then - repo="ol"$container_release_major"_ga_base" - else - repo="ol"$container_release_major"_u"$container_release_minor"_base" - fi - elif [ $container_release_major = "5" ]; then - if [ $container_release_minor = "0" ]; then - repo="el"$container_release_major"_ga_base" - elif [ $container_release_minor -lt "6" ]; then - repo="el"$container_release_major"_u"$container_release_minor"_base" - else - repo="ol"$container_release_major"_u"$container_release_minor"_base" - fi - elif [ $container_release_major = "4" -a $container_release_minor -gt "5" ]; then - repo="el"$container_release_major"_u"$container_release_minor"_base" - else - die "Unsupported release $container_release_major.$container_release_minor" - fi - sed -i "s|enabled=1|enabled=0|" $container_rootfs/etc/yum.repos.d/$repofile - sed -i "/\[$repo\]/,/\[/ s/enabled=0/enabled=1/" $container_rootfs/etc/yum.repos.d/$repofile - fi - - container_rootfs_dev_create - - # don't put devpts,proc, nor sysfs in here, it will already be mounted for us by lxc/libvirt - echo "" >$container_rootfs/etc/fstab - - # create rpm db, download and yum install minimal packages - mkdir -p $container_rootfs/var/lib/rpm - rpm --root $container_rootfs --initdb - yum_args="--installroot $container_rootfs --disablerepo=* --enablerepo=$repo -y --nogpgcheck" - min_pkgs="yum initscripts passwd rsyslog vim-minimal openssh-server openssh-clients dhclient chkconfig rootfiles policycoreutils oraclelinux-release" - if [ $container_release_major -lt "6" ]; then - min_pkgs="$min_pkgs db4-utils" - fi - - # we unshare the mount namespace because yum installing the ol4 - # packages causes $rootfs/proc to be mounted on - lxc-unshare -s MOUNT yum -- $yum_args install $min_pkgs $user_pkgs - if [ $? -ne 0 ]; then - die "Failed to download and install the rootfs, aborting." - fi - - # rsyslog and pam depend on coreutils for some common commands in - # their POSTIN scriptlets, but coreutils wasn't installed yet. now - # that coreutils is installed, reinstall the packages so their POSTIN - # runs right. similarly, libutempter depends on libselinux.so.1 when - # it runs /usr/sbin/groupadd, so reinstall it too - redo_pkgs="" - if [ $container_release_major = "5" ]; then - if [ $container_release_minor = "latest" ]; then - redo_pkgs="pam rsyslog libutempter" - elif [ $container_release_minor -lt 2 ]; then - redo_pkgs="pam" - elif [ $container_release_minor -lt 6 ]; then - redo_pkgs="pam rsyslog" - elif [ $container_release_minor -gt 5 ]; then - redo_pkgs="pam rsyslog libutempter" - fi - fi - # shadow utils fails on ol4 and ol6.1 - if [ $container_release_major = "4" -o \ - $container_release_major = "6" -a $container_release_minor = "1" ]; then - redo_pkgs="shadow-utils" - fi - if [ x"$redo_pkgs" != x ]; then - rpm --root $container_rootfs --nodeps -e $redo_pkgs - lxc-unshare -s MOUNT yum -- $yum_args install $redo_pkgs - if [ $? -ne 0 ]; then - die "Unable to reinstall packages" - fi - fi - - # if installing from a baseurl, create a .repo that the container - # can use to update to _latest from http://public-yum.oracle.com - if [ -n "$baseurl" ]; then - container_rootfs_repo_create \ - "$container_rootfs/etc/yum.repos.d/public-yum-"$latestL""$container_release_major".repo" \ - $latest_L""$container_release_major"_latest" \ - $yum_url"/repo/OracleLinux/"$latest_U""$container_release_major"/latest/$basearch" gpg - fi - - # these distributions put the rpm database in a place the guest is - # not expecting it, so move it - if [ $host_distribution = "Ubuntu" -o $host_distribution = "Debian" ]; then - mv $container_rootfs/$HOME/.rpmdb/* $container_rootfs/var/lib/rpm - fi - - # if the native rpm created the db with Hash version 9, we need to - # downgrade it to Hash version 8 for use with OL5.x - db_version=`file $container_rootfs/var/lib/rpm/Packages | \ - grep -o 'version [0-9]*' |awk '{print $2}'` - if [ $container_release_major -lt "6" -a $db_version != "8" ]; then - echo "Fixing (downgrading) rpm database from version $db_version" - rm -f $container_rootfs/var/lib/rpm/__db* - for db in $container_rootfs/var/lib/rpm/* ; do - $db_dump_cmd $db |chroot $container_rootfs db_load /var/lib/rpm/`basename $db`.new - mv $db.new $db - done - fi - - # the host rpm may not be the same as the guest, rebuild the db with - # the guest rpm version - echo "Rebuilding rpm database" - rm -f $container_rootfs/var/lib/rpm/__db* - chroot $container_rootfs rpm --rebuilddb >/dev/null 2>&1 - - ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-oracle-$name - if [ $? -ne 0 ]; then - exit 1 - fi -} - -container_release_get() -{ - if [ -f $1/etc/oracle-release ]; then - container_release_version=`cat $1/etc/oracle-release |awk '/^Oracle/ {print $5}'` - container_release_major=`echo $container_release_version |awk -F '.' '{print $1}'` - container_release_minor=`echo $container_release_version |awk -F '.' '{print $2}'` - elif grep -q "Enterprise Linux AS" $1/etc/redhat-release; then - container_release_major=`cat $1/etc/redhat-release |awk '{print $7}'` - container_release_minor=`cat $1/etc/redhat-release |awk '{print $10}' |tr -d ")"` - container_release_version="$container_release_major.$container_release_minor" - elif grep -q "Enterprise Linux Server" $1/etc/redhat-release; then - container_release_version=`cat $1/etc/redhat-release |awk '{print $7}'` - container_release_major=`echo $container_release_version |awk -F '.' '{print $1}'` - container_release_minor=`echo $container_release_version |awk -F '.' '{print $2}'` - else - echo "Unable to determine container release version" - exit 1 - fi -} - -usage() -{ - cat < architecture (ie. i386, x86_64) - -R|--release= release to download for the new container - --rootfs= rootfs path - -r|--rpms= additional rpms to install into container - -u|--url= replace yum repo url (ie. Oracle public-yum mirror) - --baseurl= use package repository (ie. file:///mnt) - arch and release must also be specified - -t|--templatefs= copy/clone rootfs at path instead of downloading - -P|--patch= only patch the rootfs at path for use as a container - -h|--help - -Release is of the format "major.minor", for example "5.8", "6.3", or "6.latest" -This template supports Oracle Linux releases 4.6 - 7.0 -EOF - return 0 -} - -options=$(getopt -o hp:n:a:R:r:u:t: -l help,rootfs:,path:,name:,arch:,release:,rpms:,url:,templatefs:,patch:,baseurl: -- "$@") -if [ $? -ne 0 ]; then - usage $(basename $0) - exit 1 -fi - -eval set -- "$options" -while true -do - case "$1" in - -h|--help) usage $0 && exit 0;; - -p|--path) cfg_dir=$2; shift 2;; - --rootfs) container_rootfs=$2; shift 2;; - -n|--name) name=$2; shift 2;; - -a|--arch) arch=$2; shift 2;; - -R|--release) container_release_version=$2; shift 2;; - -r|--rpms) user_pkgs=$2; shift 2;; - -u|--url) repourl=$2; shift 2;; - -t|--templatefs) template_rootfs=$2; shift 2;; - --patch) patch_rootfs=$2; shift 2;; - --baseurl) baseurl=$2; shift 2;; - --) shift 1; break ;; - *) break ;; - esac -done - -# make sure mandatory args are given and valid -if [ "$(id -u)" != "0" ]; then - echo "This script should be run as 'root'" - exit 1 -fi - -if [ -n "$baseurl" ]; then - if [ "$arch" = "" -o "$container_release_version" = "" ]; then - echo "The --arch and --release must be specified when using --baseurl" - usage - exit 1 - fi -fi - -if [ "$arch" = "" ]; then - arch=$(uname -m) -fi - -if [ -n "$patch_rootfs" ]; then - container_rootfs="$patch_rootfs" - container_release_get $container_rootfs - container_rootfs_patch - exit 0 -fi - -if [ -z $name ]; then - echo "Container name must be given" - usage - exit 1 -fi - -if [ -z $cfg_dir ]; then - echo "Configuration directory must be given, check lxc-create" - usage - exit 1 -fi - -basearch=$arch -if [ "$arch" = "i686" ]; then - basearch="i386" -fi - -if [ "$arch" != "i386" -a "$arch" != "x86_64" ]; then - echo "Bad architecture given, check lxc-create" - usage - exit 1 -fi - -if which lsb_release >/dev/null 2>&1; then - host_distribution=`lsb_release --id |awk '{print $3}'` - host_release_version=`lsb_release --release |awk '{print $2}'` - host_release_major=`echo $host_release_version |awk -F '.' '{print $1}'` - host_release_minor=`echo $host_release_version |awk -F '.' '{print $2}'` -else - if [ -f /etc/fedora-release ]; then - host_distribution="Fedora" - host_release_version=`cat /etc/fedora-release |awk '{print $3}'` - host_release_major=$host_release_version - host_release_minor=0 - elif [ -f /etc/oracle-release ]; then - host_distribution="OracleServer" - host_release_version=`cat /etc/oracle-release |awk '{print $5}'` - host_release_major=`echo $host_release_version |awk -F '.' '{print $1}'` - host_release_minor=`echo $host_release_version |awk -F '.' '{print $2}'` - else - echo "Unable to determine host distribution, ensure lsb_release is installed" - exit 1 - fi -fi -echo "Host is $host_distribution $host_release_version" - -if [ -z "$container_rootfs" ]; then - container_rootfs="$cfg_dir/rootfs" -fi - -if [ -n "$template_rootfs" ]; then - container_release_get $template_rootfs -else - if [ -z "$container_release_version" ]; then - if [ $host_distribution = "OracleServer" ]; then - container_release_version=$host_release_version - else - echo "No release specified with -R, defaulting to 6.5" - container_release_version="6.5" - fi - fi - container_release_major=`echo $container_release_version |awk -F '.' '{print $1}'` - container_release_minor=`echo $container_release_version |awk -F '.' '{print $2}'` -fi - -container_config_create -if [ -n "$template_rootfs" ]; then - container_rootfs_clone -else - container_rootfs_create -fi - -container_release_get $container_rootfs - -container_rootfs_configure - -echo "Container : $container_rootfs" -echo "Config : $cfg_dir/config" -echo "Network : eth0 ($lxc_network_type) on $lxc_network_link" diff --git a/templates/lxc-plamo.in b/templates/lxc-plamo.in deleted file mode 100644 index ec442ec3a..000000000 --- a/templates/lxc-plamo.in +++ /dev/null @@ -1,384 +0,0 @@ -#!/bin/bash -eu - -# -# template script for generating Plamo Linux container for LXC -# - -# -# lxc: linux Container library - -# Authors: -# KATOH Yasufumi -# TAMUKI Shoichi - -# 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 - -# ref. https://github.com/Ponce/lxc-slackware/blob/master/lxc-slackware -# lxc-ubuntu script - -# 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 - -[ -r /etc/default/lxc ] && . /etc/default/lxc - -DLSCHEME=${DLSCHEME:-"http"} -MIRRORSRV=${MIRRORSRV:-"repository.plamolinux.org"} -MIRRORPATH=${MIRRORPATH:-"/pub/linux/Plamo"} -CATEGORIES=${CATEGORIES-"00_base 01_minimum"} -EXTRACTGRS=${EXTRACTGRS-""} -IGNOREPKGS=${IGNOREPKGS-"grub kernel lilo linux_firmware microcode_ctl - cpufreqd cpufrequtils gpm ntp kmod"} -ADDONPKGS=${ADDONPKGS-"`echo contrib/Hamradio/{morse,qrq}`"} - -download_plamo() { - # check the mini plamo was not already downloaded - if ! mkdir -p $ptcache ; then - echo "Failed to create '$ptcache' directory." - return 1 - fi - # download a mini plamo into a cache - echo "Downloading Plamo-$release minimal..." - cd $ptcache - case $DLSCHEME in http) depth=2 ;; ftp) depth=3 ;; esac - rej=${IGNOREPKGS%% *} ; [ -n "$rej" ] && rej="$rej-*" - if [ `echo $IGNOREPKGS | wc -w` -gt 1 ] ; then - for p in ${IGNOREPKGS#* } ; do rej="$rej,$p-*" ; done - fi - for i in $CATEGORIES ; do - wget -nv -e robots=off -r -l $depth -nd -A .tgz,.txz -R "$rej" \ - -I $MIRRORPATH/Plamo-$release/$arch/plamo/$i \ - -X $MIRRORPATH/Plamo-$release/$arch/plamo/$i/old \ - $DLSCHEME://$MIRRORSRV$MIRRORPATH/Plamo-$release/$arch/plamo/$i - if [ $? -ne 0 ] ; then - echo "Failed to download the rootfs, aborting." - return 1 - fi - done - for i in $EXTRACTGRS ; do - wget -nv -e robots=off -r -l $depth -nd -A .tgz,.txz -R "$rej" \ - -I $MIRRORPATH/Plamo-$release/$arch/contrib/$i \ - -X $MIRRORPATH/Plamo-$release/$arch/contrib/$i/old \ - $DLSCHEME://$MIRRORSRV$MIRRORPATH/Plamo-$release/$arch/contrib/$i - if [ $? -ne 0 ] ; then - echo "Failed to download the rootfs, aborting." - return 1 - fi - done - for p in $ADDONPKGS ; do - wget -nv -e robots=off -r -l $depth -nd -A "`basename $p`-*" \ - -I $MIRRORPATH/Plamo-$release/$arch/`dirname $p` \ - -X $MIRRORPATH/Plamo-$release/$arch/`dirname $p`/old \ - $DLSCHEME://$MIRRORSRV$MIRRORPATH/Plamo-$release/$arch/`dirname $p` - if [ $? -ne 0 ] ; then - echo "Failed to download the rootfs, aborting." - return 1 - fi - done - mv $ptcache $dlcache - echo "Download complete." - return 0 -} - -copy_plamo() { - # make a local copy of the mini plamo - echo "Copying $rtcache to $rootfs..." - mkdir -p $rootfs - find $rtcache -mindepth 1 -maxdepth 1 -exec cp -a {} $rootfs \; || return 1 - return 0 -} - -install_plamo() { - mkdir -p @LOCALSTATEDIR@/lock/subsys - ( - if ! flock -n 9 ; then - echo "Cache repository is busy." - return 1 - fi - echo "Checking cache download in $dlcache..." - if [ ! -d $dlcache ] ; then - if ! download_plamo ; then - echo "Failed to download plamo $release base packages." - return 1 - fi - fi - # install "installpkg" command temporarily with static linked tar - # command into the lxc cache directory to keep the original uid/ - # gid of files/directories. - echo "Installing 'installpkg' command into $dlcache/sbin..." - ( cd $dlcache ; tar xpJf hdsetup-*.txz ; rm -rf tmp usr var ) - sed -i "/ldconfig/!s@/sbin@$dlcache&@g" $dlcache/sbin/installpkg* - PATH=$dlcache/sbin:$PATH - echo "Installing packages to $rtcache..." - if [ ! -d $rtcache ] ; then - mkdir -p $rtcache - for p in `ls -cr $dlcache/*.t?z` ; do - installpkg -root $rtcache -priority ADD $p - done - fi - echo "Copy $rtcache to $rootfs..." - if ! copy_plamo ; then - echo "Failed to copy rootfs." - return 1 - fi - return 0 - ) 9> @LOCALSTATEDIR@/lock/subsys/lxc-plamo -} - -configure_plamo() { - # suppress log level output for udev - sed -i 's/="err"/=0/' $rootfs/etc/udev/udev.conf - # /etc/fstab - cat <<- "EOF" > $rootfs/etc/fstab - none /proc proc defaults 0 0 - none /sys sysfs defaults 0 0 - none /dev tmpfs defaults 0 0 - none /tmp tmpfs defaults 0 0 - none /dev/pts devpts gid=5,mode=620 0 0 - none /proc/bus/usb usbfs noauto 0 0 - none /var/lib/nfs/rpc_pipefs rpc_pipefs defaults 0 0 - EOF - # /etc/inittab - cat <<- "EOF" | patch $rootfs/etc/inittab - 32,33c32,33 - < # What to do when power fails (shutdown to single user). - < pf::powerfail:/sbin/shutdown -f +5 "THE POWER IS FAILING" - --- - > # What to do when power fails (shutdown). - > pf::powerfail:/sbin/shutdown -h +0 "THE POWER IS FAILING" - 47a48 - > 1:1235:respawn:/sbin/agetty 38400 console - 52,53d52 - < c5:1235:respawn:/sbin/agetty 38400 tty5 linux - < c6:12345:respawn:/sbin/agetty 38400 tty6 linux - EOF - # set the hostname - echo "$name" > $rootfs/etc/HOSTNAME - # set minimal hosts - echo "127.0.0.1 localhost $name" > $rootfs/etc/hosts - # configure the network using the dhcp - echo "DHCP" > $rootfs/var/run/inet1-scheme - # localtime (JST) - ln -s ../usr/share/zoneinfo/Asia/Tokyo $rootfs/etc/localtime - # disable pam_loginuid.so in /etc/pam.d/login (for libvirt's lxc driver) - sed -i '/pam_loginuid/s/^/#/' $rootfs/etc/pam.d/login - # glibc configure - mv $rootfs/etc/ld.so.conf{.new,} - chroot $rootfs ldconfig - - # delete unnecessary process from rc.S - ed - $rootfs/etc/rc.d/rc.S <<- "EOF" - /^mount -w -n -t proc/;/^mkdir \/dev\/shm/-1d - /^mknod \/dev\/null/;/^# Clean \/etc\/mtab/-2d - /^# copy the rules/;/^# Set the hostname/-1d - /^# Check the integrity/;/^# Clean up temporary/-1d - w - EOF - - # delete unnecessary process from rc.M - ed - $rootfs/etc/rc.d/rc.M <<- "EOF" - /^# Screen blanks/;/^# Initialize ip6tables/-1d - /^# Initialize sysctl/;/^echo "Starting services/-1d - /^sync/;/^# All done/-1d - w - EOF - - # delete unnecessary process from rc.6 - ed - $rootfs/etc/rc.d/rc.6 <<- "EOF" - /^# Save system time/;/^# Unmount any remote filesystems/-1d - /^# Turn off swap/;/^# See if this is a powerfail situation/-1d - w - EOF - - # /etc/rc.d/rc.inet1.tradnet - head -n-93 $rootfs/sbin/netconfig.tradnet > /tmp/netconfig.rconly - cat <<- EOF >> /tmp/netconfig.rconly - PCMCIA=n - RC=$rootfs/etc/rc.d/rc.inet1.tradnet - IFCONFIG=sbin/ifconfig - ROUTE=sbin/route - INET1SCHEME=var/run/inet1-scheme - IPADDR=127.0.0.1 - NETWORK=127.0.0.0 - DHCPCD=usr/sbin/dhclient - LOOPBACK=y - make_config_file - EOF - rm -f $rootfs/etc/rc.d/rc.inet1.tradnet - sh /tmp/netconfig.rconly - rm -f /tmp/netconfig.rconly - sed -i '/cmdline/s/if/& false \&\&/' $rootfs/etc/rc.d/rc.inet1.tradnet - # /etc/rc.d/rc.inet2 - sed -i '/rpc.mountd/s/^/#/' $rootfs/etc/rc.d/rc.inet2 - sed -i '/modprobe/s/^/#/' $rootfs/etc/rc.d/rc.inet2 - # configure to start only the minimum of service - chmod 644 $rootfs/etc/rc.d/init.d/saslauthd - chmod 644 $rootfs/etc/rc.d/init.d/open-iscsi - rm -f $rootfs/etc/rc.d/init.d/postfix - rm -f $rootfs/var/log/initpkg/shadow - return 0 -} - -copy_configuration() { - ret=0 - cat <<- EOF >> $path/config || let ret++ - lxc.uts.name = $name - lxc.arch = $arch - EOF - if [ -f "@LXCTEMPLATECONFIG@/plamo.common.conf" ] ; then - cat <<- "EOF" >> $path/config || let ret++ - - lxc.include = @LXCTEMPLATECONFIG@/plamo.common.conf - EOF - fi - if [ $ret -ne 0 ] ; then - echo "Failed to add configuration." - return 1 - fi - return 0 -} - -post_process() { - # nothing do in Plamo Linux - true -} - -do_bindhome() { - # bind-mount the user's path into the container's /home - h=`getent passwd $bindhome | cut -d: -f6` - mkdir -p $rootfs/$h - echo "lxc.mount.entry = $h $rootfs/$h none bind 0 0" >> $path/config - # copy /etc/passwd, /etc/shadow, and /etc/group entries into container - if ! pwd=`getent passwd $bindhome` ; then - echo "Warning: failed to copy password entry for $bindhome." - else - echo $pwd >> $rootfs/etc/passwd - fi - echo `getent shadow $bindhome` >> $rootfs/etc/shadow -} - -cleanup() { - [ -d $dlcache -a -d $rtcache ] || return 0 - # lock, so we won't purge while someone is creating a repository - ( - if ! flock -n 9 ; then - echo "Cache repository is busy." - return 1 - fi - echo "Purging the download cache..." - rm -rf --one-file-system $dlcache $rtcache || return 1 - echo "Done." - return 0 - ) 9> @LOCALSTATEDIR@/lock/subsys/lxc-plamo -} - -usage() { - cat <<- EOF - $prog [-h|--help] -p|--path= -n|--name= --rootfs= - [-c|--clean] [-r|--release=] [-a|--arch=] - [-b|--bindhome=] - release: $release - arch: x86 or x86_64: defaults to host arch - bindhome: bind 's home into the container - EOF -} - -prog=`basename $0` -path="" ; name="" ; rootfs="" -clean=0 -release=${release:-6.x} -arch=`uname -m | sed 's/i.86/x86/'` ; hostarch=$arch -bindhome="" -sopts=hp:n:cr:a:b: -lopts=help,path:,name:,rootfs:,clean,release:,arch:,bindhome: -if ! options=`getopt -o $sopts -l $lopts -- "$@"` ; then - usage - exit 1 -fi -eval set -- "$options" -while true ; do - case "$1" in - -h|--help) usage && exit 0 ;; - -p|--path) path=$2 ; shift 2 ;; - -n|--name) name=$2 ; shift 2 ;; - --rootfs) rootfs=$2 ; shift 2 ;; - -c|--clean) clean=1 ; shift 1 ;; - -r|--release) release=$2 ; shift 2 ;; - -a|--arch) arch=$2 ; shift 2 ;; - -b|--bindhome) bindhome=$2 ; shift 2 ;; - --) shift 1 ; break ;; - *) break ;; - esac -done -if [ $clean -eq 1 -a -z "$path" ] ; then - cleanup || exit 1 - exit 0 -fi -if [ $hostarch == "x86" -a $arch == "x86_64" ] ; then - echo "Can't create x86_64 container on x86." - exit 1 -fi -if [ -z "$path" ] ; then - echo "'path' parameter is required." - exit 1 -fi -if [ -z "$name" ] ; then - echo "'name' parameter is required." - exit 1 -fi -if [ `id -u` -ne 0 ] ; then - echo "This script should be run as 'root'." - exit 1 -fi -cache="${LXC_CACHE_PATH:-@LOCALSTATEDIR@/cache/lxc}" -ptcache=$cache/partial-${prog##*-}-$release-$arch -dlcache=$cache/cache-${prog##*-}-$release-$arch -rtcache=$cache/rootfs-${prog##*-}-$release-$arch -if [ -z "$rootfs" ] ; then - if grep -q "^lxc.rootfs.path" $path/config ; then - rootfs=`awk -F= '/^lxc.rootfs.path =/{ print $2 }' $path/config` - else - rootfs=$path/rootfs - fi -fi -if ! install_plamo ; then - echo "Failed to install plamo $release." - exit 1 -fi -if ! configure_plamo ; then - echo "Failed to configure plamo $release for a container." - exit 1 -fi -if ! copy_configuration ; then - echo "Failed to write configuration file." - exit 1 -fi -post_process -if [ -n "$bindhome" ] ; then - do_bindhome -fi -if [ $clean -eq 1 ] ; then - cleanup || exit 1 - exit 0 -fi diff --git a/templates/lxc-pld.in b/templates/lxc-pld.in deleted file mode 100644 index b748cb87b..000000000 --- a/templates/lxc-pld.in +++ /dev/null @@ -1,484 +0,0 @@ -#!/bin/sh - -# -# template script for generating PLD Linux container for LXC -# - -# -# lxc: Linux Container library - -# Authors: -# Elan Ruusamäe - -# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 - -# Configuration -arch=$(uname -m) -cache_base=@LOCALSTATEDIR@/cache/lxc/pld/$arch -default_path=@LXCPATH@ - -if [ -e /etc/os-release ]; then - # This is a shell friendly configuration file. We can just source it. - # What we're looking for in here is the ID, VERSION_ID and the CPE_NAME - . /etc/os-release - echo "Host CPE ID from /etc/os-release: ${CPE_NAME}" -fi - -if [ "${CPE_NAME}" != "" -a "${ID}" = "pld" -a "${VERSION_ID}" != "" ]; then - pld_host_ver=${VERSION_ID} - is_pld=true -elif [ -e /etc/pld-release ]; then - # Only if all other methods fail, try to parse the pld-release file. - pld_host_ver=$(sed -e '/PLD /!d' -e 's/^\([0-9.]*\)\sPLD.*/\1/' < /etc/pld-release) - if [ "$pld_host_ver" != "" ]; then - is_pld=true - fi -fi - -# Map a few architectures to their generic PLD Linux repository archs. -case "$pld_host_ver:$arch" in -3.0:i586) arch=i486 ;; -esac - -configure_pld() -{ - - # disable selinux - mkdir -p $rootfs_path/selinux - echo 0 > $rootfs_path/selinux/enforce - - # configure the network using the dhcp - sed -i -e "s/^HOSTNAME=.*/HOSTNAME=${utsname}/" ${rootfs_path}/etc/sysconfig/network - - # set hostname on systemd - if [ $release = "3.0" ]; then - echo "${utsname}" > ${rootfs_path}/etc/hostname - fi - - # set minimal hosts - test -e $rootfs_path/etc/hosts || \ - cat < $rootfs_path/etc/hosts -127.0.0.1 localhost.localdomain localhost $utsname -::1 localhost6.localdomain6 localhost6 -EOF - - dev_path="${rootfs_path}/dev" - rm -rf $dev_path - mkdir -p $dev_path - mknod -m 666 ${dev_path}/null c 1 3 - mknod -m 666 ${dev_path}/zero c 1 5 - mknod -m 666 ${dev_path}/random c 1 8 - mknod -m 666 ${dev_path}/urandom c 1 9 - mkdir -m 755 ${dev_path}/pts - mkdir -m 1777 ${dev_path}/shm - mknod -m 666 ${dev_path}/tty c 5 0 - mknod -m 666 ${dev_path}/tty0 c 4 0 - mknod -m 666 ${dev_path}/tty1 c 4 1 - mknod -m 666 ${dev_path}/tty2 c 4 2 - mknod -m 666 ${dev_path}/tty3 c 4 3 - mknod -m 666 ${dev_path}/tty4 c 4 4 - mknod -m 600 ${dev_path}/console c 5 1 - mknod -m 666 ${dev_path}/full c 1 7 - mknod -m 600 ${dev_path}/initctl p - mknod -m 666 ${dev_path}/ptmx c 5 2 - - if [ -n "${root_password}" ]; then - echo "setting root passwd to $root_password" - echo "root:$root_password" | chroot $rootfs_path chpasswd - fi - - return 0 -} - -configure_pld_init() -{ - # default powerfail action waits 2 minutes. for lxc we want it immediately - sed -i -e '/^pf::powerfail:/ s,/sbin/shutdown.*,/sbin/halt,' ${rootfs_path}/etc/inittab -} - -configure_pld_systemd() -{ - unlink ${rootfs_path}/etc/systemd/system/default.target - chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/udev.service - chroot ${rootfs_path} ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target - - # Actually, the After=dev-%i.device line does not appear in the - # Fedora 17 or Fedora 18 systemd getty@.service file. It may be left - # over from an earlier version and it's not doing any harm. We do need - # to disable the "ConditionalPathExists=/dev/tty0" line or no gettys are - # started on the ttys in the container. Lets do it in an override copy of - # the service so it can still pass rpm verifies and not be automatically - # updated by a new systemd version. -- mhw /\/\|=mhw=|\/\/ - - sed -e 's/^ConditionPathExists=/# ConditionPathExists=/' \ - -e 's/After=dev-%i.device/After=/' \ - < ${rootfs_path}/lib/systemd/system/getty@.service \ - > ${rootfs_path}/etc/systemd/system/getty@.service - - # Setup getty service on the 4 ttys we are going to allow in the - # default config. Number should match lxc.tty.max - for i in 1 2 3 4; do - ln -sf ../getty@.service ${rootfs_path}/etc/systemd/system/getty.target.wants/getty@tty${i}.service - done -} - -download_pld() -{ - - # check the mini pld was not already downloaded - INSTALL_ROOT=$cache/partial - mkdir -p $INSTALL_ROOT - if [ $? -ne 0 ]; then - echo "Failed to create '$INSTALL_ROOT' directory" - return 1 - fi - - # download a mini pld into a cache - echo "Downloading PLD Linux minimal ..." - POLDEK="poldek --root $INSTALL_ROOT --noask --nohold --noignore" - PKG_LIST="basesystem filesystem pld-release rpm poldek vserver-packages rc-scripts pwdutils mingetty" - - mkdir -p $INSTALL_ROOT@LOCALSTATEDIR@/lib/rpm - rpm --root $INSTALL_ROOT --initdb - $POLDEK -u $PKG_LIST - - if [ $? -ne 0 ]; then - echo "Failed to download the rootfs, aborting." - return 1 - fi - - mv "$INSTALL_ROOT" "$cache/rootfs" - echo "Download complete." - - return 0 -} - -copy_pld() -{ - - # make a local copy of the minipld - echo -n "Copying rootfs to $rootfs_path ..." - cp -a $cache/rootfs/* $rootfs_path || return 1 - return 0 -} - -update_pld() -{ - POLDEK="poldek --root $cache/rootfs --noask" - $POLDEK --upgrade-dist -} - -install_pld() -{ - mkdir -p @LOCALSTATEDIR@/lock/subsys/ - ( - flock -x 9 - if [ $? -ne 0 ]; then - echo "Cache repository is busy." - return 1 - fi - - echo "Checking cache download in $cache/rootfs ... " - if [ ! -e "$cache/rootfs" ]; then - download_pld - if [ $? -ne 0 ]; then - echo "Failed to download 'pld base'" - return 1 - fi - else - echo "Cache found. Updating..." - update_pld - if [ $? -ne 0 ]; then - echo "Failed to update 'pld base', continuing with last known good cache" - else - echo "Update finished" - fi - fi - - echo "Copy $cache/rootfs to $rootfs_path ... " - copy_pld - if [ $? -ne 0 ]; then - echo "Failed to copy rootfs" - return 1 - fi - - return 0 - ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-pld - - return $? -} - -copy_configuration() -{ - - mkdir -p $config_path - grep -q "^lxc.rootfs.path" $config_path/config 2>/dev/null || echo "lxc.rootfs.path = $rootfs_path" >> $config_path/config - cat <> $config_path/config -# Most of below settings should be taken as defaults from -# lxc.include = /usr/share/lxc/config/common.conf -lxc.uts.name = $utsname -lxc.tty.max = 4 -lxc.pty.max = 1024 -# Consider if below line is right for systemd container -lxc.mount.fstab = $config_path/fstab -lxc.cap.drop = sys_module mac_admin mac_override sys_time - -lxc.autodev = $auto_dev - -# When using LXC with apparmor, uncomment the next line to run unconfined: -#lxc.apparmor.profile = unconfined - -## Devices -# Allow all devices -#lxc.cgroup.devices.allow = a -# Deny all devices -lxc.cgroup.devices.deny = a -# Allow to mknod all devices (but not using them) -lxc.cgroup.devices.allow = c *:* m -lxc.cgroup.devices.allow = b *:* m - -# /dev/null and zero -lxc.cgroup.devices.allow = c 1:3 rwm -lxc.cgroup.devices.allow = c 1:5 rwm -# consoles -lxc.cgroup.devices.allow = c 5:1 rwm -lxc.cgroup.devices.allow = c 5:0 rwm -lxc.cgroup.devices.allow = c 4:0 rwm -lxc.cgroup.devices.allow = c 4:1 rwm -# /dev/{,u}random -lxc.cgroup.devices.allow = c 1:9 rwm -lxc.cgroup.devices.allow = c 1:8 rwm -lxc.cgroup.devices.allow = c 136:* rwm -lxc.cgroup.devices.allow = c 5:2 rwm -# rtc -lxc.cgroup.devices.allow = c 254:0 rm -EOF - - cat < $config_path/fstab -proc proc proc nodev,noexec,nosuid 0 0 -sysfs sys sysfs defaults 0 0 -EOF - if [ $? -ne 0 ]; then - echo "Failed to add configuration" - return 1 - fi - - return 0 -} - -clean() -{ - - if [ ! -e $cache ]; then - exit 0 - fi - - # lock, so we won't purge while someone is creating a repository - ( - flock -x 9 - if [ $? != 0 ]; then - echo "Cache repository is busy." - exit 1 - fi - - echo -n "Purging the download cache for PLD Linux $release..." - rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1 - exit 0 - ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-pld -} - -usage() -{ - cat < - [-p|--path=] [-c|--clean] [-R|--release=] [--fqdn=] [-A|--arch=] - [-h|--help] -Mandatory args: - -n,--name container name, used to as an identifier for that container from now on -Optional args: - -p,--path path to where the container will be created, defaults to @LXCPATH@. The container config will go under @LXCPATH@ in that case - --rootfs path for actual rootfs. - -c,--clean clean the cache - -R,--release PLD Linux release for the new container. if the host is PLD Linux, then it will default to the host's release. - --fqdn fully qualified domain name (FQDN) for DNS and system naming - -A,--arch NOT USED YET. Define what arch the container will be [i686,x86_64] - -h,--help print this help -EOF - return 0 -} - -options=$(getopt -o hp:n:cR: -l help,path:,rootfs:,name:,clean,release:,fqdn: -- "$@") -if [ $? -ne 0 ]; then - usage $(basename $0) - exit 1 -fi -eval set -- "$options" - -while :; do - case "$1" in - -h|--help) usage $0 && exit 0;; - -p|--path) path=$2; shift 2;; - --rootfs) rootfs=$2; shift 2;; - -n|--name) name=$2; shift 2;; - -c|--clean) clean=$2; shift 2;; - -R|--release) release=$2; shift 2;; - --fqdn) utsname=$2; shift 2;; - --) shift 1; break ;; - *) break ;; - esac -done - -if [ ! -z "$clean" -a -z "$path" ]; then - clean || exit 1 - exit 0 -fi - -if [ -z "${utsname}" ]; then - utsname=${name} -fi - -# This follows a standard "resolver" convention that an FQDN must have -# at least two dots or it is considered a local relative host name. -# If it doesn't, append the dns domain name of the host system. -# -# This changes one significant behavior when running -# "lxc_create -n Container_Name" without using the -# --fqdn option. -# -# Old behavior: -# utsname and hostname = Container_Name -# New behavior: -# utsname and hostname = Container_Name.Domain_Name - -if [ $(expr "$utsname" : '.*\..*\.') = 0 ]; then - if [ -n "$(dnsdomainname)" ]; then - utsname=${utsname}.$(dnsdomainname) - fi -fi - -needed_pkgs="" -type poldek >/dev/null 2>&1 -if [ $? -ne 0 ]; then - needed_pkgs="poldek $needed_pkgs" -fi - -#type curl >/dev/null 2>&1 -#if [ $? -ne 0 ]; then -# needed_pkgs="curl $needed_pkgs" -#fi - -if [ -n "$needed_pkgs" ]; then - echo "Missing commands: $needed_pkgs" - echo "Please install these using \"sudo poldek -u $needed_pkgs\"" - exit 1 -fi - -if [ -z "$path" ]; then - path=$default_path/$name -fi - -if [ -z "$release" ]; then - if [ "$is_pld" -a "$pld_host_ver" ]; then - release=$pld_host_ver - else - echo "This is not a PLD Linux host and release missing, defaulting to 3.0. use -R|--release to specify release" - release=3.0 - fi -fi - -# pld th have systemd. We need autodev enabled to keep systemd from causing problems. -if [ $release = 3.0 ]; then - auto_dev="0" -else - auto_dev="0" -fi - -if [ "$(id -u)" != "0" ]; then - echo "This script should be run as 'root'" - exit 1 -fi - -if [ -z "$rootfs" ]; then - rootfs_path=$path/rootfs - # check for 'lxc.rootfs.path' passed in through default config by lxc-create - # TODO: should be lxc.rootfs.mount used instead? - if grep -q '^lxc.rootfs.path' $path/config 2>/dev/null ; then - rootfs_path=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $path/config) - fi -else - rootfs_path=$rootfs -fi -config_path=$default_path/$name -cache=$cache_base/$release - -revert() -{ - echo "Interrupted, so cleaning up" - lxc-destroy -n $name - # maybe was interrupted before copy config - rm -rf $path - rm -rf $default_path/$name - echo "exiting..." - exit 1 -} - -trap revert SIGHUP SIGINT SIGTERM - -copy_configuration -if [ $? -ne 0 ]; then - echo "Failed write configuration file" - exit 1 -fi - -install_pld -if [ $? -ne 0 ]; then - echo "Failed to install PLD Linux" - exit 1 -fi - -configure_pld -if [ $? -ne 0 ]; then - echo "Failed to configure PLD Linux for a container" - exit 1 -fi - -# If the systemd configuration directory exists - set it up for what we need. -if [ -d ${rootfs_path}/etc/systemd/system ]; then - configure_pld_systemd -fi - -# This configuration (rc.sysinit) is not inconsistent with the systemd stuff -# above and may actually coexist on some upgraded systems. Let's just make -# sure that, if it exists, we update this file, even if it's not used... -if [ -f ${rootfs_path}/etc/rc.sysinit ]; then - configure_pld_init -fi - -if [ ! -z $clean ]; then - clean || exit 1 - exit 0 -fi -echo "container rootfs and config created" diff --git a/templates/lxc-sabayon.in b/templates/lxc-sabayon.in deleted file mode 100644 index 51594c189..000000000 --- a/templates/lxc-sabayon.in +++ /dev/null @@ -1,513 +0,0 @@ -#!/bin/bash -# vim: set ts=4 sw=4 expandtab - -# Exit on error and treat unset variables as an error. -set -eu - -# -# LXC template for Sabayon OS, based of Alpine script. -# - -# Authors: -# Geaaru - -# 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 - - -#=========================== Constants ============================# - -# Make sure the usual locations are in PATH -export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin - -readonly LOCAL_STATE_DIR='@LOCALSTATEDIR@' -readonly LXC_TEMPLATE_CONFIG='@LXCTEMPLATECONFIG@' - - -# Temporary static MIRROR LIST. I will get list from online path on the near future. -readonly MIRRORS_LIST=" -http://mirror.it.sabayon.org/ -http://dl.sabayon.org/ -ftp://ftp.klid.dk/sabayonlinux/ -http://ftp.fsn.hu/pub/linux/distributions/sabayon/ -http://ftp.cc.uoc.gr/mirrors/linux/SabayonLinux/ -http://ftp.rnl.ist.utl.pt/pub/sabayon/ -ftp://ftp.nluug.nl/pub/os/Linux/distr/sabayonlinux/ -http://mirror.internode.on.net/pub/sabayon/ -http://mirror.yandex.ru/sabayon/ -http://sabayon.c3sl.ufpr.br/ -http://mirror.clarkson.edu/sabayon/ -http://na.mirror.garr.it/mirrors/sabayonlinux/" - -#======================== Global variables ========================# - -# Clean variables and set defaults. -arch="$(uname -m)" -debug='no' -flush_cache='no' -mirror_url= -name= -path= -release="DAILY" -rootfs= -unprivileged=false -mapped_uid= -mapped_gid= -flush_owner=false - -#======================== Helper Functions ========================# - -usage() { - cat <<-EOF -Template specific options can be passed to lxc-create after a '--' like this: - - lxc-create --name=NAME [lxc-create-options] -- [template-options] - -Template options: - -a ARCH, --arch=ARCH The container architecture (e.g. x86_64, armv7); defaults - to the host arch. - -d, --debug Run this script in a debug mode (set -x and wget w/o -q). - -m URL --mirror=URL The Sabayon mirror to use; defaults to random mirror. - -u, --unprivileged Tuning of rootfs for unprivileged containers. - -r, --release Identify release to use. Default is DAILY. - --mapped-gid Group Id to use on unprivileged container - (based of value present on file /etc/subgid). - --mapped-uid User Id to use on unprivileged container - (based of value present on file /etc/subuid) - --flush-owner Only for directly creation of unprivileged containers - through lxc-create command. Execute fuidshift command. - Require --mapped-gid,--mapped-uid and --unprivileged - options. - -Environment variables: - RELEASE Release version of Sabayon. Default is ${RELEASE}. -EOF -} - -random_mirror_url() { - local url="" - - if [ $arch == 'amd64' ] ; then - url=$(echo $MIRRORS_LIST | sed -e 's/ /\n/g' | sort -R --random-source=/dev/urandom | head -n 1) - else - if [ $arch == 'armv7l' ] ; then - # Currently armv7l tarball is not on sabayon mirrored tree. - url="https://dockerbuilder.sabayon.org/" - fi - fi - - [ -n "$url" ] && echo "$url" -} - -die() { - local retval=$1; shift - - echo -e "==> $@\n" - exit $retval -} - -einfo() { - echo -e "==> $@\n" -} - -fetch() { - if [ "$debug" = 'yes' ]; then - wget -T 10 -O - $@ - else - wget -T 10 -O - -q $@ - fi -} - -parse_arch() { - case "$1" in - x86_64 | amd64) echo 'amd64';; - armv7 | armv7l) echo 'armv7l';; - #arm*) echo 'armhf';; - *) return 1;; - esac -} - -run_exclusively() { - - local lock_name="$1" - local timeout=$2 - local method=$3 - shift 3 - - mkdir -p "$LOCAL_STATE_DIR/lock/subsys" - - local retval - { - echo -n "Obtaining an exclusive lock..." - if ! flock -x 9; then - echo ' failed.' - return 1 - fi - echo ' done' - - ${method} $@ - retval=$? - } 9> "$LOCAL_STATE_DIR/lock/subsys/lxc-sabayon-$lock_name" - - return $retval -} - -create_url () { - - local url="" - # Example of amd64 tarball url - # http://mirror.yandex.ru/sabayon/iso/daily/Sabayon_Linux_DAILY_amd64_tarball.tar.gz - - if [ $arch == 'amd64' ] ; then - - if [ $release = 'DAILY' ] ; then - url="${MIRROR_URL}iso/daily/Sabayon_Linux_DAILY_amd64_tarball.tar.gz" - else - url="${MIRROR_URL}iso/monthly/Sabayon_Linux_${release}_amd64_tarball.tar.gz" - fi - else - # https://dockerbuilder.sabayon.org/Sabayon_Linux_16_armv7l.tar.bz2 - if [ $arch == 'armv7l' ] ; then - - # Currently $arch tarball is not on sabayon mirrored tree. - url="${MIRROR_URL}Sabayon_Linux_16_armv7l.tar.bz2" - - fi - fi - - echo $url -} - - -#=========================== Configure ===========================# - -unprivileged_rootfs() { - - pushd ${rootfs}/etc/systemd/system - - # Disable systemd-journald-audit.socket because it seems that doesn't - # start correctly on unprivileged container - ln -s /dev/null systemd-journald-audit.socket - - # Disable systemd-remount-fs.service because on unprivileged container - # systemd can't remount filesystem - ln -s /dev/null systemd-remount-fs.service - - # Remove mount of FUSE Control File system - ln -s /dev/null sys-fs-fuse-connections.mount - - # Change execution of service systemd-sysctl to avoid errors. - mkdir systemd-sysctl.service.d - cat < systemd-sysctl.service.d/00gentoo.conf -[Service] -ExecStart= -ExecStart=/usr/lib/systemd/systemd-sysctl --prefix=/etc/sysctl.d/ -EOF - - # Disable mount of hugepages - ln -s /dev/null dev-hugepages.mount - - popd - - pushd ${rootfs} - - # Disable sabayon-anti-fork-bomb limits (already apply to lxc container manager) - sed -i -e 's/^*/#*/g' ./etc/security/limits.d/00-sabayon-anti-fork-bomb.conf || return 1 - sed -i -e 's/^root/#root/g' ./etc/security/limits.d/00-sabayon-anti-fork-bomb.conf || return 1 - - popd - - return 0 -} - -unprivileged_shift_owner () { - - # I use /usr/bin/fuidshift from LXD project. - - einfo "Executing: fuidshift ${rootfs} u:0:${mapped_uid}:65536 g:0:${mapped_gid}:65536 ..." - - fuidshift ${rootfs} u:0:${mapped_uid}:65536 g:0:${mapped_gid}:65536 || - die 1 "Error on change owners of ${rootfs} directory" - - einfo "Done." - - # Fix permission of container directory - chmod a+rx ${path} - - return 0 -} - -systemd_container_tuning () { - - # To avoid error on start systemd-tmpfiles-setup service - # it is needed clean journal directory - rm -rf ${rootfs}/var/log/journal/ - - # Remove LVM service. Normally not needed on container system. - rm -rf ${rootfs}/etc/systemd/system/sysinit.target.wants/lvm2-lvmetad.service - - # Comment unneeded entry on /etc/fstab - sed -e 's/\/dev/#\/dev/g' -i ${rootfs}/etc/fstab - - # Fix this stupid error until fix is available on sabayon image - # /usr/lib/systemd/system-generators/gentoo-local-generator: line 4: cd: /etc/local.d: No such file or directory - mkdir ${rootfs}/etc/local.d/ - - mkdir ${rootfs}/etc/systemd/system/NetworkManager.service.d/ - cat < ${rootfs}/etc/systemd/system/NetworkManager.service.d/override.conf -[Service] -ExecStartPre=-/bin/ip -4 link set dev eth0 down -EOF - chmod 644 ${rootfs}/etc/systemd/system/NetworkManager.service.d/override.conf - - return 0 -} - -configure_container() { - local config="$1" - local hostname="$2" - local arch="$3" - local privileged_options="" - local unprivileged_options="" - - if [[ $unprivileged && $unprivileged == true ]] ; then - if [[ $flush_owner == true ]] ; then - unprivileged_options=" -lxc.idmap = u 0 ${mapped_uid} 65536 -lxc.idmap = g 0 ${mapped_gid} 65536 -" - fi - - unprivileged_options=" -$unprivileged_options - -# Force use of cgroup v1. Currently systemd doesn't support -# correctly cgroup v2. See: https://github.com/lxc/lxc/issues/1669 -# about discussion of default-hierarchy option. -lxc.init.cmd = /sbin/init systemd.legacy_systemd_cgroup_controller=yes - -# Include common configuration. -lxc.include = $LXC_TEMPLATE_CONFIG/sabayon.userns.conf -" - - else - privileged_options=" -## Allow any mknod (but not reading/writing the node) -lxc.cgroup.devices.allow = b *:* m -lxc.cgroup.devices.allow = c *:* m - -### /dev/pts/* -lxc.cgroup.devices.allow = c 136:* rwm -### /dev/tty -lxc.cgroup.devices.allow = c 5:0 rwm -### /dev/console -lxc.cgroup.devices.allow = c 5:1 rwm -### /dev/ptmx -lxc.cgroup.devices.allow = c 5:2 rwm -### fuse -lxc.cgroup.devices.allow = c 10:229 rwm - -" - fi - - cat <<-EOF >> "$config" -# Specify container architecture. -lxc.arch = $arch - -# Set hostname. -lxc.uts.name = $hostname - -# Include common configuration. -lxc.include = $LXC_TEMPLATE_CONFIG/sabayon.common.conf - -$unprivileged_options -$privileged_options -EOF -} - - -#============================= Main ==============================# - -parse_cmdline() { - - # Parse command options. - local short_options="a:dm:n:p:r:hu" - local long_options="arch:,debug,mirror:,name:,path:,release:,rootfs:,mapped-uid:,mapped-gid:,flush-owner,help" - - options=$(getopt -u -q -a -o "$short_options" -l "$long_options" -- "$@") - - eval set -- "$options" - - # Process command options. - while [ $# -gt 0 ]; do - case $1 in - -a | --arch) - arch=$2 - shift - ;; - -d | --debug) - debug='yes' - ;; - -m | --mirror) - mirror_url=$2 - shift - ;; - -n | --name) - name=$2 - shift - ;; - -p | --path) - path=$2 - shift - ;; - -r | --release) - release=$2 - shift - ;; - --rootfs) - rootfs=$2 - shift - ;; - -u | --unprivileged) - unprivileged=true - ;; - -h | --help) - usage - exit 1 - ;; - --mapped-uid) - mapped_uid=$2 - shift - ;; - --mapped-gid) - mapped_gid=$2 - shift - ;; - --flush-owner) - flush_owner=true - ;; - --) - break - ;; - *) - einfo "Unknown option: $1" - usage - exit 1 - ;; - esac - shift - done - - if [ "$(id -u)" != "0" ]; then - die 1 "This script must be run as 'root'" - fi - - # Validate options. - [ -n "$name" ] || die 1 'Missing required option --name' - [ -n "$path" ] || die 1 'Missing required option --path' - - if [ -z "$rootfs" ] && [ -f "$path/config" ]; then - rootfs="$(sed -nE 's/^lxc.rootfs\s*=\s*(.*)$/\1/p' "$path/config")" - fi - if [ -z "$rootfs" ]; then - rootfs="$path/rootfs" - fi - - [ -z "$path" ] && die 1 "'path' parameter is required." - - arch=$(parse_arch "$arch") \ - || die 1 "Unsupported architecture: $arch" - - [[ $unprivileged == true && $flush_owner == true &&-z "$mapped_uid" ]] && \ - die 1 'Missing required option --mapped-uid with --unprivileged option' - - [[ $unprivileged == true && $flush_owner == true && -z "$mapped_gid" ]] && \ - die 1 'Missing required option --mapped-gid with --unprivileged option' - - [[ $flush_owner == true && $unprivileged == false ]] && \ - die 1 'flush-owner require --unprivileged option' - - return 0 -} - -main () { - - local tarball="" - - # Set global variables. - RELEASE="${RELEASE:-"DAILY"}" - ARCH="${ARCH:-`uname -m`}" - OS="${OS:-"sabayon"}" - - einfo "Processing command line arguments: $@" - - # Parse command line options - parse_cmdline "$@" - - DEBUG="$debug" - MIRROR_URL="${mirror_url:-$(random_mirror_url)}" - - einfo "Use arch = $arch, mirror_url = $MIRROR_URL, path = $path, name = $name, release = $release, unprivileged = $unprivileged, rootfs = $rootfs, mapped_uid = $mapped_uid, mapped_gid = $mapped_gid, flush_owner = $flush_owner" - - [ "$debug" = 'yes' ] && set -x - - # Download sabayon tarball - tarball=$(create_url) - einfo "Fetching tarball $tarball..." - - # TODO: use only a compression mode - if [ $arch == 'amd64' ] ; then - fetch "${tarball}" | tar -xpz -C "${rootfs}" - else - if [ $arch == 'armv7l' ] ; then - fetch "${tarball}" | tar -xpj -C "${rootfs}" - fi - fi - - einfo "Tarball ${tarball} Extracted." - - systemd_container_tuning - - # Fix container for unprivileged mode. - if [[ $unprivileged == true ]] ; then - unprivileged_rootfs - if [[ $flush_owner == true ]] ; then - unprivileged_shift_owner - fi - fi - - return 0 -} - - -einfo "Prepare creation of sabayon container with params: $@ ($#)" - -# Here we go! -run_exclusively 'main' 10 main "$@" -configure_container "$path/config" "$name" "$arch" - -einfo "Container's rootfs and config have been created" -cat <<-EOF - Edit the config file $path/config to check/enable networking setup. - The installed system is preconfigured for a loopback and single network - interface configured via DHCP. - - To start the container, run "lxc-start -n $name". - The root password is not set; to enter the container run "lxc-attach -n $name". - - Note: From kenel >= 4.6 for use unprivileged containers it is needed this mount on host: - - mkdir /sys/fs/cgroup/systemd - mount -t cgroup -o none,name=systemd systemd /sys/fs/cgroup/systemd -EOF diff --git a/templates/lxc-slackware.in b/templates/lxc-slackware.in deleted file mode 100644 index 0c85c5103..000000000 --- a/templates/lxc-slackware.in +++ /dev/null @@ -1,793 +0,0 @@ -#!/bin/bash - -# -# lxc: linux Container library - -# Authors: -# Daniel Lezcano - -# Template for slackware by Matteo Bernardini -# some parts are taken from the debian one (used as model) - -# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 - -# Add some directories to PATH in case we create containers with sudo -export PATH=/sbin:/usr/sbin:$PATH - -cache=${cache:-/var/cache/lxc/slackware} - -# Use the primary Slackware site by default, but please consider changing -# this to a closer mirror site. -MIRROR=${MIRROR:-http://ftp.slackware.com/pub/slackware} - -if [ -z "$arch" ]; then -case "$( uname -m )" in - i?86) arch=i486 ;; - arm*) arch=arm ;; - *) arch=$( uname -m ) ;; -esac -fi - -LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@" - -configure_slackware() -{ -rootfs=$1 -hostname=$2 - -echo "Configuring..." ; echo - -# The next part contains excerpts taken from SeTconfig (written by -# Patrick Volkerding) from the slackware setup disk. -# But before pasting them just set a variable to use them as they are -T_PX=$rootfs - -( cd $T_PX ; chmod 755 ./ ) -( cd $T_PX ; chmod 755 ./var ) -if [ -d $T_PX/usr/src/linux ]; then - chmod 755 $T_PX/usr/src/linux -fi -if [ ! -d $T_PX/proc ]; then - mkdir $T_PX/proc - chown root.root $T_PX/proc -fi -if [ ! -d $T_PX/sys ]; then - mkdir $T_PX/sys - chown root.root $T_PX/sys -fi -chmod 1777 $T_PX/tmp -if [ ! -d $T_PX/var/spool/mail ]; then - mkdir -p $T_PX/var/spool/mail - chmod 755 $T_PX/var/spool - chown root.mail $T_PX/var/spool/mail - chmod 1777 $T_PX/var/spool/mail -fi - -echo "#!/bin/sh" > $T_PX/etc/rc.d/rc.keymap -echo "# Load the keyboard map. More maps are in /usr/share/kbd/keymaps." \ - >> $T_PX/etc/rc.d/rc.keymap -echo "if [ -x /usr/bin/loadkeys ]; then" >> $T_PX/etc/rc.d/rc.keymap -echo " /usr/bin/loadkeys us" >> $T_PX/etc/rc.d/rc.keymap -echo "fi" >> $T_PX/etc/rc.d/rc.keymap -chmod 755 $T_PX/etc/rc.d/rc.keymap - -# Network configuration is left to the user, that have to edit -# /etc/rc.d/rc.inet1.conf and /etc/resolv.conf of the container -# just set the hostname -cat < $rootfs/etc/HOSTNAME -$hostname.example.net -EOF -cp $rootfs/etc/HOSTNAME $rootfs/etc/hostname - -# make needed devices, from Chris Willing's MAKEDEV.sh -# http://www.vislab.uq.edu.au/howto/lxc/MAKEDEV.sh -DEV=$rootfs/dev -mkdir -p ${DEV} -mknod -m 666 ${DEV}/null c 1 3 -mknod -m 666 ${DEV}/zero c 1 5 -mknod -m 666 ${DEV}/random c 1 8 -mknod -m 666 ${DEV}/urandom c 1 9 -mkdir -m 755 ${DEV}/pts -mkdir -m 1777 ${DEV}/shm -mknod -m 666 ${DEV}/tty c 5 0 -mknod -m 600 ${DEV}/console c 5 1 -mknod -m 666 ${DEV}/tty0 c 4 0 -mknod -m 666 ${DEV}/tty1 c 4 1 -mknod -m 666 ${DEV}/tty2 c 4 2 -mknod -m 666 ${DEV}/tty3 c 4 3 -mknod -m 666 ${DEV}/tty4 c 4 4 -mknod -m 666 ${DEV}/tty5 c 4 5 -mknod -m 666 ${DEV}/full c 1 7 -mknod -m 600 ${DEV}/initctl p -mknod -m 660 ${DEV}/loop0 b 7 0 -mknod -m 660 ${DEV}/loop1 b 7 1 -ln -s pts/ptmx ${DEV}/ptmx -ln -s /proc/self/fd ${DEV}/fd - -echo "Adding an etc/fstab" -cat >$rootfs/etc/fstab <$rootfs/tmp/rcs.patch <<'EOF' ---- ./etc/rc.orig/rc.6 2012-08-15 01:03:12.000000000 +0200 -+++ ./etc/rc.d/rc.6 2013-02-17 10:26:30.888839354 +0100 -@@ -9,6 +9,12 @@ - # Author: Miquel van Smoorenburg - # Modified by: Patrick J. Volkerding, - # -+# minor tweaks for an lxc container -+# by Matteo Bernardini , -+# based also on Chris Willing's modifications -+# http://www.vislab.uq.edu.au/howto/lxc/rc.6 -+# a check for a container variable is made to jump sections -+container="lxc" - - # Set the path. - PATH=/sbin:/etc:/bin:/usr/bin -@@ -37,6 +43,9 @@ - ;; - esac - -+# lxc container check -+if [ ! $container = "lxc" ]; then -+ - # Save the system time to the hardware clock using hwclock --systohc. - if [ -x /sbin/hwclock ]; then - # Check for a broken motherboard RTC clock (where ioports for rtc are -@@ -53,6 +62,8 @@ - fi - fi - -+fi # end container check -+ - # Run any local shutdown scripts: - if [ -x /etc/rc.d/rc.local_shutdown ]; then - /etc/rc.d/rc.local_shutdown stop -@@ -148,6 +159,9 @@ - sleep 2 - fi - -+# lxc container check -+if [ ! $container = "lxc" ]; then -+ - # Shut down PCMCIA devices: - if [ -x /etc/rc.d/rc.pcmcia ]; then - . /etc/rc.d/rc.pcmcia stop -@@ -155,11 +169,16 @@ - /bin/sleep 5 - fi - -+fi # end container check -+ - # Turn off process accounting: - if [ -x /sbin/accton -a -r /var/log/pacct ]; then - /sbin/accton off - fi - -+# lxc container check -+if [ ! $container = "lxc" ]; then -+ - # Terminate acpid before syslog: - if [ -x /etc/rc.d/rc.acpid -a -r /var/run/acpid.pid ]; then # quit - . /etc/rc.d/rc.acpid stop -@@ -170,6 +189,8 @@ - sh /etc/rc.d/rc.udev force-stop - fi - -+fi # end container check -+ - # Kill all remaining processes. - if [ ! "$1" = "fast" ]; then - echo "Sending all processes the SIGTERM signal." -@@ -179,6 +200,9 @@ - /sbin/killall5 -9 - fi - -+# lxc container check -+if [ ! $container = "lxc" ]; then -+ - # Try to turn off quota. - if /bin/grep -q quota /etc/fstab ; then - if [ -x /sbin/quotaoff ]; then -@@ -187,6 +211,8 @@ - fi - fi - -+fi # end container check -+ - # Carry a random seed between reboots. - echo "Saving random seed from /dev/urandom in /etc/random-seed." - # Use the pool size from /proc, or 512 bytes: -@@ -205,6 +231,9 @@ - rm -f /var/lock/subsys/* - fi - -+# lxc container check -+if [ ! $container = "lxc" ]; then -+ - # Turn off swap: - echo "Turning off swap." - /sbin/swapoff -a -@@ -216,6 +245,8 @@ - echo "Remounting root filesystem read-only." - /bin/mount -v -n -o remount,ro / - -+fi # end container check -+ - # This never hurts: - /bin/sync - -@@ -240,12 +271,17 @@ - done - fi - -+# lxc container check -+if [ ! $container = "lxc" ]; then -+ - # Deactivate LVM volume groups: - if [ -r /etc/lvmtab -o -d /etc/lvm/backup ]; then - echo "Deactivating LVM volume groups:" - /sbin/vgchange -an --ignorelockingfailure - fi - -+fi # end container check -+ - # This never hurts again (especially since root-on-LVM always fails - # to deactivate the / logical volume... but at least it was - # remounted as read-only first) -@@ -258,6 +294,9 @@ - # This is to ensure all processes have completed on SMP machines: - wait - -+# lxc container check -+if [ ! $container = "lxc" ]; then -+ - if [ -x /sbin/genpowerd ]; then - # See if this is a powerfail situation: - if /bin/egrep -q "FAIL|SCRAM" /etc/upsstatus 2> /dev/null ; then -@@ -274,6 +313,13 @@ - fi - fi - -+else -+ -+# confirm successful shutdown of the container -+echo ; echo "* container stopped. *" ; echo -+ -+fi # end container check -+ - # Now halt (poweroff with APM or ACPI enabled kernels) or reboot. - if [ "$command" = "reboot" ]; then - echo "Rebooting." ---- ./etc/rc.orig/rc.S 2012-09-13 21:38:34.000000000 +0200 -+++ ./etc/rc.d/rc.S 2013-02-17 09:39:41.579799641 +0100 -@@ -4,9 +4,18 @@ - # - # Mostly written by: Patrick J. Volkerding, - # -+# minor tweaks for an lxc container -+# by Matteo Bernardini , -+# based also on Chris Willing's modifications -+# http://www.vislab.uq.edu.au/howto/lxc/rc.S -+# a check for a container variable is made to jump sections -+container="lxc" - - PATH=/sbin:/usr/sbin:/bin:/usr/bin - -+# lxc container check -+if [ ! $container = "lxc" ]; then -+ - # Try to mount /proc: - /sbin/mount -v proc /proc -n -t proc 2> /dev/null - -@@ -254,10 +263,27 @@ - read junk; - fi # Done checking root filesystem - -+else -+ # We really don't want to start udev in the container -+ if [ -f /etc/rc.d/rc.udev ]; then -+ chmod -x /etc/rc.d/rc.udev -+ fi -+ # Alsa won't work -+ if [ -f /etc/rc.d/rc.alsa ]; then -+ chmod -x /etc/rc.d/rc.alsa -+ fi -+ # This too -+ if [ -f /etc/rc.d/rc.loop ]; then -+ chmod -x /etc/rc.d/rc.loop -+ fi -+fi # end container check - - # Any /etc/mtab that exists here is old, so we start with a new one: - /bin/rm -f /etc/mtab{,~,.tmp} && /bin/touch /etc/mtab - -+# lxc container check -+if [ ! $container = "lxc" ]; then -+ - # Add entry for / to /etc/mtab: - /sbin/mount -f -w / - -@@ -337,6 +363,8 @@ - # mounted read-write. - /sbin/swapon -a 2> /dev/null - -+fi # end container check -+ - # Clean up some temporary files: - rm -f /var/run/* /var/run/*/* /var/run/*/*/* /etc/nologin \ - /etc/dhcpc/*.pid /etc/forcefsck /etc/fastboot \ -@@ -364,7 +392,7 @@ - # if the first line of that file begins with the word 'Linux'. - # You are free to modify the rest of the file as you see fit. - if [ -x /bin/sed ]; then -- /bin/sed -i "{1s/^Linux.*/$(/bin/uname -sr)\./}" /etc/motd -+ /bin/sed -i "{1s/^Linux.*/$(/bin/uname -sr) lxc container\./}" /etc/motd - fi - - # If there are SystemV init scripts for this runlevel, run them. -@@ -372,6 +400,9 @@ - . /etc/rc.d/rc.sysvinit - fi - -+# lxc container check -+if [ ! $container = "lxc" ]; then -+ - # Run serial port setup script: - # CAREFUL! This can make some systems hang if the rc.serial script isn't - # set up correctly. If this happens, you may have to edit the file from a -@@ -380,6 +411,8 @@ - sh /etc/rc.d/rc.serial start - fi - -+fi # end container check -+ - # Carry an entropy pool between reboots to improve randomness. - if [ -f /etc/random-seed ]; then - echo "Using /etc/random-seed to initialize /dev/urandom." ---- ./etc/rc.orig/rc.M 2012-09-25 19:47:07.000000000 +0200 -+++ ./etc/rc.d/rc.M 2013-02-17 09:39:41.579799641 +0100 -@@ -10,6 +10,10 @@ - # Author: Fred N. van Kempen, - # Heavily modified by Patrick Volkerding - # -+# minor tweaks for an lxc container -+# by Matteo Bernardini : -+# a check for a container variable is made to jump sections -+container="lxc" - - # Tell the viewers what's going to happen. - echo "Going multiuser..." -@@ -20,6 +24,9 @@ - /sbin/ldconfig & - fi - -+# lxc container check -+if [ ! $container = "lxc" ]; then -+ - # Screen blanks after 15 minutes idle time, and powers down in one hour - # if the kernel supports APM or ACPI power management: - /bin/setterm -blank 15 -powersave powerdown -powerdown 60 -@@ -33,6 +40,8 @@ - /bin/hostname darkstar - fi - -+fi # end container check -+ - # Set the permissions on /var/log/dmesg according to whether the kernel - # permits non-root users to access kernel dmesg information: - if [ -r /proc/sys/kernel/dmesg_restrict ]; then -@@ -135,6 +144,9 @@ - chmod 755 / 2> /dev/null - chmod 1777 /tmp /var/tmp - -+# lxc container check -+if [ ! $container = "lxc" ]; then -+ - # Start APM or ACPI daemon. - # If APM is enabled in the kernel, start apmd: - if [ -e /proc/apm ]; then -@@ -146,6 +158,8 @@ - . /etc/rc.d/rc.acpid start - fi - -+fi # end container check -+ - # Update any existing icon cache files: - if find /usr/share/icons 2> /dev/null | grep -q icon-theme.cache ; then - for theme_dir in /usr/share/icons/* ; do ---- ./etc/rc.orig/rc.inet1 2012-08-05 19:13:27.000000000 +0200 -+++ ./etc/rc.d/rc.inet1 2013-02-17 09:39:41.579799641 +0100 -@@ -3,6 +3,11 @@ - # This script is used to bring up the various network interfaces. - # - # @(#)/etc/rc.d/rc.inet1 10.2 Sun Jul 24 12:45:56 PDT 2005 (pjv) -+# -+# minor tweaks for an lxc container -+# by Matteo Bernardini : -+# a check for a container variable is made to jump sections -+container="lxc" - - ############################ - # READ NETWORK CONFIG FILE # -@@ -105,6 +110,10 @@ - [ "${IFNAME[$i]}" = "${1}" ] && break - i=$(($i+1)) - done -+ -+ # lxc container check -+ if [ ! $container = "lxc" ]; then -+ - # If the interface is a bridge, then create it first: - [ -n "${BRNICS[$i]}" ] && br_open $i - # If the interface isn't in the kernel yet (but there's an alias for it in -@@ -115,6 +124,9 @@ - /sbin/modprobe ${1} - fi - fi -+ -+ fi # end container check -+ - if grep `echo ${1}: | cut -f 1 -d :`: /proc/net/dev 1> /dev/null ; then # interface exists - if ! /sbin/ifconfig | grep -w "${1}" 1>/dev/null || \ - ! /sbin/ifconfig ${1} | grep -w inet 1> /dev/null ; then # interface not up or not configured -EOF -( cd $rootfs ; patch -p1 < tmp/rcs.patch ; rm tmp/rcs.patch ) - -# restart rc.inet1 to have routing for the loop device -echo "/etc/rc.d/rc.inet1 restart" >> $rootfs/etc/rc.d/rc.local - -# reduce the number of local consoles: two should be enough -sed -i '/^c3\|^c4\|^c5\|^c6/s/^/# /' $rootfs/etc/inittab - -# better not use this in a container -sed -i 's/.*genpowerfail.*//' $rootfs/etc/inittab - -# add a message to rc.local that confirms successful container startup -echo "echo ; echo \"* container $name started. *\" ; echo" >> $rootfs/etc/rc.d/rc.local - -# borrow the time configuration from the local machine -cp -a /etc/localtime $rootfs/etc/localtime - -return 0 -} - -copy_slackware() -{ -rootfs=$1 - -# make a local copy of the installed filesystem -echo -n "Copying rootfs to $rootfs..." -mkdir -p $rootfs -cp -a $cache/rootfs-$release-$arch/* $rootfs/ || exit 1 - -# fix fstab with the actual path -sed -i "s|$cache/rootfs-$release-$arch|$rootfs|" $rootfs/etc/fstab - -return 0 -} - -install_slackware() -{ -rootfs=$1 -mkdir -p /var/lock/subsys/ -( -flock -n -x 9 -if [ $? -ne 0 ]; then - echo "Cache repository is busy." - return 1 -fi - -if [ "$arch" == "x86_64" ]; then - PKGMAIN=slackware64 -elif [ "$arch" == "arm" ]; then - PKGMAIN=slackwarearm -else - PKGMAIN=slackware -fi - -export CONF=$cache/slackpkg-conf -export ROOT=$cache/rootfs-$release-$arch - -mkdir -p $cache/cache-$release-$arch $cache/rootfs-$release-$arch \ - $cache/slackpkg-$release-$arch $CONF/templates - -echo "$MIRROR/$PKGMAIN-$release/" > $CONF/mirrors -touch $CONF/blacklist - -cat < $CONF/slackpkg.conf -# v2.8 -ARCH=$arch -TEMP=$cache/cache-$release-$arch -WORKDIR=$cache/slackpkg-$release-$arch -DELALL=off -CHECKMD5=on -CHECKGPG=on -CHECKSIZE=off -PRIORITY=( patches %PKGMAIN extra pasture testing ) -POSTINST=on -ONLY_NEW_DOTNEW=off -ONOFF=on -DOWNLOAD_ALL=on -DIALOG=off -BATCH=on -DEFAULT_ANSWER=y -USE_INCLUDES=on -SPINNING=off -EOF - -# thanks to Vincent Batts for this list of packages -# (that I modified a little :P) -# http://connie.slackware.com/~vbatts/minimal/ -cat < $CONF/templates/minimal-lxc.template -aaa_base -aaa_elflibs -aaa_terminfo -bash -bin -bzip2 -coreutils -dhcpcd -dialog -diffutils -e2fsprogs -elvis -etc -findutils -gawk -glibc-solibs -gnupg -grep -gzip -hostname -iputils -libunistring -logrotate -mpfr -net-tools -network-scripts -ncurses -openssh -openssl-solibs -pkgtools -procps-ng -sed -shadow -sharutils -slackpkg -sysklogd -sysvinit -sysvinit-functions -sysvinit-scripts -tar -udev -util-linux -wget -which -xz -EOF - -TEMPLATE=${TEMPLATE:-minimal-lxc} -if [ ! "$TEMPLATE" = "minimal-lxc" ]; then - if [ -f /etc/slackpkg/templates/$TEMPLATE.template ]; then - cat /etc/slackpkg/templates/$TEMPLATE.template \ - > $CONF/templates/$TEMPLATE.template - else - TEMPLATE="minimal-lxc" - fi -fi - -# clean previous installs -rm -fR $ROOT/* - -slackpkg -default_answer=n update -slackpkg install-template $TEMPLATE - -# add a slackpkg default mirror -echo "$MIRROR/$PKGMAIN-$release/" >> $ROOT/etc/slackpkg/mirrors - -# blacklist the devs package (we have to use our premade devices). -# do the same with the kernel packages (we use the host's one), -# but leave available headers and sources -echo "devs" >> $ROOT/etc/slackpkg/blacklist -sed -i \ - -e "s|^#kernel-|kernel-|" \ - -e "s|^kernel-headers|#kernel-headers|" \ - -e "s|^kernel-source|#kernel-source|" \ - $ROOT/etc/slackpkg/blacklist - -# force klog to use the system call interface to the kernel message -# buffers - needed for unprivileged containers -sed -i 's|3\ \-x|3 -x -s|' $ROOT/etc/rc.d/rc.syslog || true - -return 0 - -) 9>/var/lock/subsys/lxc - -return $? -} - -copy_configuration() -{ -path=$1 -rootfs=$2 -name=$3 - -cat <> $path/config - -lxc.uts.name = $name -lxc.arch = $arch - -lxc.mount.fstab = $rootfs/etc/fstab - -lxc.include = ${LXC_TEMPLATE_CONFIG}/slackware.common.conf -EOF - -if [ $? -ne 0 ]; then - echo "Failed to add configuration." - return 1 -fi - -return 0 -} - -clean() -{ -if [ ! -e $cache ]; then - exit 0 -fi - -# lock, so we won't purge while someone is creating a repository -( -flock -n -x 9 -if [ $? != 0 ]; then - echo "Cache repository is busy." - exit 1 -fi - -echo -n "Purging the download cache..." -rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1 -exit 0 - -) 9>/var/lock/subsys/lxc -} - -usage() -{ -cat < --clean -EOF -return 0 -} - -options=$(getopt -o hp:n:a:r:c -l help,rootfs:,path:,name:,arch:,release:,clean -- "$@") -if [ $? -ne 0 ]; then - usage $(basename $0) - exit 1 -fi -eval set -- "$options" - -while true -do -case "$1" in - -h|--help) usage $0 && exit 0;; - -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 2;; - --) shift 1; break ;; - *) break ;; -esac -done - -if [ ! -z "$clean" -a -z "$path" ]; then - clean || exit 1 - exit 0 -fi - -type installpkg -if [ $? -ne 0 ]; then - echo "'installpkg' command is missing." - exit 1 -fi - -type slackpkg -if [ $? -ne 0 ]; then - echo "'slackpkg' command is missing." - exit 1 -fi - -if [ -z "$path" ]; then - echo "'path' parameter is required." - exit 1 -fi - -if [ "$(id -u)" != "0" ]; then - echo "This script should be run as 'root'." - exit 1 -fi - -# If no release version was specified, use current -release=${release:-current} - -if [ -z "$name" ]; then - # no name given? set a default one - name=slackwarecontainer -fi - -# detect rootfs -config="$path/config" -if [ -z "$rootfs" ]; then - if grep -q '^lxc.rootfs.path' $config 2>/dev/null ; then - rootfs=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $config) - else - rootfs=$path/rootfs - fi -fi - -echo - -set -e - -install_slackware $rootfs -if [ $? -ne 0 ]; then - echo "Failed to install slackware." - exit 1 -fi - -echo - -configure_slackware $cache/rootfs-$release-$arch $name -if [ $? -ne 0 ]; then - echo "Failed to configure slackware for a container." - exit 1 -fi - -echo - -rootfs=$path/rootfs -copy_slackware $rootfs -if [ $? -ne 0 ]; then - echo "Failed to copy rootfs." - exit 1 -fi - -echo - -copy_configuration $path $rootfs $name -if [ $? -ne 0 ]; then - echo "Failed to write configuration file." - exit 1 -fi - -if [ ! -z $clean ]; then - clean || exit 1 - exit 0 -fi diff --git a/templates/lxc-sparclinux.in b/templates/lxc-sparclinux.in deleted file mode 100644 index e5e686f8e..000000000 --- a/templates/lxc-sparclinux.in +++ /dev/null @@ -1,702 +0,0 @@ -#!/bin/sh -# -# Template script for generating Linux for SPARC for LXC -# based on lxc-fedora, lxc-ubuntu -# -# Copyright © 2011 Wim Coekaerts -# Copyright © 2012 Dwight Engen -# Copyright � 2015 Wim Coekaerts -# -# Modified for Oracle Linux 5 -# Wim Coekaerts -# -# Modified for Oracle Linux 6,7 combined OL4,5,6 into one template script -# Dwight Engen -# -# Modified for Linux for SPARC 1.0 -# Wim Coekaerts -# -# 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 -# - -# 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 - -die() -{ - echo "failed: $1" - exit 1 -} - -is_btrfs_subvolume() -{ - if which btrfs >/dev/null 2>&1 && \ - btrfs subvolume list "$1" >/dev/null 2>&1; then - return 0 - fi - return 1 -} - -can_chcon() -{ - if which chcon >/dev/null 2>&1; then - selinuxenabled >/dev/null 2>&1 - return $? - fi - return 1 -} - -# fix up the container_rootfs -container_rootfs_patch() -{ - echo "Patching container rootfs $container_rootfs for Linux for SPARC $container_release_major.$container_release_minor" - - # copy ourself into the container to be used to --patch the rootfs when - # yum update on certain packages is done. we do this here instead of in - # container_rootfs_configure() in case the patching done in this function - # is updated in the future, we can inject the updated version of ourself - # into older containers. - if [ $container_rootfs != "/" ]; then - cp -f `readlink -f $0` $container_rootfs/usr/bin/lxc-patch - mkdir -p $container_rootfs/usr/share/yum-plugins - cp @DATADIR@/lxc/lxc-patch.py $container_rootfs/usr/share/yum-plugins - mkdir -p $container_rootfs/etc/yum/pluginconf.d - cat < $container_rootfs/etc/yum/pluginconf.d/lxc-patch.conf -[main] -enabled=1 -packages=dbus,initscripts,iptables,openssh-server,setup,selinux-policy,readahead,udev,util-linux,util-linux-ng -EOF - fi - - # "disable" selinux in the guest. The policy in the container isn't - # likely to match the hosts (unless host == guest exactly) and the - # kernel can only be enforcing one policy. - # - mkdir -p $container_rootfs/selinux - echo 0 > $container_rootfs/selinux/enforce - if [ -e $container_rootfs/etc/selinux/config ]; then - sed -i 's|SELINUX=enforcing|SELINUX=disabled|' $container_rootfs/etc/selinux/config - else - mkdir -p $container_rootfs/etc/selinux - echo "SELINUX=disabled" >$container_rootfs/etc/selinux/config - fi - sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*close|#session required pam_selinux.so close|' $container_rootfs/etc/pam.d/login - sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*open|#session required pam_selinux.so open|' $container_rootfs/etc/pam.d/login - sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*close|#session required pam_selinux.so close|' $container_rootfs/etc/pam.d/sshd - sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*open|#session required pam_selinux.so open|' $container_rootfs/etc/pam.d/sshd - - # setting /proc/$$/loginuid doesn't work under user namespace, which - # prevents logins from working - sed -i 's|session[ \t]*required[ \t]*pam_loginuid.so|#session required pam_loginuid.so|' $container_rootfs/etc/pam.d/sshd - sed -i 's|session[ \t]*required[ \t]*pam_loginuid.so|#session required pam_loginuid.so|' $container_rootfs/etc/pam.d/login - - if [ -f $container_rootfs/usr/sbin/selinuxenabled ]; then - mv $container_rootfs/usr/sbin/selinuxenabled $container_rootfs/usr/sbin/selinuxenabled.lxcorig - ln -s /bin/false $container_rootfs/usr/sbin/selinuxenabled - fi - - # ensure /dev/ptmx refers to the newinstance devpts of the container, or - # pty's will get crossed up with the hosts (https://lkml.org/lkml/2012/1/23/512) - rm -f $container_rootfs/dev/ptmx - ln -s pts/ptmx $container_rootfs/dev/ptmx - - # silence error in checking for selinux - sed -i 's|cat /proc/self/attr/current|cat /proc/self/attr/current 2>/dev/null|' $container_rootfs/etc/rc.sysinit - sed -i 's|cat /proc/self/attr/current|cat /proc/self/attr/current 2>/dev/null|' $container_rootfs/etc/rc.d/rc.sysinit - - # disable ipv6 - rm -f $container_rootfs/etc/sysconfig/network-scripts/init.ipv6-global - - # remove module stuff for iptables it just shows errors that are not - # relevant in a container - if [ -f "$container_rootfs/etc/sysconfig/iptables-config" ]; then - sed -i 's|IPTABLES_MODULES=".*|IPTABLES_MODULES=""|' $container_rootfs/etc/sysconfig/iptables-config - sed -i 's|IPTABLES_MODULES_UNLOAD=".*|IPTABLES_MODULES_UNLOAD="no"|' $container_rootfs/etc/sysconfig/iptables-config - fi - - # disable readahead in the container - if [ $container_release_major = "1" -a -e $container_rootfs/etc/sysconfig/readahead ]; then - rm -f $container_rootfs/etc/init/readahead-collector.conf - rm -f $container_rootfs/etc/init/readahead-disable-services.conf - sed -i 's|READAHEAD="yes"|READAHEAD="no"|' $container_rootfs/etc/sysconfig/readahead - fi - - - # no need to attempt to mount / - sed -i 's|mount -f /$|# LXC mount -f /|' $container_rootfs/etc/rc.sysinit - sed -i 's|mount -f /$|# LXC mount -f /|' $container_rootfs/etc/rc.d/rc.sysinit - sed -i 's|action \$"Remounting root filesystem|/bin/true # LXC action $"Remounting root filesystem|' $container_rootfs/etc/rc.sysinit - sed -i 's|action \$"Remounting root filesystem|/bin/true # LXC action $"Remounting root filesystem|' $container_rootfs/etc/rc.d/rc.sysinit - - # disable udev in the container - sed -i 's|.sbin.start_udev||' $container_rootfs/etc/rc.sysinit - sed -i 's|.sbin.start_udev||' $container_rootfs/etc/rc.d/rc.sysinit - - sed -i 's|\[ -x /sbin/hwclock|\[ 0 -eq 1|' $container_rootfs/etc/rc.d/init.d/halt - sed -i 's|^\[ -x /sbin/hwclock|\[ 0 -eq 1|' $container_rootfs/etc/rc.sysinit - sed -i 's|^\[ -x /sbin/hwclock|\[ 0 -eq 1|' $container_rootfs/etc/rc.d/rc.sysinit - sed -i 's|^/sbin/hwclock|# LXC /sbin/nohwclock|' $container_rootfs/etc/rc.sysinit - sed -i 's|^/sbin/hwclock|# LXC /sbin/nohwclock|' $container_rootfs/etc/rc.d/rc.sysinit - - touch $container_rootfs/.nolvm - - # fix assumptions that plymouth is available - sed -i 's|\[ "$PROMPT" != no \] && plymouth|[ "$PROMPT" != no ] \&\& [ -n "$PLYMOUTH" ] \&\& plymouth|' $container_rootfs/etc/rc.sysinit - sed -i 's|\[ "$PROMPT" != no \] && plymouth|[ "$PROMPT" != no ] \&\& [ -n "$PLYMOUTH" ] \&\& plymouth|' $container_rootfs/etc/rc.d/rc.sysinit - rm -f $container_rootfs/etc/init/plymouth-shutdown.conf - rm -f $container_rootfs/etc/init/quit-plymouth.conf - rm -f $container_rootfs/etc/init/splash-manager.conf - - # dont try to unmount /dev/lxc devices - sed -i 's|&& $1 !~ /^\\/dev\\/ram/|\&\& $2 !~ /^\\/dev\\/lxc/ \&\& $1 !~ /^\\/dev\\/ram/|' $container_rootfs/etc/init.d/halt - - # don't try to unmount swap - sed -i 's|\[ -f /proc/swaps \]|# LXC [ -f /proc/swaps ]|' $container_rootfs/etc/init.d/halt - - sed -i 's|mount -n -o remount /dev/shm >/dev/null 2>&1$|mkdir -p /dev/shm \&\& mount -t tmpfs tmpfs /dev/shm # LXC|' $container_rootfs/etc/rc.sysinit - sed -i 's|mount -n -o remount /dev/shm >/dev/null 2>&1$|mkdir -p /dev/shm \&\& mount -t tmpfs tmpfs /dev/shm # LXC|' $container_rootfs/etc/rc.d/rc.sysinit - - # there might be other services that are useless but the below set is a good start - # some of these might not exist in the image, so we silence chkconfig complaining - # about the service file not being found - for service in \ - acpid apmd auditd autofs cpuspeed dund gpm haldaemon hidd \ - ip6tables irqbalance iscsi iscsid isdn kdump kudzu \ - lm_sensors lvm2-monitor mdmonitor microcode_ctl \ - ntpd pcmcia postfix sendmail udev-post xfs ; - do - chroot $container_rootfs chkconfig 2>/dev/null $service off - done - - for service in rsyslog ; - do - chroot $container_rootfs chkconfig 2>/dev/null $service on - done -} - -container_rootfs_configure() -{ - container_rootfs_patch - echo "Configuring container for Linux for SPARC $container_release_major.$container_release_minor" - - # configure the network to use dhcp. we set DHCP_HOSTNAME so the guest - # will report its name and be resolv'able by the hosts dnsmasq - cat < $container_rootfs/etc/sysconfig/network-scripts/ifcfg-eth0 -DEVICE=eth0 -BOOTPROTO=dhcp -ONBOOT=yes -HOSTNAME=$name -DHCP_HOSTNAME=\`hostname\` -NM_CONTROLLED=no -TYPE=Ethernet -EOF - - cat < $container_rootfs/etc/sysconfig/network -NETWORKING=yes -NETWORKING_IPV6=no -HOSTNAME=$name -EOF - - # set minimal hosts - echo "127.0.0.1 localhost $name" > $container_rootfs/etc/hosts - - # this file has to exist for libvirt/Virtual machine monitor to boot the container - touch $container_rootfs/etc/mtab - - # setup console and tty[1-4] for login. note that /dev/console and - # /dev/tty[1-4] will be symlinks to the ptys /dev/lxc/console and - # /dev/lxc/tty[1-4] so that package updates can overwrite the symlinks. - # lxc will maintain these links and bind mount ptys over /dev/lxc/* - # since lxc.tty.dir is specified in the config. - - # allow root login on console, tty[1-4], and pts/0 for libvirt - echo "# LXC (Linux Containers)" >>$container_rootfs/etc/securetty - echo "lxc/console" >>$container_rootfs/etc/securetty - for i in 1 2 3 4; do - echo "lxc/tty$i" >>$container_rootfs/etc/securetty - done - echo "# For libvirt/Virtual Machine Monitor" >>$container_rootfs/etc/securetty - for i in 0 1 2 3 4; do - echo "pts/$i" >>$container_rootfs/etc/securetty - done - - # prevent mingetty from calling vhangup(2) since it fails with userns - if [ -f $container_rootfs/etc/init/tty.conf ]; then - sed -i 's|mingetty|mingetty --nohangup|' $container_rootfs/etc/init/tty.conf - fi - - # create maygetty which only spawns a getty on the console when running - # under lxc, not libvirt-lxc which symlinks /dev/console to the same pty - # as /dev/tty1 - cat <$container_rootfs/sbin/maygetty -#!/bin/sh -if [ "\$container" = "lxc" ]; then - exec /sbin/mingetty \$@ -fi -exec sleep infinity -EOF - chmod 755 $container_rootfs/sbin/maygetty - - cat < $container_rootfs/etc/init/console.conf -# console - getty -# -# This service maintains a getty on the console from the point the system is -# started until it is shut down again. - -start on stopped rc RUNLEVEL=[2345] -stop on runlevel [!2345] -env container - -respawn -exec /sbin/maygetty --nohangup --noclear /dev/console -EOF - - cat < $container_rootfs/etc/init/power-status-changed.conf -# power-status-changed - used to cleanly shut down the container -# -# This task is run whenever init receives SIGPWR -# Used to shut down the machine. - -start on power-status-changed - -exec init 0 -EOF - - # start with a clean /var/log/messages - rm -f $container_rootfs/var/log/messages - - # set initial timezone as on host - if [ -f /etc/sysconfig/clock ]; then - . /etc/sysconfig/clock - echo ZONE=$ZONE > $container_rootfs/etc/sysconfig/clock - chroot $container_rootfs tzdata-update - else - echo "Timezone in container is not configured. Adjust it manually." - fi - - # add oracle user - chroot $container_rootfs useradd -m -s /bin/bash oracle - printf "Added container user:\033[1moracle\033[0m\n" - printf "Added container user:\033[1mroot\033[0m\n" -} - -# create the container's lxc config file -container_config_create() -{ - echo "Create configuration file $cfg_dir/config" - mkdir -p $cfg_dir || die "unable to create config dir $cfg_dir" - - echo "# Common configuration" >> $cfg_dir/config - if [ -e "@LXCTEMPLATECONFIG@/sparclinux.common.conf" ]; then - echo "lxc.include = @LXCTEMPLATECONFIG@/sparclinux.common.conf" >> $cfg_dir/config - fi - - cat <> $cfg_dir/config || die "unable to create $cfg_dir/config" -# Container configuration for Linux for SPARC $container_release_major.$container_release_minor -lxc.arch = $arch -lxc.uts.name = $name -EOF - grep -q "^lxc.rootfs.path" $cfg_dir/config 2>/dev/null || echo "lxc.rootfs.path = $container_rootfs" >> $cfg_dir/config - - echo "lxc.cap.drop = sys_resource" >>$cfg_dir/config - - echo "lxc.cap.drop = setfcap setpcap" >>$cfg_dir/config - - echo "# Networking" >>$cfg_dir/config - # see if the default network settings were already specified - lxc_network_type=`grep '^lxc.net.0.type' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'` - if [ -z "$lxc_network_type" ]; then - echo "lxc.net.0.type = veth" >>$cfg_dir/config - lxc_network_type=veth - fi - - lxc_network_link=`grep '^lxc.net.0.link' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'` - if [ -z "$lxc_network_link" ]; then - echo "lxc.net.0.link = lxcbr0" >>$cfg_dir/config - lxc_network_link=lxcbr0 - fi - - lxc_network_hwaddr=`grep '^lxc.net.0.hwaddr' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'` - if [ -z "$lxc_network_hwaddr" ]; then - # generate a hwaddr for the container - # see http://sourceforge.net/tracker/?func=detail&aid=3411497&group_id=163076&atid=826303 - local hwaddr="00:16:3e:`dd if=/dev/urandom bs=8 count=1 2>/dev/null |od -t x8 | \ - head -n1 | awk '{print $2}' | cut -c1-6 | \ - sed 's/\(..\)/\1:/g; s/.$//'`" - echo "lxc.net.0.hwaddr = $hwaddr" >>$cfg_dir/config - fi - - lxc_network_flags=`grep '^lxc.net.0.flags' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'` - if [ -z "$lxc_network_flags" ]; then - echo "lxc.net.0.flags = up" >>$cfg_dir/config - fi - - cat <> $cfg_dir/config || die "unable to create $cfg_dir/config" -lxc.net.0.name = eth0 -lxc.net.0.mtu = 1500 -EOF -} - -container_rootfs_clone() -{ - if is_btrfs_subvolume $template_rootfs; then - # lxc-create already made $container_rootfs a btrfs subvolume, but - # in this case we want to snapshot the original subvolume so we we - # have to delete the one that lxc-create made - btrfs subvolume delete $container_rootfs - btrfs subvolume snapshot $template_rootfs $container_rootfs || die "btrfs clone template" - else - echo "Copying rootfs ..." - cp -axT $template_rootfs $container_rootfs || die "copy template" - fi -} - -container_rootfs_repo_create() -{ - echo "# LXC generated .repo file" >$1 - echo "[$2]" >>$1 - echo "name=Linux for SPARC $container_release_major.$container_release_minor ($basearch)" >>$1 - echo "baseurl=$3/" >>$1 - echo "enabled=1" >>$1 - echo "skip_if_unavailable=1" >>$1 - - if [ "$4" != "" ]; then - echo "gpgkey=$yum_url/RPM-GPG-KEY-oracle-ol$container_release_major" >>$1 - echo "gpgcheck=1" >>$1 - else - echo "gpgcheck=0" >>$1 - fi -} - -container_rootfs_dev_create() -{ - # create required devices. note that /dev/console will be created by lxc - # or libvirt itself to be a symlink to the right pty. - # take care to not nuke /dev in case $container_rootfs isn't set - dev_path="$container_rootfs/dev" - if [ $container_rootfs != "/" -a -d $dev_path ]; then - rm -rf $dev_path - fi - mkdir -p $dev_path - if can_chcon; then - # ensure symlinks created in /dev have the right context - chcon -t device_t $dev_path - fi - mknod -m 666 $dev_path/null c 1 3 - mknod -m 666 $dev_path/zero c 1 5 - mknod -m 666 $dev_path/random c 1 8 - mknod -m 666 $dev_path/urandom c 1 9 - mkdir -m 755 $dev_path/pts - mkdir -m 1777 $dev_path/shm - mknod -m 666 $dev_path/tty c 5 0 - mknod -m 666 $dev_path/tty1 c 4 1 - mknod -m 666 $dev_path/tty2 c 4 2 - mknod -m 666 $dev_path/tty3 c 4 3 - mknod -m 666 $dev_path/tty4 c 4 4 - mknod -m 666 $dev_path/full c 1 7 - mknod -m 600 $dev_path/initctl p - - # set selinux labels same as host - if can_chcon; then - for node in null zero random urandom pts shm \ - tty tty0 tty1 tty2 tty3 tty4 full ; - do - chcon --reference /dev/$node $dev_path/$node 2>/dev/null - done - fi -} - -container_rootfs_create() -{ - if can_chcon; then - chcon --reference / $container_rootfs 2>/dev/null - fi - - cmds="rpm wget yum" - for cmd in $cmds; do - which $cmd >/dev/null 2>&1 - if [ $? -ne 0 ]; then - die "The $cmd command is required, please install it" - fi - done - - mkdir -p @LOCALSTATEDIR@/lock/subsys - ( - flock -x 9 - if [ $? -ne 0 ]; then - die "The template is busy." - fi - - echo "Yum installing release $container_release_major.$container_release_minor for $basearch" - - if [ -n "$repourl" ]; then - yum_url=$repourl - else - yum_url=http://yum.oracle.com - fi - - if [ -n "$baseurl" ]; then - # create .repo pointing at baseurl - repo="lxc-install" - mkdir -p $container_rootfs/etc/yum.repos.d - container_rootfs_repo_create \ - $container_rootfs/etc/yum.repos.d/lxc-install.repo $repo $baseurl - else - # get public-yum repo file - if [ $container_release_major = "1" ]; then - repofile=yum-linux-sparc64.repo - else - die "Unsupported release $container_release_major" - fi - - mkdir -p $container_rootfs/etc/yum.repos.d - wget -q $yum_url/$repofile -O $container_rootfs/etc/yum.repos.d/$repofile - if [ $? -ne 0 ]; then - die "Unable to download repo file $yum_url/$repofile, release unavailable" - fi - - # yum will take $basearch from host, so force the arch we want - sed -i "s|\$basearch|$basearch|" $container_rootfs/etc/yum.repos.d/$repofile - - # replace url if they specified one - if [ -n "$repourl" ]; then - sed -i "s|baseurl=http://yum.oracle.com/|baseurl=$repourl/repo|" $container_rootfs/etc/yum.repos.d/$repofile - sed -i "s|gpgkey=http://yum.oracle.com|gpgkey=$repourl|" $container_rootfs/etc/yum.repos.d/$repofile - - fi - - # disable all repos, then enable the repo for the version we are installing. - if [ $container_release_minor = "latest" ]; then - repo="lfs"_$container_release_minor - else - die "Unsupported release $container_release_major.$container_release_minor" - fi - sed -i "s|enabled=1|enabled=0|" $container_rootfs/etc/yum.repos.d/$repofile - sed -i "/\[$repo\]/,/\[/ s/enabled=0/enabled=1/" $container_rootfs/etc/yum.repos.d/$repofile - fi - - container_rootfs_dev_create - - # don't put devpts,proc, nor sysfs in here, it will already be mounted for us by lxc/libvirt - echo "" >$container_rootfs/etc/fstab - - # create rpm db, download and yum install minimal packages - mkdir -p $container_rootfs/var/lib/rpm - rpm --root $container_rootfs --initdb - yum_args="--installroot $container_rootfs --disablerepo=* --enablerepo=$repo -y --nogpgcheck" - min_pkgs="yum initscripts passwd rsyslog vim-minimal openssh-server openssh-clients dhclient chkconfig rootfiles policycoreutils sparclinux-release" - - # we unshare the mount namespace because yum installing the ol4 - # packages causes $rootfs/proc to be mounted on - lxc-unshare -s MOUNT yum -- $yum_args install $min_pkgs $user_pkgs - if [ $? -ne 0 ]; then - die "Failed to download and install the rootfs, aborting." - fi - - # rsyslog and pam depend on coreutils for some common commands in - # their POSTIN scriptlets, but coreutils wasn't installed yet. now - # that coreutils is installed, reinstall the packages so their POSTIN - # runs right. similarly, libutempter depends on libselinux.so.1 when - # it runs /usr/sbin/groupadd, so reinstall it too - redo_pkgs="" - if [ x"$redo_pkgs" != x ]; then - rpm --root $container_rootfs --nodeps -e $redo_pkgs - lxc-unshare -s MOUNT yum -- $yum_args install $redo_pkgs - if [ $? -ne 0 ]; then - die "Unable to reinstall packages" - fi - fi - - # these distributions put the rpm database in a place the guest is - # not expecting it, so move it - if [ $host_distribution = "Ubuntu" -o $host_distribution = "Debian" ]; then - mv $container_rootfs/$HOME/.rpmdb/* $container_rootfs/var/lib/rpm - fi - - # if the native rpm created the db with Hash version 9, we need to - # downgrade it to Hash version 8 for use with OL5.x - db_version=`file $container_rootfs/var/lib/rpm/Packages | \ - grep -o 'version [0-9]*' |awk '{print $2}'` - - # the host rpm may not be the same as the guest, rebuild the db with - # the guest rpm version - echo "Rebuilding rpm database" - rm -f $container_rootfs/var/lib/rpm/__db* - chroot $container_rootfs rpm --rebuilddb >/dev/null 2>&1 - - ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-sparclinux-$name - if [ $? -ne 0 ]; then - exit 1 - fi -} - -container_release_get() -{ - if [ -f $1/etc/sparclinux-release ]; then - container_release_version=`cat $1/etc/sparclinux-release |awk '/^Linux/ {print $5}'` - container_release_major=`echo $container_release_version |awk -F '.' '{print $1}'` - container_release_minor=`echo $container_release_version |awk -F '.' '{print $2}'` - else - echo "Unable to determine container release version" - exit 1 - fi -} - -usage() -{ - cat < architecture (sparc64) - -R|--release= release to download for the new container - --rootfs= rootfs path - -r|--rpms= additional rpms to install into container - -u|--url= replace yum repo url (ie. Oracle public-yum mirror) - --baseurl= use package repository (ie. file:///mnt) - arch and release must also be specified - -t|--templatefs= copy/clone rootfs at path instead of downloading - -P|--patch= only patch the rootfs at path for use as a container - -h|--help - -Release is of the format "major.minor", for example "1.0" or "1.latest" -This template supports Linux for SPARC release 1.0 -EOF - return 0 -} - -options=$(getopt -o hp:n:a:R:r:u:t: -l help,rootfs:,path:,name:,arch:,release:,rpms:,url:,templatefs:,patch:,baseurl: -- "$@") -if [ $? -ne 0 ]; then - usage $(basename $0) - exit 1 -fi - -eval set -- "$options" -while true -do - case "$1" in - -h|--help) usage $0 && exit 0;; - -p|--path) cfg_dir=$2; shift 2;; - --rootfs) container_rootfs=$2; shift 2;; - -n|--name) name=$2; shift 2;; - -a|--arch) arch=$2; shift 2;; - -R|--release) container_release_version=$2; shift 2;; - -r|--rpms) user_pkgs=$2; shift 2;; - -u|--url) repourl=$2; shift 2;; - -t|--templatefs) template_rootfs=$2; shift 2;; - --patch) patch_rootfs=$2; shift 2;; - --baseurl) baseurl=$2; shift 2;; - --) shift 1; break ;; - *) break ;; - esac -done - -# make sure mandatory args are given and valid -if [ "$(id -u)" != "0" ]; then - echo "This script should be run as 'root'" - exit 1 -fi - -if [ -n "$baseurl" ]; then - if [ "$arch" = "" -o "$container_release_version" = "" ]; then - echo "The --arch and --release must be specified when using --baseurl" - usage - exit 1 - fi -fi - -if [ "$arch" = "" ]; then - arch=$(uname -m) -fi - -if [ -n "$patch_rootfs" ]; then - container_rootfs="$patch_rootfs" - container_release_get $container_rootfs - container_rootfs_patch - exit 0 -fi - -if [ -z $name ]; then - echo "Container name must be given" - usage - exit 1 -fi - -if [ -z $cfg_dir ]; then - echo "Configuration directory must be given, check lxc-create" - usage - exit 1 -fi - -basearch=$arch - -if [ "$arch" != "sparc64" ]; then - echo "Bad architecture given, check lxc-create" - usage - exit 1 -fi - -if [ -f /etc/sparclinux-release ]; then - host_distribution="SPARCLinux" - host_release_version=`cat /etc/sparclinux-release |awk '{print $5}'` - host_release_major=`echo $host_release_version |awk -F '.' '{print $1}'` - host_release_minor=`echo $host_release_version |awk -F '.' '{print $2}'` -else - echo "Unable to determine host distribution" - exit 1 -fi - -echo "Host is $host_distribution $host_release_version" - -if [ -z "$container_rootfs" ]; then - container_rootfs="$cfg_dir/rootfs" -fi - -if [ -n "$template_rootfs" ]; then - container_release_get $template_rootfs -else - if [ -z "$container_release_version" ]; then - if [ $host_distribution = "SPARCLinux" ]; then - container_release_version=$host_release_version - else - echo "No release specified with -R, defaulting to 1.latest" - container_release_version="1.latest" - fi - fi - container_release_major=`echo $container_release_version |awk -F '.' '{print $1}'` - container_release_minor=`echo $container_release_version |awk -F '.' '{print $2}'` -fi - -container_config_create -if [ -n "$template_rootfs" ]; then - container_rootfs_clone -else - container_rootfs_create -fi - -container_release_get $container_rootfs - -container_rootfs_configure - -echo "Container : $container_rootfs" -echo "Config : $cfg_dir/config" -echo "Network : eth0 ($lxc_network_type) on $lxc_network_link" diff --git a/templates/lxc-sshd.in b/templates/lxc-sshd.in deleted file mode 100644 index e6f90ad7c..000000000 --- a/templates/lxc-sshd.in +++ /dev/null @@ -1,276 +0,0 @@ -#!/bin/bash - -# -# lxc: linux Container library - -# Authors: -# Daniel Lezcano - -# 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 - -# 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 - -install_sshd() -{ - rootfs=$1 - - tree="\ -$rootfs/var/empty/sshd \ -$rootfs/var/lib/empty/sshd \ -$rootfs/etc/init.d \ -$rootfs/etc/rc.d \ -$rootfs/etc/ssh \ -$rootfs/etc/sysconfig/network-scripts \ -$rootfs/dev/shm \ -$rootfs/run/sshd \ -$rootfs/proc \ -$rootfs/sys \ -$rootfs/bin \ -$rootfs/sbin \ -$rootfs/usr \ -$rootfs/tmp \ -$rootfs/home \ -$rootfs/root \ -$rootfs/lib \ -$rootfs/lib64" - - mkdir -p $tree - if [ $? -ne 0 ]; then - return 1 - fi - - ln -s /run $rootfs/var/run - if [ $? -ne 0 ]; then - return 1 - fi - - return 0 -} - -configure_sshd() -{ - rootfs=$1 - - cat < $rootfs/etc/passwd -root:x:0:0:root:/root:/bin/bash -sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin -EOF - - cat < $rootfs/etc/group -root:x:0:root -sshd:x:74: -EOF - -ssh-keygen -t rsa -N "" -f $rootfs/etc/ssh/ssh_host_rsa_key -ssh-keygen -t dsa -N "" -f $rootfs/etc/ssh/ssh_host_dsa_key - - # by default setup root password with no password - cat < $rootfs/etc/ssh/sshd_config -Port 22 -Protocol 2 -HostKey /etc/ssh/ssh_host_rsa_key -HostKey /etc/ssh/ssh_host_dsa_key -UsePrivilegeSeparation yes -SyslogFacility AUTH -LogLevel INFO -LoginGraceTime 120 -PermitRootLogin yes -StrictModes yes -PubkeyAuthentication yes -IgnoreRhosts yes -HostbasedAuthentication no -PermitEmptyPasswords yes -ChallengeResponseAuthentication no -EOF - - if [ -n "$auth_key" -a -f "$auth_key" ]; then - u_path="/root/.ssh" - root_u_path="$rootfs/$u_path" - mkdir -p $root_u_path - cp $auth_key "$root_u_path/authorized_keys" - chown -R 0:0 "$rootfs/$u_path" - chmod 700 "$rootfs/$u_path" - echo "Inserted SSH public key from $auth_key into $rootfs/$u_path" - fi - - return 0 -} - -copy_configuration() -{ - path=$1 - rootfs=$2 - name=$3 - - init_path=$(realpath --relative-to=/ $(readlink -f /sbin/init)) - - grep -q "^lxc.rootfs.path" $path/config 2>/dev/null || echo "lxc.rootfs.path = $rootfs" >> $path/config -cat <> $path/config -lxc.uts.name = $name -lxc.pty.max = 1024 -lxc.cap.drop = sys_module mac_admin mac_override sys_time - -# When using LXC with apparmor, uncomment the next line to run unconfined: -#lxc.apparmor.profile = unconfined - -lxc.mount.entry = /dev dev none ro,bind 0 0 -lxc.mount.entry = /lib lib none ro,bind 0 0 -lxc.mount.entry = /bin bin none ro,bind 0 0 -lxc.mount.entry = /usr usr none ro,bind 0 0 -lxc.mount.entry = /sbin sbin none ro,bind 0 0 -lxc.mount.entry = tmpfs run/sshd tmpfs mode=0644 0 0 -lxc.mount.entry = @LXCTEMPLATEDIR@/lxc-sshd $init_path none ro,bind 0 0 -lxc.mount.entry = /etc/init.d etc/init.d none ro,bind 0 0 - -lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed -EOF - - # Oracle Linux and Fedora need the following two bind mounted - if [ -d /etc/sysconfig/network-scripts ]; then - cat <> $path/config -lxc.mount.entry = /etc/sysconfig/network-scripts etc/sysconfig/network-scripts none ro,bind 0 0 -EOF - fi - - if [ -d /etc/rc.d ]; then - cat <> $path/config -lxc.mount.entry = /etc/rc.d etc/rc.d none ro,bind 0 0 -EOF - fi - - # if no .ipv4 section in config, then have the container run dhcp - grep -q "^lxc.net.0.ipv4.address" $path/config || touch $rootfs/run-dhcp - - if [ "$(uname -m)" = "x86_64" ]; then - cat <> $path/config -lxc.mount.entry = /lib64 lib64 none ro,bind 0 0 -EOF - fi -} - -usage() -{ - cat < [--rootfs=] -EOF - return 0 -} - -check_for_cmd() -{ - cmd_path=`type $1` - if [ $? -ne 0 ]; then - echo "The command '$1' $cmd_path is not accessible on the system" - exit 1 - fi - # we use cut instead of awk because awk is alternatives symlink on ubuntu - # and /etc/alternatives isn't bind mounted - cmd_path=`echo $cmd_path |cut -d ' ' -f 3` -} - -options=$(getopt -o hp:n:S: -l help,rootfs:,path:,name:,auth-key: -- "$@") -if [ $? -ne 0 ]; then - usage $(basename $0) - exit 1 -fi -eval set -- "$options" - -while true -do - case "$1" in - -h|--help) usage $0 && exit 0;; - -p|--path) path=$2; shift 2;; - --rootfs) rootfs=$2; shift 2;; - -n|--name) name=$2; shift 2;; - -S|--auth-key) auth_key=$2; shift 2;; - --) shift 1; break ;; - *) break ;; - esac -done - -if [ "$(id -u)" != "0" ]; then - echo "This script should be run as 'root'" - exit 1 -fi - -if [ $0 = "/sbin/init" ]; then - - PATH="$PATH:/bin:/sbin:/usr/sbin" - check_for_cmd @SBINDIR@/init.lxc - check_for_cmd sshd - sshd_path=$cmd_path - - # run dhcp? - if [ -f /run-dhcp ]; then - check_for_cmd dhclient - check_for_cmd ifconfig - touch /etc/fstab - rm -f /dhclient.conf - cat > /dhclient.conf << EOF -send host-name = gethostname(); -EOF - ifconfig eth0 up - dhclient eth0 -cf /dhclient.conf - echo "Container IP address:" - ifconfig eth0 |grep inet - fi - - exec @SBINDIR@/init.lxc -- $sshd_path - exit 1 -fi - -if [ -z "$path" ]; then - echo "'path' parameter is required" - exit 1 -fi - -# detect rootfs -config="$path/config" -if [ -z "$rootfs" ]; then - if grep -q '^lxc.rootfs.path' $config 2>/dev/null ; then - rootfs=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $config) - else - rootfs=$path/rootfs - fi -fi - -install_sshd $rootfs -if [ $? -ne 0 ]; then - echo "failed to install sshd's rootfs" - exit 1 -fi - -configure_sshd $rootfs -if [ $? -ne 0 ]; then - echo "failed to configure sshd template" - exit 1 -fi - -copy_configuration $path $rootfs $name -if [ $? -ne 0 ]; then - echo "failed to write configuration file" - exit 1 -fi diff --git a/templates/lxc-ubuntu-cloud.in b/templates/lxc-ubuntu-cloud.in deleted file mode 100644 index 2bf534ab8..000000000 --- a/templates/lxc-ubuntu-cloud.in +++ /dev/null @@ -1,374 +0,0 @@ -#!/bin/bash - -# template script for generating ubuntu container for LXC based on released -# cloud images. -# -# Copyright © 2012 Serge Hallyn -# -# 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 - -set -e - -STATE_DIR="@LOCALSTATEDIR@" -HOOK_DIR="@LXCHOOKDIR@" -CLONE_HOOK_FN="$HOOK_DIR/ubuntu-cloud-prep" -LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@" -KNOWN_RELEASES="precise trusty xenial yakkety zesty" -skip_arch_check=${UCTEMPLATE_SKIP_ARCH_CHECK:-0} - -# Make sure the usual locations are in PATH -export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin - -if [ -r /etc/default/lxc ]; then - . /etc/default/lxc -fi - -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 - -copy_configuration() -{ - path=$1 - rootfs=$2 - name=$3 - arch=$4 - release=$5 - - if [ $arch = "i386" ]; then - arch="i686" - fi - - # if there is exactly one veth network entry, make sure it has an - # associated hwaddr. - nics=`grep -e '^lxc\.net\.0\.type[ \t]*=[ \t]*veth' $path/config | wc -l` - if [ $nics -eq 1 ]; then - grep -q "^lxc.net.0.hwaddr" $path/config || sed -i -e "/^lxc\.net\.0\.type[ \t]*=[ \t]*veth/a lxc.net.0.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')" $path/config - fi - - # Generate the configuration file - ## Relocate all the network config entries - sed -i -e "/lxc.net.0/{w ${path}/config-network" -e "d}" $path/config - - ## Relocate any other config entries - sed -i -e "/lxc./{w ${path}/config-auto" -e "d}" $path/config - - ## Add all the includes - echo "" >> $path/config - echo "# Common configuration" >> $path/config - if [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.common.conf" ]; then - echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.common.conf" >> $path/config - fi - if [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.${release}.conf" ]; then - echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.${release}.conf" >> $path/config - fi - if [ $in_userns -eq 1 ] && [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.userns.conf" ]; then - echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.userns.conf" >> $path/config - fi - - ## Add the container-specific config - echo "" >> $path/config - echo "# Container specific configuration" >> $path/config - [ -e "$path/config-auto" ] && cat $path/config-auto >> $path/config && rm $path/config-auto - grep -q "^lxc.rootfs.path" $path/config 2>/dev/null || echo "lxc.rootfs.path = $rootfs" >> $path/config - cat <> $path/config -lxc.uts.name = $name -lxc.arch = $arch -EOF - - ## Re-add the previously removed network config - echo "" >> $path/config - echo "# Network configuration" >> $path/config - cat $path/config-network >> $path/config - rm $path/config-network - - # Set initial timezone as on host - if [ -f /etc/timezone ]; then - cat /etc/timezone > $rootfs/etc/timezone - chroot $rootfs dpkg-reconfigure -f noninteractive tzdata - elif [ -f /etc/sysconfig/clock ]; then - . /etc/sysconfig/clock - echo $ZONE > $rootfs/etc/timezone - chroot $rootfs dpkg-reconfigure -f noninteractive tzdata - else - echo "Timezone in container is not configured. Adjust it manually." - fi - - # rmdir /dev/shm for containers that have /run/shm - # I'm afraid of doing rm -rf $rootfs/dev/shm, in case it did - # get bind mounted to the host's /run/shm. So try to rmdir - # it, and in case that fails move it out of the way. - # NOTE: This can only be removed once 12.04 goes out of support - if [ ! -L $rootfs/dev/shm ] && [ -e $rootfs/dev/shm ]; then - rmdir $rootfs/dev/shm 2>/dev/null || mv $rootfs/dev/shm $rootfs/dev/shm.bak - ln -s /run/shm $rootfs/dev/shm - fi - - return 0 -} - -usage() -{ - cat < ]: Release name of container, defaults to host -[ --rootfs ]: Path in which rootfs will be placed -[ -a | --arch ]: Architecture of container, defaults to host architecture -[ -T | --tarball ]: Location of tarball -[ -d | --debug ]: Run with 'set -x' to debug errors -[ -s | --stream]: Use specified stream rather than 'tryreleased' - -Additionally, clone hooks can be passed through (ie, --userdata). For those, -see: - $CLONE_HOOK_FN --help -EOF - return 0 -} - -options=$(getopt -o a:hp:r:n:Fi:CLS:T:ds:u: -l arch:,help,rootfs:,path:,release:,name:,flush-cache,hostid:,auth-key:,cloud,no_locales,tarball:,debug,stream:,userdata:,vendordata:,mapped-uid:,mapped-gid: -- "$@") -if [ $? -ne 0 ]; then - usage $(basename $0) - exit 1 -fi -eval set -- "$options" - -mapped_uid=-1 -mapped_gid=-1 -# default release is trusty, or the systems release if recognized -release=trusty -if [ -f /etc/lsb-release ]; then - . /etc/lsb-release - rels=$(ubuntu-distro-info --supported 2>/dev/null) || - rels="$KNOWN_RELEASES" - for r in $rels; do - [ "$DISTRIB_CODENAME" = "$r" ] && release="$r" - done -fi - -# Code taken from debootstrap -if [ -x /usr/bin/dpkg ] && /usr/bin/dpkg --print-architecture >/dev/null 2>&1; then - arch=`/usr/bin/dpkg --print-architecture` -elif type udpkg >/dev/null 2>&1 && udpkg --print-architecture >/dev/null 2>&1; then - arch=`/usr/bin/udpkg --print-architecture` -else - arch=$(uname -m) - if [ "$arch" = "i686" ]; then - arch="i386" - elif [ "$arch" = "x86_64" ]; then - arch="amd64" - elif [ "$arch" = "armv7l" ]; then - # note: arm images don't exist before oneiric; are called armhf in - # trusty and later; and are not supported by the query, so we don't actually - # support them yet (see check later on). When Query2 is available, - # we'll use that to enable arm images. - arch="armhf" - elif [ "$arch" = "aarch64" ]; then - arch="arm64" - elif [ "$arch" = "ppc64le" ]; then - arch="ppc64el" - fi -fi - -debug=0 -hostarch=$arch -cloud=0 -locales=1 -flushcache=0 -stream="tryreleased" -cloneargs=() -while true -do - case "$1" in - -h|--help) usage $0 && exit 1;; - -p|--path) path=$2; shift 2;; - -n|--name) name=$2; shift 2;; - -F|--flush-cache) flushcache=1; shift 1;; - -r|--release) release=$2; shift 2;; - -a|--arch) arch=$2; shift 2;; - -T|--tarball) tarball=$2; shift 2;; - -d|--debug) debug=1; shift 1;; - -s|--stream) stream=$2; shift 2;; - --rootfs) rootfs=$2; shift 2;; - -L|--no?locales) cloneargs[${#cloneargs[@]}]="--no-locales"; shift 1;; - -i|--hostid) cloneargs[${#cloneargs[@]}]="--hostid=$2"; shift 2;; - -u|--userdata) cloneargs[${#cloneargs[@]}]="--userdata=$2"; shift 2;; - -V|--vendordata) cloneargs[${#cloneargs[@]}]="--vendordata=$2"; shift 2;; - -C|--cloud) cloneargs[${#cloneargs[@]}]="--cloud"; shift 1;; - -S|--auth-key) cloneargs[${#cloneargs[@]}]="--auth-key=$2"; shift 2;; - --mapped-uid) mapped_uid=$2; shift 2;; - --mapped-gid) mapped_gid=$2; shift 2;; - --) shift 1; break ;; - *) break ;; - esac -done - -cloneargs=( "--name=$name" "${cloneargs[@]}" ) - -if [ $debug -eq 1 ]; then - set -x -fi - -if [ "$arch" = "i686" ]; then - arch=i386 -fi - -if [ "$skip_arch_check" = "0" ]; then - case "$hostarch:$arch" in - $arch:$arch) : ;; # the host == container - amd64:i386) :;; # supported "cross" - arm64:arm*) :;; # supported "cross" - armel:armhf) :;; # supported "cross" - armhf:armel) :;; # supported "cross" - *) echo "cannot create '$arch' container on hostarch '$hostarch'"; - exit 1;; - esac -fi - -if [ "$stream" != "daily" -a "$stream" != "released" -a "$stream" != "tryreleased" ]; then - echo "Only 'daily' and 'released' and 'tryreleased' streams are supported" - exit 1 -fi - -if [ -z "$path" ]; then - echo "'path' parameter is required" - exit 1 -fi - -if [ "$(id -u)" != "0" ]; then - echo "This script should be run as 'root'" - exit 1 -fi - -# detect rootfs -config="$path/config" -if [ -z "$rootfs" ]; then - if grep -q '^lxc.rootfs.path' $config 2>/dev/null ; then - rootfs=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $config) - else - rootfs=$path/rootfs - fi -fi - -type ubuntu-cloudimg-query -type wget - -# determine the url, tarball, and directory names -# download if needed -# Allow the cache base to be set by environment variable -cache=${LXC_CACHE_PATH:-"$STATE_DIR/cache/lxc"}/cloud-$release -if [ $in_userns -eq 1 ]; then - STATE_DIR="$HOME/.cache/lxc" - cache=${LXC_CACHE_PATH:-"$STATE_DIR"}/cloud-$release -fi - -mkdir -p $cache - -if [ "$stream" = "tryreleased" ]; then - stream=released - ubuntu-cloudimg-query $release $stream $arch 1>/dev/null 2>/dev/null || stream=daily -fi - -if [ -n "$tarball" ]; then - url2="$tarball" -else - if ! url1=`ubuntu-cloudimg-query $release $stream $arch --format "%{url}\n"`; then - echo "There is no download available for release=$release, stream=$stream, arch=$arch" - [ "$stream" = "daily" ] || echo "You may try with '--stream=daily'" - exit 1 - fi - if [ "$release" = "precise" ] || [ "$release" = "trusty" ]; then - url2=`echo $url1 | sed -e 's/.tar.gz/-root\0/' -e 's/.tar.gz/.tar.xz/'` - else - url2=`echo $url1 | sed -e 's/.tar.gz/.squashfs/'` - fi -fi - -filename=`basename $url2` - -wgetcleanup() -{ - rm -f $filename -} - -do_extract_rootfs() { - - cd $cache - if [ $flushcache -eq 1 ]; then - echo "Clearing the cached images" - rm -f $filename - fi - - trap wgetcleanup EXIT SIGHUP SIGINT SIGTERM - if [ ! -f $filename ]; then - wget $url2 - fi - trap EXIT - trap SIGHUP - trap SIGINT - trap SIGTERM - - echo "Extracting container rootfs" - mkdir -p $rootfs - cd $rootfs - if [ "${filename##*.}" = "squashfs" ]; then - unsquashfs -n -f -d "$rootfs" "$cache/$filename" - else - if [ $in_userns -eq 1 ]; then - tar --anchored --exclude="dev/*" --numeric-owner -xpf "$cache/$filename" - mkdir -p $rootfs/dev/pts/ - else - tar --numeric-owner -xpf "$cache/$filename" - fi - fi -} - -if [ -n "$tarball" ]; then - do_extract_rootfs -else - mkdir -p "$STATE_DIR/lock/subsys/" - ( - flock -x 9 - do_extract_rootfs - ) 9>"$STATE_DIR/lock/subsys/lxc-ubuntu-cloud" -fi - -copy_configuration $path $rootfs $name $arch $release - -"$CLONE_HOOK_FN" "${cloneargs[@]}" "$rootfs" - -if [ $mapped_uid -ne -1 ]; then - chown $mapped_uid $path/config - chown -R $mapped_uid $STATE_DIR - chown -R $mapped_uid $cache -fi -if [ $mapped_gid -ne -1 ]; then - chgrp $mapped_gid $path/config - chgrp -R $mapped_gid $STATE_DIR - chgrp -R $mapped_gid $cache -fi - -echo "Container $name created." -exit 0 - -# vi: ts=4 expandtab diff --git a/templates/lxc-ubuntu.in b/templates/lxc-ubuntu.in deleted file mode 100644 index 80a28fd2a..000000000 --- a/templates/lxc-ubuntu.in +++ /dev/null @@ -1,877 +0,0 @@ -#!/bin/bash - -# -# template script for generating ubuntu container for LXC -# -# This script consolidates and extends the existing lxc ubuntu scripts -# - -# Copyright © 2011 Serge Hallyn -# Copyright © 2010 Wilhelm Meier -# Author: Wilhelm Meier -# -# 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 - -# 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 - -set -e - -LOCALSTATEDIR="@LOCALSTATEDIR@" -LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@" -# Allows the lxc-cache directory to be set by environment variable -LXC_CACHE_PATH=${LXC_CACHE_PATH:-"$LOCALSTATEDIR/cache/lxc"} - -if [ -r /etc/default/lxc ]; then - . /etc/default/lxc -fi - -# Check if given path is in a btrfs partition -is_btrfs() -{ - [ -e $1 -a $(stat -f -c '%T' $1) = "btrfs" ] -} - -# Check if given path is the root of a btrfs subvolume -is_btrfs_subvolume() -{ - [ -d $1 -a $(stat -f -c '%T' $1) = "btrfs" -a $(stat -c '%i' $1) -eq 256 ] -} - -try_mksubvolume() -{ - path=$1 - [ -d $path ] && return 0 - mkdir -p $(dirname $path) - if which btrfs >/dev/null 2>&1 && is_btrfs $(dirname $path); then - btrfs subvolume create $path - else - mkdir -p $path - fi -} - -try_rmsubvolume() -{ - path=$1 - [ -d $path ] || return 0 - if which btrfs >/dev/null 2>&1 && is_btrfs_subvolume $path; then - btrfs subvolume delete $path - else - rm -rf $path - fi -} - -configure_ubuntu() -{ - rootfs=$1 - hostname=$2 - release=$3 - user=$4 - password=$5 - - # configure the network using the dhcp - if chroot $rootfs which netplan >/dev/null 2>&1; then - cat < $rootfs/etc/netplan/10-lxc.yaml -network: - ethernets: - eth0: {dhcp4: true} - version: 2 -EOF - else - cat < $rootfs/etc/network/interfaces -# This file describes the network interfaces available on your system -# and how to activate them. For more information, see interfaces(5). - -# The loopback network interface -auto lo -iface lo inet loopback - -auto eth0 -iface eth0 inet dhcp -EOF - fi - - # set the hostname - cat < $rootfs/etc/hostname -$hostname -EOF - # set minimal hosts - cat < $rootfs/etc/hosts -127.0.0.1 localhost -127.0.1.1 $hostname - -# The following lines are desirable for IPv6 capable hosts -::1 ip6-localhost ip6-loopback -fe00::0 ip6-localnet -ff00::0 ip6-mcastprefix -ff02::1 ip6-allnodes -ff02::2 ip6-allrouters -EOF - - if [ ! -f $rootfs/etc/init/container-detect.conf ]; then - # suppress log level output for udev - sed -i "s/=\"err\"/=0/" $rootfs/etc/udev/udev.conf - - # remove jobs for consoles 5 and 6 since we only create 4 consoles in - # this template - rm -f $rootfs/etc/init/tty{5,6}.conf - fi - - if [ -z "$bindhome" ]; then - chroot $rootfs useradd --create-home -s /bin/bash $user - echo "$user:$password" | chroot $rootfs chpasswd - fi - - # make sure we have the current locale defined in the container - if [ -z "$LANG" ] || echo $LANG | grep -E -q "^C(\..+)*$"; then - chroot $rootfs locale-gen en_US.UTF-8 || true - chroot $rootfs update-locale LANG=en_US.UTF-8 || true - else - chroot $rootfs locale-gen $LANG || true - chroot $rootfs update-locale LANG=$LANG || true - fi - - # generate new SSH keys - if [ -x $rootfs/var/lib/dpkg/info/openssh-server.postinst ]; then - cat > $rootfs/usr/sbin/policy-rc.d << EOF -#!/bin/sh -exit 101 -EOF - chmod +x $rootfs/usr/sbin/policy-rc.d - - if [ -f "$rootfs/etc/init/ssh.conf" ]; then - mv "$rootfs/etc/init/ssh.conf" "$rootfs/etc/init/ssh.conf.disabled" - fi - - rm -f $rootfs/etc/ssh/ssh_host_*key* - - DPKG_MAINTSCRIPT_PACKAGE=openssh DPKG_MAINTSCRIPT_NAME=postinst chroot $rootfs /var/lib/dpkg/info/openssh-server.postinst configure - - sed -i "s/root@$(hostname)/root@$hostname/g" $rootfs/etc/ssh/ssh_host_*.pub - - if [ -f "$rootfs/etc/init/ssh.conf.disabled" ]; then - mv "$rootfs/etc/init/ssh.conf.disabled" "$rootfs/etc/init/ssh.conf" - fi - - rm -f $rootfs/usr/sbin/policy-rc.d - fi - - return 0 -} - -# finish setting up the user in the container by injecting ssh key and -# adding sudo group membership. -# passed-in user is either 'ubuntu' or the user to bind in from host. -finalize_user() -{ - user=$1 - - sudo_version=$(chroot $rootfs dpkg-query -W -f='${Version}' sudo) - - if chroot $rootfs dpkg --compare-versions $sudo_version gt "1.8.3p1-1"; then - groups="sudo" - else - groups="sudo admin" - fi - - for group in $groups; do - chroot $rootfs groupadd --system $group >/dev/null 2>&1 || true - chroot $rootfs adduser ${user} $group >/dev/null 2>&1 || true - done - - if [ -n "$auth_key" -a -f "$auth_key" ]; then - u_path="/home/${user}/.ssh" - root_u_path="$rootfs/$u_path" - mkdir -p $root_u_path - cp $auth_key "$root_u_path/authorized_keys" - chroot $rootfs chown -R ${user}: "$u_path" - - echo "Inserted SSH public key from $auth_key into /home/${user}/.ssh/authorized_keys" - fi - return 0 -} - -# A function to try and autodetect squid-deb-proxy servers on the local network -# if either the squid-deb-proxy-client package is installed on the host or -# a parent container set the 50squid-deb-proxy-client file. -squid_deb_proxy_autodetect() -{ - local apt_discover=/usr/share/squid-deb-proxy-client/apt-avahi-discover - local proxy_file=/etc/apt/apt.conf.d/50squid-deb-proxy-client - squid_proxy_line= # That's a global :/ - - # Maybe the host is aware of a squid-deb-proxy? - if [ -f $apt_discover ]; then - echo -n "Discovering squid-deb-proxy..." - squid_proxy_line=$($apt_discover) - if [ -n "$squid_proxy_line" ]; then - echo "found squid-deb-proxy: $squid_proxy_line" - else - echo "no squid-deb-proxy found" - fi - fi - - # Are we in a nested container, and the parent already knows of a proxy? - if [ -f $proxy_file ]; then - # Extract the squid URL from the file (whatever is between "") - squid_proxy_line=`cat $proxy_file | sed "s/.*\"\(.*\)\".*/\1/"` - fi -} - -# -# Choose proxies for container -# http_proxy will be used by debootstrap on the host. -# APT_PROXY will be used to set /etc/apt/apt.conf.d/70proxy in the container. -# -choose_container_proxy() -{ - local rootfs=$1 - local arch=$2 - - if [ -z "$HTTP_PROXY" ]; then - HTTP_PROXY="none" - fi - case "$HTTP_PROXY" in - none) - squid_deb_proxy_autodetect - if [ -n "$squid_proxy_line" ]; then - APT_PROXY=$squid_proxy_line - export http_proxy=$squid_proxy_line - else - APT_PROXY= - fi - ;; - apt) - RES=`apt-config shell APT_PROXY Acquire::http::Proxy` - eval $RES - [ -z "$APT_PROXY" ] || export http_proxy=$APT_PROXY - ;; - *) - APT_PROXY=$HTTP_PROXY - export http_proxy=$HTTP_PROXY - ;; - esac -} - -write_sourceslist() -{ - # $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 $1/etc/apt/apt.conf.d - cat > $1/etc/apt/apt.conf.d/70proxy << EOF -Acquire::http::Proxy "$APT_PROXY" ; -EOF - fi - - case $2 in - amd64|i386) - MIRROR=${MIRROR:-http://archive.ubuntu.com/ubuntu} - SECURITY_MIRROR=${SECURITY_MIRROR:-http://security.ubuntu.com/ubuntu} - ;; - *) - MIRROR=${MIRROR:-http://ports.ubuntu.com/ubuntu-ports} - SECURITY_MIRROR=${SECURITY_MIRROR:-http://ports.ubuntu.com/ubuntu-ports} - ;; - esac - if [ -n "$3" ]; then - cat >> "$1/etc/apt/sources.list" << EOF -deb [arch=$2] $MIRROR ${release} main restricted universe multiverse -deb [arch=$2] $MIRROR ${release}-updates main restricted universe multiverse -deb [arch=$2] $SECURITY_MIRROR ${release}-security main restricted universe multiverse -EOF - else - cat >> "$1/etc/apt/sources.list" << EOF -deb $MIRROR ${release} main restricted universe multiverse -deb $MIRROR ${release}-updates main restricted universe multiverse -deb $SECURITY_MIRROR ${release}-security main restricted universe multiverse -EOF - fi -} - -install_packages() -{ - local rootfs="$1" - shift - local packages="$*" - if [ -z $update ] - then - chroot $rootfs apt-get update - update=true - fi - if [ -n "${packages}" ] - then - chroot $rootfs apt-get install --force-yes -y --no-install-recommends ${packages} - fi -} - -cleanup() -{ - try_rmsubvolume $cache/partial-$arch - try_rmsubvolume $cache/rootfs-$arch -} - -suggest_flush() -{ - echo "Container upgrade failed. The container cache may be out of date," - echo "in which case flushing the cache (see -F in the help output) may help." -} - -download_ubuntu() -{ - cache=$1 - arch=$2 - release=$3 - - case $2 in - amd64|i386) - MIRROR=${MIRROR:-http://archive.ubuntu.com/ubuntu} - SECURITY_MIRROR=${SECURITY_MIRROR:-http://security.ubuntu.com/ubuntu} - ;; - *) - MIRROR=${MIRROR:-http://ports.ubuntu.com/ubuntu-ports} - SECURITY_MIRROR=${SECURITY_MIRROR:-http://ports.ubuntu.com/ubuntu-ports} - ;; - esac - - packages_template=${packages_template:-"apt-transport-https,ssh,vim"} - debootstrap_parameters= - - # Try to guess a list of langpacks to install - langpacks="language-pack-en" - - if which dpkg >/dev/null 2>&1; then - langpacks=`(echo $langpacks && - dpkg -l | grep -E "^ii language-pack-[a-z]* " | - cut -d ' ' -f3) | sort -u` - fi - packages_template="${packages_template},$(echo $langpacks | sed 's/ /,/g')" - - if [ -n "$variant" ]; then - debootstrap_parameters="$debootstrap_parameters --variant=$variant" - fi - if [ "$variant" = 'minbase' ]; then - packages_template="${packages_template},sudo" - # Newer releases use netplan, EOL releases not supported - case $release in - trusty|xenial|zesty) - packages_template="${packages_template},ifupdown,isc-dhcp-client" - ;; - esac - fi - - echo "Installing packages in template: ${packages_template}" - - trap cleanup EXIT SIGHUP SIGINT SIGTERM - # check the mini ubuntu was not already downloaded - try_mksubvolume "$cache/partial-$arch" - if [ $? -ne 0 ]; then - echo "Failed to create '$cache/partial-$arch' directory" - return 1 - fi - - choose_container_proxy $cache/partial-$arch/ $arch - # download a mini ubuntu into a cache - echo "Downloading ubuntu $release minimal ..." - if [ -n "$(which qemu-debootstrap)" ]; then - qemu-debootstrap --verbose $debootstrap_parameters --components=main,universe --arch=$arch --include=${packages_template} $release $cache/partial-$arch $MIRROR - else - debootstrap --verbose $debootstrap_parameters --components=main,universe --arch=$arch --include=${packages_template} $release $cache/partial-$arch $MIRROR - fi - - if [ $? -ne 0 ]; then - echo "Failed to download the rootfs, aborting." - return 1 - fi - - # Serge isn't sure whether we should avoid doing this when - # $release == `distro-info -d` - echo "Installing updates" - > $cache/partial-$arch/etc/apt/sources.list - write_sourceslist $cache/partial-$arch/ $arch - - chroot "$1/partial-${arch}" apt-get update - if [ $? -ne 0 ]; then - echo "Failed to update the apt cache" - return 1 - fi - cat > "$1/partial-${arch}"/usr/sbin/policy-rc.d << EOF -#!/bin/sh -exit 101 -EOF - chmod +x "$1/partial-${arch}"/usr/sbin/policy-rc.d - - ( - cat << EOF - mount -t proc proc "${1}/partial-${arch}/proc" - chroot "${1}/partial-${arch}" apt-get dist-upgrade -y -EOF - ) | lxc-unshare -s MOUNT -- sh -eu || (suggest_flush; false) - - rm -f "$1/partial-${arch}"/usr/sbin/policy-rc.d - - chroot "$1/partial-${arch}" apt-get clean - - mv "$1/partial-$arch" "$1/rootfs-$arch" - trap EXIT - trap SIGINT - trap SIGTERM - trap SIGHUP - echo "Download complete" - return 0 -} - -copy_ubuntu() -{ - cache=$1 - arch=$2 - rootfs=$3 - - # make a local copy of the miniubuntu - echo "Copying rootfs to $rootfs ..." - try_mksubvolume $rootfs - if which btrfs >/dev/null 2>&1 && is_btrfs_subvolume $cache/rootfs-$arch && is_btrfs_subvolume $rootfs; then - realrootfs=$(dirname $config)/rootfs - [ "$rootfs" = "$realrootfs" ] || umount $rootfs || return 1 - btrfs subvolume delete $realrootfs || return 1 - btrfs subvolume snapshot $cache/rootfs-$arch $realrootfs || return 1 - [ "$rootfs" = "$realrootfs" ] || mount --bind $realrootfs $rootfs || return 1 - else - rsync -SHaAX $cache/rootfs-$arch/ $rootfs/ || return 1 - fi - return 0 -} - -install_ubuntu() -{ - rootfs=$1 - release=$2 - flushcache=$3 - cache="$4/$release" - mkdir -p $LOCALSTATEDIR/lock/subsys/ - - ( - flock -x 9 - if [ $? -ne 0 ]; then - echo "Cache repository is busy." - return 1 - fi - - - if [ $flushcache -eq 1 ]; then - echo "Flushing cache..." - try_rmsubvolume $cache/partial-$arch - try_rmsubvolume $cache/rootfs-$arch - fi - - echo "Checking cache download in $cache/rootfs-$arch ... " - if [ ! -e "$cache/rootfs-$arch" ]; then - download_ubuntu $cache $arch $release - if [ $? -ne 0 ]; then - echo "Failed to download 'ubuntu $release base'" - return 1 - fi - fi - - echo "Copy $cache/rootfs-$arch to $rootfs ... " - copy_ubuntu $cache $arch $rootfs - if [ $? -ne 0 ]; then - echo "Failed to copy rootfs" - return 1 - fi - - return 0 - - ) 9>$LOCALSTATEDIR/lock/subsys/lxc-ubuntu$release - - return $? -} - -copy_configuration() -{ - path=$1 - rootfs=$2 - name=$3 - arch=$4 - release=$5 - - if [ $arch = "i386" ]; then - arch="i686" - fi - - # if there is exactly one veth network entry, make sure it has an - # associated hwaddr. - nics=`grep -e '^lxc\.net\.0\.type[ \t]*=[ \t]*veth' $path/config | wc -l` - if [ $nics -eq 1 ]; then - grep -q "^lxc.net.0.hwaddr" $path/config || sed -i -e "/^lxc\.net\.0\.type[ \t]*=[ \t]*veth/a lxc.net.0.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')" $path/config - fi - - # Generate the configuration file - ## Relocate all the network config entries - sed -i -e "/lxc.net.0/{w ${path}/config-network" -e "d}" $path/config - - ## Relocate any other config entries - sed -i -e "/lxc./{w ${path}/config-auto" -e "d}" $path/config - - ## Add all the includes - echo "" >> $path/config - echo "# Common configuration" >> $path/config - if [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu.common.conf" ]; then - echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu.common.conf" >> $path/config - fi - if [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu.${release}.conf" ]; then - echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu.${release}.conf" >> $path/config - fi - - ## Add the container-specific config - echo "" >> $path/config - echo "# Container specific configuration" >> $path/config - [ -e "$path/config-auto" ] && cat $path/config-auto >> $path/config && rm $path/config-auto - grep -q "^lxc.rootfs.path" $path/config 2>/dev/null || echo "lxc.rootfs.path = $rootfs" >> $path/config - cat <> $path/config -lxc.uts.name = $name -lxc.arch = $arch -EOF - - ## Re-add the previously removed network config - echo "" >> $path/config - echo "# Network configuration" >> $path/config - cat $path/config-network >> $path/config - rm $path/config-network - - if [ $? -ne 0 ]; then - echo "Failed to add configuration" - return 1 - fi - - return 0 -} - -post_process() -{ - rootfs=$1 - release=$2 - packages=$3 - - # 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 [ -x "$(ls -1 ${rootfs}/usr/bin/qemu-*-static 2>/dev/null)" ]; then - dpkg_version=$(chroot $rootfs dpkg-query -W -f='${Version}' dpkg) - if chroot $rootfs dpkg --compare-versions $dpkg_version ge "1.16.2"; then - chroot $rootfs dpkg --add-architecture ${hostarch} - else - mkdir -p ${rootfs}/etc/dpkg/dpkg.cfg.d - echo "foreign-architecture ${hostarch}" > ${rootfs}/etc/dpkg/dpkg.cfg.d/lxc-multiarch - fi - - # Save existing value of MIRROR and SECURITY_MIRROR - DEFAULT_MIRROR=$MIRROR - DEFAULT_SECURITY_MIRROR=$SECURITY_MIRROR - - # Write a new sources.list containing both native and multiarch entries - > ${rootfs}/etc/apt/sources.list - write_sourceslist $rootfs $arch "native" - - MIRROR=$DEFAULT_MIRROR - SECURITY_MIRROR=$DEFAULT_SECURITY_MIRROR - write_sourceslist $rootfs $hostarch "multiarch" - - # Finally update the lists and install upstart using the host architecture - HOST_PACKAGES="upstart:${hostarch} mountall:${hostarch} isc-dhcp-client:${hostarch}" - chroot $rootfs apt-get update - if chroot $rootfs dpkg -l iproute2 | grep -q ^ii; then - HOST_PACKAGES="$HOST_PACKAGES iproute2:${hostarch}" - else - HOST_PACKAGES="$HOST_PACKAGES iproute:${hostarch}" - fi - install_packages $rootfs $HOST_PACKAGES - fi - - # Install Packages in container - if [ -n "$packages" ] - then - local packages="`echo $packages | sed 's/,/ /g'`" - echo "Installing packages: ${packages}" - install_packages $rootfs $packages - fi - - # Set initial timezone as on host - if [ -f /etc/timezone ]; then - cat /etc/timezone > $rootfs/etc/timezone - chroot $rootfs dpkg-reconfigure -f noninteractive tzdata - elif [ -f /etc/sysconfig/clock ]; then - . /etc/sysconfig/clock - echo $ZONE > $rootfs/etc/timezone - chroot $rootfs dpkg-reconfigure -f noninteractive tzdata - else - echo "Timezone in container is not configured. Adjust it manually." - fi - - # rmdir /dev/shm for containers that have /run/shm - # I'm afraid of doing rm -rf $rootfs/dev/shm, in case it did - # get bind mounted to the host's /run/shm. So try to rmdir - # it, and in case that fails move it out of the way. - # NOTE: This can only be removed once 12.04 goes out of support - if [ ! -L $rootfs/dev/shm ] && [ -e $rootfs/dev/shm ]; then - rmdir $rootfs/dev/shm 2>/dev/null || mv $rootfs/dev/shm $rootfs/dev/shm.bak - ln -s /run/shm $rootfs/dev/shm - fi - - # Re-enable service startup - rm $rootfs/usr/sbin/policy-rc.d -} - -do_bindhome() -{ - rootfs=$1 - user=$2 - - # copy /etc/passwd, /etc/shadow, and /etc/group entries into container - pwd=`getent passwd $user` || { echo "Failed to copy password entry for $user"; false; } - echo $pwd >> $rootfs/etc/passwd - - # make sure user's shell exists in the container - shell=`echo $pwd | cut -d: -f 7` - if [ ! -x $rootfs/$shell ]; then - echo "shell $shell for user $user was not found in the container." - pkg=`dpkg -S $(readlink -m $shell) | cut -d ':' -f1` - echo "Installing $pkg" - install_packages $rootfs $pkg - fi - - shad=`getent shadow $user` - echo "$shad" >> $rootfs/etc/shadow - - # bind-mount the user's path into the container's /home - h=`getent passwd $user | cut -d: -f 6` - mkdir -p $rootfs/$h - - # use relative path in container - h2=${h#/} - while [ ${h2:0:1} = "/" ]; do - h2=${h2#/} - done - echo "lxc.mount.entry = $h $h2 none bind 0 0" >> $path/config - - # Make sure the group exists in container - grp=`echo $pwd | cut -d: -f 4` # group number for $user - grpe=`getent group $grp` || return 0 # if host doesn't define grp, ignore in container - chroot $rootfs getent group "$grpe" || echo "$grpe" >> $rootfs/etc/group -} - -usage() -{ - cat <] [-d|--debug] - [-F | --flush-cache] [-r|--release ] [-v|--variant] [ -S | --auth-key ] - [--rootfs ] [--packages ] [-u|--user ] [--password ] - [--mirror ] [--security-mirror ] -release: the ubuntu release (e.g. xenial): defaults to host release on ubuntu, otherwise uses latest LTS -variant: debootstrap variant to use (see debootstrap(8)) -bindhome: bind 's home into the container - The ubuntu user will not be created, and will have - sudo access. -arch: the container architecture (e.g. amd64): defaults to host arch -auth-key: SSH Public key file to inject into container -packages: list of packages to add comma separated -mirror,security-mirror: mirror for download and /etc/apt/sources.list -EOF - return 0 -} - -options=$(getopt -o a:b:hp:r:v:n:FS:du: -l arch:,bindhome:,help,path:,release:,variant:,name:,flush-cache,auth-key:,debug,rootfs:,packages:,user:,password:,mirror:,security-mirror: -- "$@") -if [ $? -ne 0 ]; then - usage $(basename $0) - exit 1 -fi -eval set -- "$options" - -release=xenial # Default to the last Ubuntu LTS release for non-Ubuntu systems -if [ -f /etc/lsb-release ]; then - . /etc/lsb-release - if [ "$DISTRIB_ID" = "Ubuntu" ]; then - release=$DISTRIB_CODENAME - fi -fi - -bindhome= - -# Code taken from debootstrap -if [ -x /usr/bin/dpkg ] && /usr/bin/dpkg --print-architecture >/dev/null 2>&1; then - arch=`/usr/bin/dpkg --print-architecture` -elif which udpkg >/dev/null 2>&1 && udpkg --print-architecture >/dev/null 2>&1; then - arch=`/usr/bin/udpkg --print-architecture` -else - arch=$(uname -m) - if [ "$arch" = "i686" ]; then - arch="i386" - elif [ "$arch" = "x86_64" ]; then - arch="amd64" - elif [ "$arch" = "armv7l" ]; then - arch="armhf" - elif [ "$arch" = "aarch64" ]; then - arch="arm64" - elif [ "$arch" = "ppc64le" ]; then - arch="ppc64el" - fi -fi - -debug=0 -hostarch=$arch -flushcache=0 -packages="" -user="ubuntu" -password="ubuntu" - -while true -do - case "$1" in - -h|--help) usage $0 && exit 0;; - --rootfs) rootfs=$2; shift 2;; - -p|--path) path=$2; shift 2;; - -n|--name) name=$2; shift 2;; - -u|--user) user=$2; shift 2;; - --password) password=$2; shift 2;; - -F|--flush-cache) flushcache=1; shift 1;; - -r|--release) release=$2; shift 2;; - -v|--variant) variant=$2; shift 2;; - --packages) packages=$2; shift 2;; - -b|--bindhome) bindhome=$2; shift 2;; - -a|--arch) arch=$2; shift 2;; - -S|--auth-key) auth_key=$2; shift 2;; - -d|--debug) debug=1; shift 1;; - --mirror) MIRROR=$2; shift 2;; - --security-mirror) SECURITY_MIRROR=$2; shift 2;; - --) shift 1; break ;; - *) break ;; - esac -done - -if [ $debug -eq 1 ]; then - set -x -fi - -if [ -n "$bindhome" ]; then - pwd=`getent passwd $bindhome` - if [ $? -ne 0 ]; then - echo "Error: no password entry found for $bindhome" - exit 1 - fi -fi - - -if [ "$arch" = "i686" ]; then - arch=i386 -fi - -if [ $hostarch = "i386" -a $arch = "amd64" ]; then - echo "can't create $arch container on $hostarch" - exit 1 -fi - -if [ $hostarch = "armhf" -o $hostarch = "armel" -o $hostarch = "arm64" ] && \ - [ $arch != "armhf" -a $arch != "armel" -a $arch != "arm64" ]; then - echo "can't create $arch container on $hostarch" - exit 1 -fi - -if [ $arch = "arm64" ] && [ $hostarch != "arm64" ]; then - echo "can't create $arch container on $hostarch" - exit 1 -fi - -if [ $hostarch = "powerpc" -a $arch != "powerpc" ]; then - echo "can't create $arch container on $hostarch" - exit 1 -fi - -which debootstrap >/dev/null 2>&1 || { echo "'debootstrap' command is missing" >&2; false; } - -if [ -z "$path" ]; then - echo "'path' parameter is required" - exit 1 -fi - -if [ "$(id -u)" != "0" ]; then - echo "This script should be run as 'root'" - exit 1 -fi - -# detect rootfs -config="$path/config" -# if $rootfs exists here, it was passed in with --rootfs -if [ -z "$rootfs" ]; then - if grep -q '^lxc.rootfs.path' $config 2>/dev/null ; then - rootfs=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $config) - else - rootfs=$path/rootfs - fi -fi - -install_ubuntu $rootfs $release $flushcache $LXC_CACHE_PATH -if [ $? -ne 0 ]; then - echo "failed to install ubuntu $release" - exit 1 -fi - -configure_ubuntu $rootfs $name $release $user $password -if [ $? -ne 0 ]; then - echo "failed to configure ubuntu $release for a container" - exit 1 -fi - -copy_configuration $path $rootfs $name $arch $release -if [ $? -ne 0 ]; then - echo "failed write configuration file" - exit 1 -fi - -post_process $rootfs $release $trim_container $packages - -if [ -n "$bindhome" ]; then - do_bindhome $rootfs $bindhome - finalize_user $bindhome -else - finalize_user $user -fi - -echo "" -echo "##" -if [ -n "$bindhome" ]; then - echo "# Log in as user $bindhome" -else - echo "# The default user is '$user' with password '$password'!" - echo "# Use the 'sudo' command to run tasks as root in the container." -fi -echo "##" -echo "" diff --git a/templates/lxc-voidlinux.in b/templates/lxc-voidlinux.in deleted file mode 100644 index d74da385a..000000000 --- a/templates/lxc-voidlinux.in +++ /dev/null @@ -1,199 +0,0 @@ -#!/bin/bash - -# -# template script for generating Void Linux container for LXC -# - -# -# lxc: linux Container library - -# Authors: -# Gregor Reitzenstein - -# Based on lxc-archlinux template by: -# Alexander Vladimirov -# John Lane - -# 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 - -# Utility functions - -# Check if array $2 contains item $1 -containsElement() { - local e - for e in "${@:2}"; do [[ "$1" == "$e" ]] && return 0; done - return 1 -} - -# split comma-separated string into an array -# ${1} - string to split -# ${2} - separator (default is ",") -# ${result} - result value on success -split_string() { - local ifs=${IFS} - IFS="${2:-,}" - read -ra result < <(echo "${1}") - IFS=${ifs} - return 0 -} - -# Make sure the usual locations are in PATH -export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin - -# defaults -default_path="/var/lib/lxc" -default_path="@LXCPATH@" -shared_config="@LXCTEMPLATECONFIG@/voidlinux.common.conf" -userns_config="@LXCTEMPLATECONFIG@/voidlinux.userns.conf" - -pkg_blacklist=("linux>=0" "e2fsprogs>=0" "btrfs-progs>=0" "xfsprogs>=0" "f2fs-tools>=0" "dosfstools>=0") -base_packages=() -for pkg in $(xbps-query -Mv --repository="http://repo2.voidlinux.eu/current/" -x base-system); do - containsElement "$pkg" "${pkg_blacklist[@]}" || base_packages+=($pkg) -done -declare -a additional_packages - -copy_configuration() { - mkdir -p "${config_path}" - local config="${config_path}/config" - echo "lxc.uts.name = ${name}" >> "${config}" - grep -q "^lxc.rootfs.path" "${config}" 2>/dev/null \ - || echo "lxc.rootfs.path = ${rootfs_path}" >> "${config}" - - # Detect if were in a UserNS and include the right config - if [ -z "${LXC_MAPPED_GID+x}" ] || [ -z "${LXC_MAPPED_UID+x}" ]; then - echo "lxc.include = ${userns_config}" >> "${config}" - else - echo "lxc.include = ${shared_config}" >> "${config}" - fi - - if [ $? -ne 0 ]; then - echo "Failed to configure container" - return 1 - fi - return 0 -} - -install_void() { - if ! yes | xbps-install -Sy -R http://repo2.voidlinux.eu/current -r "${rootfs_path}" "${base_packages[@]}" - then - echo "Failed to install container packages" - return 1 - fi -} - -usage() { - cat < [-p|--path=] [-a|--arch=] - [-r|--root_password=] [-P|--packages=] [-h|--help] - -Mandatory args: - -n,--name container name, used to as an identifier for that container from now on -Optional args: - -p,--path path to where the container rootfs will be created (${default_path}) - --rootfs path for actual container rootfs, (${default_path}/rootfs) - -P,--packages preinstall additional packages, comma-separated list - -c,--config use specified pacman config when installing container packages - -a,--arch use specified architecture instead of host's architecture - -r,--root_password set container root password - -h,--help print this help -EOF - return 0 -} - -options=$(getopt -o hp:P:n:c:r: -l help,rootfs:,path:,packages:,name:,config:,root_password:,mapped-uid:,mapped-gid: -- "${@}") -if [ ${?} -ne 0 ]; then - usage "$(basename "${0}")" - exit 1 -fi -eval set -- "${options}" - -while true -do - case "${1}" in - -h|--help) usage "${0}" && exit 0;; - -p|--path) path=${2}; shift 2;; - -n|--name) name=${2}; shift 2;; - -c|--config) config_path=${2}; shift 2;; - --rootfs) rootfs_path=${2}; shift 2;; - -P|--packages) additional_packages=${2}; shift 2;; - -r|--root_password) root_passwd=${2}; shift 2;; - --mapped-uid) LXC_MAPPED_UID=$2; shift 2;; - --mapped-gid) LXC_MAPPED_GID=$2; shift 2;; - --) shift 1; break ;; - *) break ;; - esac -done - -if [ -z "${name}" ]; then - echo "missing required 'name' parameter" - exit 1 -fi - -type xbps-install >/dev/null 2>&1 -if [ ${?} -ne 0 ]; then - echo "'xbps-install' command is missing." -fi -type xbps-query >/dev/null 2>&1 -if [ ${?} -ne 0 ]; then - echo "'xbps-query' command is missing." -fi - -if [ -z "${rootfs_path}" ]; then - rootfs_path="${path}/rootfs" -fi -config_path="${path}" - -revert() { - echo "Interrupted, cleaning up" - lxc-destroy -n "${name}" - rm -rf "${path:?}/${name}" - rm -rf "${default_path:?}/${name}" - exit 1 -} -trap revert SIGHUP SIGINT SIGTERM - -copy_configuration -if [ $? -ne 0 ]; then - echo "Failed to write configuration file" - rm -rf "${config_path}" - exit 1 -fi - -if [ ${#additional_packages[@]} -gt 0 ]; then - split_string "${additional_packages}" - base_packages+=(${result[@]}) -fi - -mkdir -p "${rootfs_path}" -install_void -if [ ${?} -ne 0 ]; then - echo "Failed to install Void Linux" - rm -rf "${config_path}" "${path}" - exit 1 -fi - - - -if [ -n "${root_passwd}" ]; then - echo "root:${root_passwd}" | chroot "${rootfs_path}" chpasswd -fi - -cat << EOF -Void Linux Container ${name} has been successfully created. The configuration is -stored in ${config_path}/config. Please refer to https://wiki.voidlinux.eu for -information regarding Void Linux. -EOF From b80f86f2b54bffd20fa9e9ab554317bc35f2b8b4 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Tue, 27 Feb 2018 01:28:45 +0100 Subject: [PATCH 07/12] templates: bump compat level to 5 Signed-off-by: Christian Brauner --- templates/lxc-download.in | 2 +- templates/lxc-local.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/lxc-download.in b/templates/lxc-download.in index 5f3fe638a..b0d5c6a1b 100644 --- a/templates/lxc-download.in +++ b/templates/lxc-download.in @@ -28,7 +28,7 @@ LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@" # Defaults DOWNLOAD_ARCH= DOWNLOAD_BUILD= -DOWNLOAD_COMPAT_LEVEL=4 +DOWNLOAD_COMPAT_LEVEL=5 DOWNLOAD_DIST= DOWNLOAD_FLUSH_CACHE="false" DOWNLOAD_FORCE_CACHE="false" diff --git a/templates/lxc-local.in b/templates/lxc-local.in index 6c6caf814..baea28043 100644 --- a/templates/lxc-local.in +++ b/templates/lxc-local.in @@ -30,7 +30,7 @@ LXC_PATH= LXC_ROOTFS= LXC_CONFIG= MODE="system" -COMPAT_LEVEL=4 +COMPAT_LEVEL=5 # Make sure the usual locations are in PATH export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin From 832cb1824ac2612f2de0ea37084ce157e1ea15a4 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Tue, 27 Feb 2018 10:47:34 +0100 Subject: [PATCH 08/12] lxc-download: make POSIX shellcheck clean Signed-off-by: Christian Brauner --- templates/lxc-download.in | 671 +++++++++++++++++++------------------- 1 file changed, 331 insertions(+), 340 deletions(-) diff --git a/templates/lxc-download.in b/templates/lxc-download.in index b0d5c6a1b..f87518359 100644 --- a/templates/lxc-download.in +++ b/templates/lxc-download.in @@ -55,12 +55,12 @@ LXC_PATH= LXC_ROOTFS= if [ -z "${DOWNLOAD_KEYSERVER:-}" ]; then - DOWNLOAD_KEYSERVER="hkp://pool.sks-keyservers.net" + DOWNLOAD_KEYSERVER="hkp://pool.sks-keyservers.net" - # Deal with GPG over http proxy - if [ -n "${http_proxy:-}" ]; then - DOWNLOAD_KEYSERVER="hkp://p80.pool.sks-keyservers.net:80" - fi + # Deal with GPG over http proxy + if [ -n "${http_proxy:-}" ]; then + DOWNLOAD_KEYSERVER="hkp://p80.pool.sks-keyservers.net:80" + fi fi # Make sure the usual locations are in PATH @@ -68,140 +68,141 @@ export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin # Some useful functions cleanup() { - if [ -d "${DOWNLOAD_TEMP}" ]; then - rm -Rf "${DOWNLOAD_TEMP}" - fi + if [ -d "${DOWNLOAD_TEMP}" ]; then + rm -Rf "${DOWNLOAD_TEMP}" + fi } wget_wrapper() { - for i in $(seq 3); do - if wget "$@"; then - return 0 - fi - done + for _ in $(seq 3); do + if wget "$@"; then + return 0 + fi + done - return 1 + return 1 } download_file() { - if ! wget_wrapper -T 30 -q "https://${DOWNLOAD_SERVER}/$1" -O "$2" >/dev/null 2>&1; then - if ! wget_wrapper -T 30 -q "http://${DOWNLOAD_SERVER}/$1" -O "$2" >/dev/null 2>&1; then - if [ "$3" = "noexit" ]; then - return 1 - else - echo "ERROR: Failed to download http://${DOWNLOAD_SERVER}/$1" 1>&2 - exit 1 - fi - elif [ "${DOWNLOAD_SHOW_HTTP_WARNING}" = "true" ]; then - DOWNLOAD_SHOW_HTTP_WARNING="false" - echo "WARNING: Failed to download the file over HTTPs." 1>&2 - echo " The file was instead download over HTTP. " 1>&2 - echo "A server replay attack may be possible!" 1>&2 - fi + if ! wget_wrapper -T 30 -q "https://${DOWNLOAD_SERVER}/$1" -O "$2" >/dev/null 2>&1; then + if ! wget_wrapper -T 30 -q "http://${DOWNLOAD_SERVER}/$1" -O "$2" >/dev/null 2>&1; then + if [ "$3" = "noexit" ]; then + return 1 + else + echo "ERROR: Failed to download http://${DOWNLOAD_SERVER}/$1" 1>&2 + exit 1 + fi + elif [ "${DOWNLOAD_SHOW_HTTP_WARNING}" = "true" ]; then + DOWNLOAD_SHOW_HTTP_WARNING="false" + echo "WARNING: Failed to download the file over HTTPs" 1>&2 + echo " The file was instead download over HTTP " 1>&2 + echo "A server replay attack may be possible!" 1>&2 fi + fi } download_sig() { - if ! download_file "$1" "$2" noexit; then - if [ "${DOWNLOAD_VALIDATE}" = "true" ]; then - if [ "$3" = "normal" ]; then - echo "ERROR: Failed to download http://${DOWNLOAD_SERVER}/$1" 1>&2 - exit 1 - else - return 1 - fi - else - return 0 - fi + if ! download_file "$1" "$2" noexit; then + if [ "${DOWNLOAD_VALIDATE}" = "true" ]; then + if [ "$3" = "normal" ]; then + echo "ERROR: Failed to download http://${DOWNLOAD_SERVER}/$1" 1>&2 + exit 1 + else + return 1 + fi + else + return 0 fi + fi } gpg_setup() { - if [ "${DOWNLOAD_VALIDATE}" = "false" ]; then - return + if [ "${DOWNLOAD_VALIDATE}" = "false" ]; then + return + fi + + if [ "${DOWNLOAD_READY_GPG}" = "true" ]; then + return + fi + + echo "Setting up the GPG keyring" + + mkdir -p "${DOWNLOAD_TEMP}/gpg" + chmod 700 "${DOWNLOAD_TEMP}/gpg" + export GNUPGHOME="${DOWNLOAD_TEMP}/gpg" + + success= + for _ in $(seq 3); do + if gpg --keyserver "${DOWNLOAD_KEYSERVER}" \ + --recv-keys "${DOWNLOAD_KEYID}" >/dev/null 2>&1; then + success=1 + break fi + break + done - if [ "${DOWNLOAD_READY_GPG}" = "true" ]; then - return - fi + if [ -z "${success}" ]; then + echo "ERROR: Unable to fetch GPG key from keyserver" + exit 1 + fi - echo "Setting up the GPG keyring" - - mkdir -p "${DOWNLOAD_TEMP}/gpg" - chmod 700 "${DOWNLOAD_TEMP}/gpg" - export GNUPGHOME="${DOWNLOAD_TEMP}/gpg" - - success= - for i in $(seq 3); do - if gpg --keyserver "${DOWNLOAD_KEYSERVER}" \ - --recv-keys "${DOWNLOAD_KEYID}" >/dev/null 2>&1; then - success=1 - break - fi - break - done - - if [ -z "${success}" ]; then - echo "ERROR: Unable to fetch GPG key from keyserver." - exit 1 - fi - - DOWNLOAD_READY_GPG="true" + DOWNLOAD_READY_GPG="true" } gpg_validate() { - if [ "${DOWNLOAD_VALIDATE}" = "false" ]; then - if [ "${DOWNLOAD_SHOW_GPG_WARNING}" = "true" ]; then - echo "WARNING: Running without gpg validation!" 1>&2 - fi - DOWNLOAD_SHOW_GPG_WARNING="false" - return 0 + if [ "${DOWNLOAD_VALIDATE}" = "false" ]; then + if [ "${DOWNLOAD_SHOW_GPG_WARNING}" = "true" ]; then + echo "WARNING: Running without gpg validation!" 1>&2 fi + DOWNLOAD_SHOW_GPG_WARNING="false" + return 0 + fi - if ! gpg --verify "$1" >/dev/null 2>&1; then - echo "ERROR: Invalid signature for $1" 1>&2 - exit 1 - fi + if ! gpg --verify "$1" >/dev/null 2>&1; then + echo "ERROR: Invalid signature for $1" 1>&2 + exit 1 + fi } in_userns() { - [ -e /proc/self/uid_map ] || { echo no; return; } - while read -r line; do - fields="$(echo "$line" | awk '{ print $1 " " $2 " " $3 }')" - if [ "${fields}" = "0 0 4294967295" ]; then - echo no; - return; - fi - if echo "${fields}" | grep -q " 0 1$"; then - echo userns-root; - return; - fi - done < /proc/self/uid_map + [ -e /proc/self/uid_map ] || { echo no; return; } + while read -r line; do + fields="$(echo "$line" | awk '{ print $1 " " $2 " " $3 }')" + if [ "${fields}" = "0 0 4294967295" ]; then + echo no; + return; + fi + if echo "${fields}" | grep -q " 0 1$"; then + echo userns-root; + return; + fi + done < /proc/self/uid_map - [ "$(cat /proc/self/uid_map)" = "$(cat /proc/1/uid_map)" ] && \ - { echo userns-root; return; } - echo yes + [ "$(cat /proc/self/uid_map)" = "$(cat /proc/1/uid_map)" ] && { echo userns-root; return; } + echo yes } relevant_file() { - FILE_PATH="${LXC_CACHE_PATH}/$1" - if [ -e "${FILE_PATH}-${DOWNLOAD_MODE}" ]; then - FILE_PATH="${FILE_PATH}-${DOWNLOAD_MODE}" - fi - if [ -e "${FILE_PATH}.${DOWNLOAD_COMPAT_LEVEL}" ]; then - FILE_PATH="${FILE_PATH}.${DOWNLOAD_COMPAT_LEVEL}" - fi + FILE_PATH="${LXC_CACHE_PATH}/$1" - echo "${FILE_PATH}" + if [ -e "${FILE_PATH}-${DOWNLOAD_MODE}" ]; then + FILE_PATH="${FILE_PATH}-${DOWNLOAD_MODE}" + fi + + if [ -e "${FILE_PATH}.${DOWNLOAD_COMPAT_LEVEL}" ]; then + FILE_PATH="${FILE_PATH}.${DOWNLOAD_COMPAT_LEVEL}" + fi + + echo "${FILE_PATH}" } usage() { - cat < ]: The name of the distribution @@ -229,84 +230,83 @@ DOWNLOAD_KEYSERVER : The URL of the key server to use, instead of the default. Can be further overridden by using optional argument --keyserver EOF - return 0 + return 0 } if ! options=$(getopt -o d:r:a:hl -l dist:,release:,arch:,help,list,variant:,\ server:,keyid:,keyserver:,no-validate,flush-cache,force-cache,name:,path:,\ rootfs:,mapped-uid:,mapped-gid: -- "$@"); then - usage - exit 1 + usage + exit 1 fi eval set -- "$options" while :; do - case "$1" in - -h|--help) usage && exit 1;; - -l|--list) DOWNLOAD_LIST_IMAGES="true"; shift 1;; - -d|--dist) DOWNLOAD_DIST="$2"; shift 2;; - -r|--release) DOWNLOAD_RELEASE="$2"; shift 2;; - -a|--arch) DOWNLOAD_ARCH="$2"; shift 2;; - --variant) DOWNLOAD_VARIANT="$2"; shift 2;; - --server) DOWNLOAD_SERVER="$2"; shift 2;; - --keyid) DOWNLOAD_KEYID="$2"; shift 2;; - --keyserver) DOWNLOAD_KEYSERVER="$2"; shift 2;; - --no-validate) DOWNLOAD_VALIDATE="false"; shift 1;; - --flush-cache) DOWNLOAD_FLUSH_CACHE="true"; shift 1;; - --force-cache) DOWNLOAD_FORCE_CACHE="true"; shift 1;; - --name) LXC_NAME="$2"; shift 2;; - --path) LXC_PATH="$2"; shift 2;; - --rootfs) LXC_ROOTFS="$2"; shift 2;; - --mapped-uid) LXC_MAPPED_UID="$2"; shift 2;; - --mapped-gid) LXC_MAPPED_GID="$2"; shift 2;; - *) break;; - esac + case "$1" in + -h|--help) usage && exit 1;; + -l|--list) DOWNLOAD_LIST_IMAGES="true"; shift 1;; + -d|--dist) DOWNLOAD_DIST="$2"; shift 2;; + -r|--release) DOWNLOAD_RELEASE="$2"; shift 2;; + -a|--arch) DOWNLOAD_ARCH="$2"; shift 2;; + --variant) DOWNLOAD_VARIANT="$2"; shift 2;; + --server) DOWNLOAD_SERVER="$2"; shift 2;; + --keyid) DOWNLOAD_KEYID="$2"; shift 2;; + --keyserver) DOWNLOAD_KEYSERVER="$2"; shift 2;; + --no-validate) DOWNLOAD_VALIDATE="false"; shift 1;; + --flush-cache) DOWNLOAD_FLUSH_CACHE="true"; shift 1;; + --force-cache) DOWNLOAD_FORCE_CACHE="true"; shift 1;; + --name) LXC_NAME="$2"; shift 2;; + --path) LXC_PATH="$2"; shift 2;; + --rootfs) LXC_ROOTFS="$2"; shift 2;; + --mapped-uid) LXC_MAPPED_UID="$2"; shift 2;; + --mapped-gid) LXC_MAPPED_GID="$2"; shift 2;; + *) break;; + esac done # Check for required binaries for bin in tar xz wget; do - if ! command -V "${bin}" >/dev/null 2>&1; then - echo "ERROR: Missing required tool: ${bin}" 1>&2 - exit 1 - fi + if ! command -V "${bin}" >/dev/null 2>&1; then + echo "ERROR: Missing required tool: ${bin}" 1>&2 + exit 1 + fi done # Check for GPG if [ "${DOWNLOAD_VALIDATE}" = "true" ]; then - if ! command -V gpg >/dev/null 2>&1; then - echo "ERROR: Missing recommended tool: gpg" 1>&2 - echo "You can workaround this by using --no-validate." 1>&2 - exit 1 - fi + if ! command -V gpg >/dev/null 2>&1; then + echo "ERROR: Missing recommended tool: gpg" 1>&2 + echo "You can workaround this by using --no-validate" 1>&2 + exit 1 + fi fi # Check that we have all variables we need if [ -z "${LXC_NAME}" ] || [ -z "${LXC_PATH}" ] || [ -z "${LXC_ROOTFS}" ]; then - if [ "${DOWNLOAD_LIST_IMAGES}" != "true" ]; then - echo "ERROR: Not running through LXC." 1>&2 - exit 1 - fi + if [ "${DOWNLOAD_LIST_IMAGES}" != "true" ]; then + echo "ERROR: Please pass the name, path, and rootfs for the container" 1>&2 + exit 1 + fi fi USERNS="$(in_userns)" if [ "${USERNS}" != "no" ]; then - if [ "${USERNS}" = "yes" ]; then - if [ -z "${LXC_MAPPED_UID}" ] || [ "${LXC_MAPPED_UID}" = "-1" ]; then - echo "ERROR: In a user namespace without a map." 1>&2 - exit 1 - fi - DOWNLOAD_MODE="user" - DOWNLOAD_TARGET="user" - else - DOWNLOAD_MODE="user" - DOWNLOAD_TARGET="system" + if [ "${USERNS}" = "yes" ]; then + if [ -z "${LXC_MAPPED_UID}" ] || [ "${LXC_MAPPED_UID}" = "-1" ]; then + echo "ERROR: In a user namespace without a map" 1>&2 + exit 1 fi + DOWNLOAD_MODE="user" + DOWNLOAD_TARGET="user" + else + DOWNLOAD_MODE="user" + DOWNLOAD_TARGET="system" + fi fi -if [ -z "${DOWNLOAD_DIST}" ] || [ -z "${DOWNLOAD_RELEASE}" ] || \ - [ -z "${DOWNLOAD_ARCH}" ]; then - DOWNLOAD_INTERACTIVE="true" +if [ -z "${DOWNLOAD_DIST}" ] || [ -z "${DOWNLOAD_RELEASE}" ] || [ -z "${DOWNLOAD_ARCH}" ]; then + DOWNLOAD_INTERACTIVE="true" fi # Trap all exit signals @@ -314,84 +314,79 @@ trap cleanup EXIT HUP INT TERM # /tmp may be mounted in tmpfs or noexec if mountpoint -q /tmp; then - DOWNLOAD_TEMP="${LXC_PATH}" + DOWNLOAD_TEMP="${LXC_PATH}" fi if ! command -V mktemp >/dev/null 2>&1; then - DOWNLOAD_TEMP="${DOWNLOAD_TEMP}/tmp/lxc-download.$$" + DOWNLOAD_TEMP="${DOWNLOAD_TEMP}/tmp/lxc-download.$$" else - DOWNLOAD_TEMP="${DOWNLOAD_TEMP}$(mktemp -d)" + DOWNLOAD_TEMP="${DOWNLOAD_TEMP}$(mktemp -d)" fi # Simply list images -if [ "${DOWNLOAD_LIST_IMAGES}" = "true" ] || \ - [ "${DOWNLOAD_INTERACTIVE}" = "true" ]; then - # Initialize GPG - gpg_setup +if [ "${DOWNLOAD_LIST_IMAGES}" = "true" ] || [ "${DOWNLOAD_INTERACTIVE}" = "true" ]; then + # Initialize GPG + gpg_setup - # Grab the index - DOWNLOAD_INDEX_PATH="/meta/1.0/index-${DOWNLOAD_MODE}" + # Grab the index + DOWNLOAD_INDEX_PATH="/meta/1.0/index-${DOWNLOAD_MODE}" - echo "Downloading the image index" - if ! download_file "${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL}" \ - "${DOWNLOAD_TEMP}/index" noexit || - ! download_sig "${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL}.asc" \ - "${DOWNLOAD_TEMP}/index.asc" noexit; then - download_file "${DOWNLOAD_INDEX_PATH}" "${DOWNLOAD_TEMP}/index" normal - download_sig "${DOWNLOAD_INDEX_PATH}.asc" \ - "${DOWNLOAD_TEMP}/index.asc" normal - fi + echo "Downloading the image index" + if ! download_file "${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL}" "${DOWNLOAD_TEMP}/index" noexit || + ! download_sig "${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL}.asc" "${DOWNLOAD_TEMP}/index.asc" noexit; then + download_file "${DOWNLOAD_INDEX_PATH}" "${DOWNLOAD_TEMP}/index" normal + download_sig "${DOWNLOAD_INDEX_PATH}.asc" "${DOWNLOAD_TEMP}/index.asc" normal + fi - gpg_validate "${DOWNLOAD_TEMP}/index.asc" + gpg_validate "${DOWNLOAD_TEMP}/index.asc" - # Parse it - echo "" - echo "---" - printf "DIST\tRELEASE\tARCH\tVARIANT\tBUILD\n" - echo "---" - while IFS=';' read -r f1 f2 f3 f4 f5 f6; do + # Parse it + echo "" + echo "---" + printf "DIST\tRELEASE\tARCH\tVARIANT\tBUILD\n" + echo "---" + while IFS=';' read -r f1 f2 f3 f4 f5 f6; do + [ -n "${DOWNLOAD_DIST}" ] && [ "$f1" != "${DOWNLOAD_DIST}" ] && continue + [ -n "${DOWNLOAD_RELEASE}" ] && [ "$f2" != "${DOWNLOAD_RELEASE}" ] && continue + [ -n "${DOWNLOAD_ARCH}" ] && [ "$f3" != "${DOWNLOAD_ARCH}" ] && continue + [ -n "${DOWNLOAD_VARIANT}" ] && [ "$f4" != "${DOWNLOAD_VARIANT}" ] && continue + [ -z "${f5}" ] || [ -z "${f6}" ] && continue - [ -n "${DOWNLOAD_DIST}" ] && [ "$f1" != "${DOWNLOAD_DIST}" ] && continue - [ -n "${DOWNLOAD_RELEASE}" ] && [ "$f2" != "${DOWNLOAD_RELEASE}" ] && continue - [ -n "${DOWNLOAD_ARCH}" ] && [ "$f3" != "${DOWNLOAD_ARCH}" ] && continue - [ -n "${DOWNLOAD_VARIANT}" ] && [ "$f4" != "${DOWNLOAD_VARIANT}" ] && continue - [ -z "${f5}" ] || [ -z "${f6}" ] && continue + printf "%s\t%s\t%s\t%s\t%s\n" "${f1}" "${f2}" "${f3}" "${f4}" "${f5}" + unset f1 f2 f3 f4 f5 f6 + done < "${DOWNLOAD_TEMP}/index" + echo "---" - printf "%s\t%s\t%s\t%s\t%s\n" "${f1}" "${f2}" "${f3}" "${f4}" "${f5}" - unset f1 f2 f3 f4 f5 f6 - done < "${DOWNLOAD_TEMP}/index" - echo "---" + if [ "${DOWNLOAD_LIST_IMAGES}" = "true" ]; then + exit 1 + fi - if [ "${DOWNLOAD_LIST_IMAGES}" = "true" ]; then - exit 1 - fi + # Interactive mode + echo "" - # Interactive mode - echo "" + if [ -z "${DOWNLOAD_DIST}" ]; then + echo "Distribution: " + read -r DOWNLOAD_DIST + fi - if [ -z "${DOWNLOAD_DIST}" ]; then - echo "Distribution: " - read -r DOWNLOAD_DIST - fi + if [ -z "${DOWNLOAD_RELEASE}" ]; then + echo "Release: " + read -r DOWNLOAD_RELEASE + fi - if [ -z "${DOWNLOAD_RELEASE}" ]; then - echo "Release: " - read -r DOWNLOAD_RELEASE - fi + if [ -z "${DOWNLOAD_ARCH}" ]; then + echo "Architecture: " + read -r DOWNLOAD_ARCH + fi - if [ -z "${DOWNLOAD_ARCH}" ]; then - echo "Architecture: " - read -r DOWNLOAD_ARCH - fi - - echo "" + echo "" fi # Setup the cache if [ "${DOWNLOAD_TARGET}" = "system" ]; then - LXC_CACHE_BASE="${LOCALSTATEDIR}/cache/lxc/" + LXC_CACHE_BASE="${LOCALSTATEDIR}/cache/lxc/" else - LXC_CACHE_BASE="${HOME}/.cache/lxc/" + LXC_CACHE_BASE="${HOME}/.cache/lxc/" fi # Allow the setting of the LXC_CACHE_PATH with the usage of environment variables. @@ -401,110 +396,102 @@ LXC_CACHE_PATH="${LXC_CACHE_PATH}/${DOWNLOAD_RELEASE}/${DOWNLOAD_ARCH}/" LXC_CACHE_PATH="${LXC_CACHE_PATH}/${DOWNLOAD_VARIANT}" if [ -d "${LXC_CACHE_PATH}" ]; then - if [ "${DOWNLOAD_FLUSH_CACHE}" = "true" ]; then - echo "Flushing the cache..." - rm -Rf "${LXC_CACHE_PATH}" - elif [ "${DOWNLOAD_FORCE_CACHE}" = "true" ]; then - DOWNLOAD_USE_CACHE="true" - else - DOWNLOAD_USE_CACHE="true" - if [ -e "$(relevant_file expiry)" ]; then - if [ "$(cat "$(relevant_file expiry)")" -lt "$(date +%s)" ]; then - echo "The cached copy has expired, re-downloading..." - DOWNLOAD_USE_CACHE="false" - fi - fi + if [ "${DOWNLOAD_FLUSH_CACHE}" = "true" ]; then + echo "Flushing the cache..." + rm -Rf "${LXC_CACHE_PATH}" + elif [ "${DOWNLOAD_FORCE_CACHE}" = "true" ]; then + DOWNLOAD_USE_CACHE="true" + else + DOWNLOAD_USE_CACHE="true" + if [ -e "$(relevant_file expiry)" ]; then + if [ "$(cat "$(relevant_file expiry)")" -lt "$(date +%s)" ]; then + echo "The cached copy has expired, re-downloading..." + DOWNLOAD_USE_CACHE="false" + fi fi + fi fi # Download what's needed if [ "${DOWNLOAD_USE_CACHE}" = "false" ]; then - # Initialize GPG - gpg_setup + # Initialize GPG + gpg_setup - # Grab the index - DOWNLOAD_INDEX_PATH="/meta/1.0/index-${DOWNLOAD_MODE}" + # Grab the index + DOWNLOAD_INDEX_PATH="/meta/1.0/index-${DOWNLOAD_MODE}" - echo "Downloading the image index" - if ! download_file "${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL}" \ - "${DOWNLOAD_TEMP}/index" noexit || - ! download_sig "${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL}.asc" \ - "${DOWNLOAD_TEMP}/index.asc" noexit; then - download_file "${DOWNLOAD_INDEX_PATH}" "${DOWNLOAD_TEMP}/index" normal - download_sig "${DOWNLOAD_INDEX_PATH}.asc" \ - "${DOWNLOAD_TEMP}/index.asc" normal + echo "Downloading the image index" + if ! download_file "${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL}" "${DOWNLOAD_TEMP}/index" noexit || + ! download_sig "${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL}.asc" "${DOWNLOAD_TEMP}/index.asc" noexit; then + download_file "${DOWNLOAD_INDEX_PATH}" "${DOWNLOAD_TEMP}/index" normal + download_sig "${DOWNLOAD_INDEX_PATH}.asc" "${DOWNLOAD_TEMP}/index.asc" normal + fi + + gpg_validate "${DOWNLOAD_TEMP}/index.asc" + + # Parse it + while IFS=';' read -r f1 f2 f3 f4 f5 f6; do + if [ "${f1}" != "${DOWNLOAD_DIST}" ] || \ + [ "${f2}" != "${DOWNLOAD_RELEASE}" ] || \ + [ "${f3}" != "${DOWNLOAD_ARCH}" ] || \ + [ "${f4}" != "${DOWNLOAD_VARIANT}" ] || \ + [ -z "${f6}" ]; then + continue fi - gpg_validate "${DOWNLOAD_TEMP}/index.asc" + DOWNLOAD_BUILD="${f5}" + DOWNLOAD_URL="${f6}" - # Parse it - while IFS=';' read -r f1 f2 f3 f4 f5 f6; do + unset f1 f2 f3 f4 f5 f6 + break + done < "${DOWNLOAD_TEMP}/index" - if [ "${f1}" != "${DOWNLOAD_DIST}" ] || \ - [ "${f2}" != "${DOWNLOAD_RELEASE}" ] || \ - [ "${f3}" != "${DOWNLOAD_ARCH}" ] || \ - [ "${f4}" != "${DOWNLOAD_VARIANT}" ] || \ - [ -z "${f6}" ]; then - continue - fi + if [ -z "${DOWNLOAD_URL}" ]; then + echo "ERROR: Couldn't find a matching image" 1>&1 + exit 1 + fi - DOWNLOAD_BUILD="${f5}" - DOWNLOAD_URL="${f6}" - - unset f1 f2 f3 f4 f5 f6 - break - done < "${DOWNLOAD_TEMP}/index" - - if [ -z "${DOWNLOAD_URL}" ]; then - echo "ERROR: Couldn't find a matching image." 1>&1 - exit 1 - fi - - if [ -d "${LXC_CACHE_PATH}" ] && [ -f "${LXC_CACHE_PATH}/build_id" ] && \ - [ "$(cat "${LXC_CACHE_PATH}/build_id")" = "${DOWNLOAD_BUILD}" ]; then - echo "The cache is already up to date." - echo "Using image from local cache" - else - # Download the actual files - echo "Downloading the rootfs" - download_file "${DOWNLOAD_URL}/rootfs.tar.xz" \ - "${DOWNLOAD_TEMP}/rootfs.tar.xz" normal - download_sig "${DOWNLOAD_URL}/rootfs.tar.xz.asc" \ - "${DOWNLOAD_TEMP}/rootfs.tar.xz.asc" normal - gpg_validate "${DOWNLOAD_TEMP}/rootfs.tar.xz.asc" - - echo "Downloading the metadata" - download_file "${DOWNLOAD_URL}/meta.tar.xz" \ - "${DOWNLOAD_TEMP}/meta.tar.xz" normal - download_sig "$DOWNLOAD_URL/meta.tar.xz.asc" \ - "${DOWNLOAD_TEMP}/meta.tar.xz.asc" normal - gpg_validate "${DOWNLOAD_TEMP}/meta.tar.xz.asc" - - if [ -d "${LXC_CACHE_PATH}" ]; then - rm -Rf "${LXC_CACHE_PATH}" - fi - mkdir -p "${LXC_CACHE_PATH}" - mv "${DOWNLOAD_TEMP}/rootfs.tar.xz" "${LXC_CACHE_PATH}" - if ! tar Jxf "${DOWNLOAD_TEMP}/meta.tar.xz" -C "${LXC_CACHE_PATH}"; then - echo "ERROR: Invalid rootfs tarball." 2>&1 - exit 1 - fi - - echo "${DOWNLOAD_BUILD}" > "${LXC_CACHE_PATH}/build_id" - - if [ -n "${LXC_MAPPED_UID}" ] && [ "${LXC_MAPPED_UID}" != "-1" ]; then - # As the script is run in strict mode (set -eu), all commands - # exiting with non 0 would make the script stop. - # || true or || : (more portable) prevents that. - chown -R "${LXC_MAPPED_UID}" "${LXC_CACHE_BASE}" >/dev/null 2>&1 || : - fi - if [ -n "${LXC_MAPPED_GID}" ] && [ "${LXC_MAPPED_GID}" != "-1" ]; then - chgrp -R "${LXC_MAPPED_GID}" "${LXC_CACHE_BASE}" >/dev/null 2>&1 || : - fi - echo "The image cache is now ready" - fi -else + if [ -d "${LXC_CACHE_PATH}" ] && [ -f "${LXC_CACHE_PATH}/build_id" ] && \ + [ "$(cat "${LXC_CACHE_PATH}/build_id")" = "${DOWNLOAD_BUILD}" ]; then + echo "The cache is already up to date" echo "Using image from local cache" + else + # Download the actual files + echo "Downloading the rootfs" + download_file "${DOWNLOAD_URL}/rootfs.tar.xz" "${DOWNLOAD_TEMP}/rootfs.tar.xz" normal + download_sig "${DOWNLOAD_URL}/rootfs.tar.xz.asc" "${DOWNLOAD_TEMP}/rootfs.tar.xz.asc" normal + gpg_validate "${DOWNLOAD_TEMP}/rootfs.tar.xz.asc" + + echo "Downloading the metadata" + download_file "${DOWNLOAD_URL}/meta.tar.xz" "${DOWNLOAD_TEMP}/meta.tar.xz" normal + download_sig "$DOWNLOAD_URL/meta.tar.xz.asc" "${DOWNLOAD_TEMP}/meta.tar.xz.asc" normal + gpg_validate "${DOWNLOAD_TEMP}/meta.tar.xz.asc" + + if [ -d "${LXC_CACHE_PATH}" ]; then + rm -Rf "${LXC_CACHE_PATH}" + fi + mkdir -p "${LXC_CACHE_PATH}" + mv "${DOWNLOAD_TEMP}/rootfs.tar.xz" "${LXC_CACHE_PATH}" + if ! tar Jxf "${DOWNLOAD_TEMP}/meta.tar.xz" -C "${LXC_CACHE_PATH}"; then + echo "ERROR: Invalid rootfs tarball." 2>&1 + exit 1 + fi + + echo "${DOWNLOAD_BUILD}" > "${LXC_CACHE_PATH}/build_id" + + if [ -n "${LXC_MAPPED_UID}" ] && [ "${LXC_MAPPED_UID}" != "-1" ]; then + # As the script is run in strict mode (set -eu), all commands + # exiting with non 0 would make the script stop. + # || true or || : (more portable) prevents that. + chown -R "${LXC_MAPPED_UID}" "${LXC_CACHE_BASE}" >/dev/null 2>&1 || : + fi + if [ -n "${LXC_MAPPED_GID}" ] && [ "${LXC_MAPPED_GID}" != "-1" ]; then + chgrp -R "${LXC_MAPPED_GID}" "${LXC_CACHE_BASE}" >/dev/null 2>&1 || : + fi + echo "The image cache is now ready" + fi +else + echo "Using image from local cache" fi # Unpack the rootfs @@ -513,9 +500,9 @@ echo "Unpacking the rootfs" EXCLUDES="" excludelist=$(relevant_file excludes) if [ -f "${excludelist}" ]; then - while read -r line; do - EXCLUDES="${EXCLUDES} --exclude=${line}" - done < "${excludelist}" + while read -r line; do + EXCLUDES="${EXCLUDES} --exclude=${line}" + done < "${excludelist}" fi # Do not surround ${EXCLUDES} by quotes. This does not work. The solution could @@ -523,8 +510,7 @@ fi # is to use a function wrapper, but the latter can't be used here as the args # are dynamic. We thus need to ignore the warning brought by shellcheck. # shellcheck disable=SC2086 -tar --anchored ${EXCLUDES} --numeric-owner -xpJf \ - "${LXC_CACHE_PATH}/rootfs.tar.xz" -C "${LXC_ROOTFS}" +tar --anchored ${EXCLUDES} --numeric-owner -xpJf "${LXC_CACHE_PATH}/rootfs.tar.xz" -C "${LXC_ROOTFS}" mkdir -p "${LXC_ROOTFS}/dev/pts/" @@ -532,57 +518,62 @@ mkdir -p "${LXC_ROOTFS}/dev/pts/" configfile="$(relevant_file config)" fstab="$(relevant_file fstab)" if [ ! -e "${configfile}" ]; then - echo "ERROR: meta tarball is missing the configuration file" 1>&2 - exit 1 + echo "ERROR: meta tarball is missing the configuration file" 1>&2 + exit 1 fi ## Extract all the network config entries -sed -i -e "/lxc.net.0/{w ${LXC_PATH}/config-network" -e "d}" \ - "${LXC_PATH}/config" +sed -i -e "/lxc.net.0/{w ${LXC_PATH}/config-network" -e "d}" "${LXC_PATH}/config" ## Extract any other config entry sed -i -e "/lxc./{w ${LXC_PATH}/config-auto" -e "d}" "${LXC_PATH}/config" ## Append the defaults -echo "" >> "${LXC_PATH}/config" -echo "# Distribution configuration" >> "${LXC_PATH}/config" -cat "$configfile" >> "${LXC_PATH}/config" +{ + echo "" + echo "# Distribution configuration" + cat "$configfile" +} >> "${LXC_PATH}/config" ## Add the container-specific config -echo "" >> "${LXC_PATH}/config" -echo "# Container specific configuration" >> "${LXC_PATH}/config" -if [ -e "${LXC_PATH}/config-auto" ]; then - cat "${LXC_PATH}/config-auto" >> "${LXC_PATH}/config" +{ + echo "" + echo "# Container specific configuration" + if [ -e "${LXC_PATH}/config-auto" ]; then + cat "${LXC_PATH}/config-auto" rm "${LXC_PATH}/config-auto" -fi -if [ -e "${fstab}" ]; then - echo "lxc.mount.fstab = ${LXC_PATH}/fstab" >> "${LXC_PATH}/config" -fi -echo "lxc.uts.name = ${LXC_NAME}" >> "${LXC_PATH}/config" + fi + if [ -e "${fstab}" ]; then + echo "lxc.mount.fstab = ${LXC_PATH}/fstab" + fi + echo "lxc.uts.name = ${LXC_NAME}" +} >> "${LXC_PATH}/config" ## Re-add the previously removed network config if [ -e "${LXC_PATH}/config-network" ]; then - echo "" >> "${LXC_PATH}/config" - echo "# Network configuration" >> "${LXC_PATH}/config" - cat "${LXC_PATH}/config-network" >> "${LXC_PATH}/config" + { + echo "" + echo "# Network configuration" + cat "${LXC_PATH}/config-network" rm "${LXC_PATH}/config-network" + } >> "${LXC_PATH}/config" fi TEMPLATE_FILES="${LXC_PATH}/config" # Setup the fstab if [ -e "${fstab}" ]; then - cp "${fstab}" "${LXC_PATH}/fstab" - TEMPLATE_FILES="${TEMPLATE_FILES};${LXC_PATH}/fstab" + cp "${fstab}" "${LXC_PATH}/fstab" + TEMPLATE_FILES="${TEMPLATE_FILES};${LXC_PATH}/fstab" fi # Look for extra templates if [ -e "$(relevant_file templates)" ]; then - while read -r line; do - fullpath="${LXC_ROOTFS}/${line}" - [ ! -e "${fullpath}" ] && continue - TEMPLATE_FILES="${TEMPLATE_FILES};${fullpath}" - done < "$(relevant_file templates)" + while read -r line; do + fullpath="${LXC_ROOTFS}/${line}" + [ ! -e "${fullpath}" ] && continue + TEMPLATE_FILES="${TEMPLATE_FILES};${fullpath}" + done < "$(relevant_file templates)" fi # Replace variables in all templates @@ -590,31 +581,31 @@ OLD_IFS=${IFS} IFS=";" for file in ${TEMPLATE_FILES}; do [ ! -f "${file}" ] && continue - - sed -i "s#LXC_NAME#${LXC_NAME}#g" "${file}" - sed -i "s#LXC_PATH#${LXC_PATH}#g" "${file}" - sed -i "s#LXC_ROOTFS#${LXC_ROOTFS}#g" "${file}" - sed -i "s#LXC_TEMPLATE_CONFIG#${LXC_TEMPLATE_CONFIG}#g" "${file}" - sed -i "s#LXC_HOOK_DIR#${LXC_HOOK_DIR}#g" "${file}" + sed -i "s#LXC_NAME#${LXC_NAME}#g" "${file}" + sed -i "s#LXC_PATH#${LXC_PATH}#g" "${file}" + sed -i "s#LXC_ROOTFS#${LXC_ROOTFS}#g" "${file}" + sed -i "s#LXC_TEMPLATE_CONFIG#${LXC_TEMPLATE_CONFIG}#g" "${file}" + sed -i "s#LXC_HOOK_DIR#${LXC_HOOK_DIR}#g" "${file}" done IFS=${OLD_IFS} # prevent mingetty from calling vhangup(2) since it fails with userns on CentOS / Oracle if [ -f "${LXC_ROOTFS}/etc/init/tty.conf" ]; then - sed -i 's|mingetty|mingetty --nohangup|' "${LXC_ROOTFS}/etc/init/tty.conf" + sed -i 's|mingetty|mingetty --nohangup|' "${LXC_ROOTFS}/etc/init/tty.conf" fi if [ -n "${LXC_MAPPED_UID}" ] && [ "${LXC_MAPPED_UID}" != "-1" ]; then - chown "${LXC_MAPPED_UID}" "${LXC_PATH}/config" "${LXC_PATH}/fstab" >/dev/null 2>&1 || : + chown "${LXC_MAPPED_UID}" "${LXC_PATH}/config" "${LXC_PATH}/fstab" >/dev/null 2>&1 || : fi + if [ -n "${LXC_MAPPED_GID}" ] && [ "${LXC_MAPPED_GID}" != "-1" ]; then - chgrp "${LXC_MAPPED_GID}" "${LXC_PATH}/config" "${LXC_PATH}/fstab" >/dev/null 2>&1 || : + chgrp "${LXC_MAPPED_GID}" "${LXC_PATH}/config" "${LXC_PATH}/fstab" >/dev/null 2>&1 || : fi if [ -e "$(relevant_file create-message)" ]; then - echo "" - echo "---" - cat "$(relevant_file create-message)" + echo "" + echo "---" + cat "$(relevant_file create-message)" fi exit 0 From b62671d84965e4c3baf1d958154cc4a7e64f828f Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Tue, 27 Feb 2018 11:46:33 +0100 Subject: [PATCH 09/12] lxc-busybox: make shellcheck clean Signed-off-by: Christian Brauner --- templates/lxc-busybox.in | 584 ++++++++++++++------------------------- 1 file changed, 215 insertions(+), 369 deletions(-) diff --git a/templates/lxc-busybox.in b/templates/lxc-busybox.in index fa7c78ff7..82666b1cb 100644 --- a/templates/lxc-busybox.in +++ b/templates/lxc-busybox.in @@ -1,349 +1,221 @@ -#!/bin/bash +#!/bin/sh +# Client script for LXC container images. # -# lxc: linux Container library +# Copyright @ Daniel Lezcano +# Copyright © 2018 Christian Brauner +# +# 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. -# Authors: -# Daniel Lezcano +# 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. -# 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 +# 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 LXC_MAPPED_UID= LXC_MAPPED_GID= -SSH= # Make sure the usual locations are in PATH export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin -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() { + [ -e /proc/self/uid_map ] || { echo no; return; } + while read -r line; do + fields="$(echo "$line" | awk '{ print $1 " " $2 " " $3 }')" + if [ "${fields}" = "0 0 4294967295" ]; then + echo no; + return; + fi + if echo "${fields}" | grep -q " 0 1$"; then + echo userns-root; + return; + fi + done < /proc/self/uid_map + + [ "$(cat /proc/self/uid_map)" = "$(cat /proc/1/uid_map)" ] && { echo userns-root; return; } + echo yes } -in_userns=0 -[ $(am_in_userns) = "yes" ] && in_userns=1 - -copy_binary() -{ - binary_path=`which $1` - if [ $? -ne 0 ]; then - echo "Unable to find $1 binary on the system" - return 1 - fi - - dir_path="${binary_path%/*}" - echo /{,usr/}{,s}bin | grep $dir_path >/dev/null 2>&1 - if [ $? -ne 0 ]; then - echo "Binary $1 is located at $binary_path and will not be copied" - echo "($dir_path not supported)" - return 1 - fi - - cp $binary_path $rootfs/$binary_path - if [ $? -ne 0 ]; then - echo "Failed to copy $binary_path to rootfs" - return 1 - fi - - return 0 -} +USERNS="$(in_userns)" install_busybox() { - rootfs=$1 - name=$2 - res=0 - tree="\ -$rootfs/selinux \ -$rootfs/dev \ -$rootfs/home \ -$rootfs/root \ -$rootfs/etc \ -$rootfs/etc/init.d \ -$rootfs/bin \ -$rootfs/usr/bin \ -$rootfs/sbin \ -$rootfs/usr/sbin \ -$rootfs/proc \ -$rootfs/sys \ -$rootfs/mnt \ -$rootfs/tmp \ -$rootfs/var/log \ -$rootfs/usr/share/udhcpc \ -$rootfs/dev/pts \ -$rootfs/dev/shm \ -$rootfs/lib \ -$rootfs/usr/lib \ -$rootfs/lib64 \ -$rootfs/usr/lib64" + rootfs="${1}" + name="${2}" + res=0 + fstree="\ +${rootfs}/selinux \ +${rootfs}/dev \ +${rootfs}/home \ +${rootfs}/root \ +${rootfs}/etc \ +${rootfs}/etc/init.d \ +${rootfs}/bin \ +${rootfs}/usr/bin \ +${rootfs}/sbin \ +${rootfs}/usr/sbin \ +${rootfs}/proc \ +${rootfs}/sys \ +${rootfs}/mnt \ +${rootfs}/tmp \ +${rootfs}/var/log \ +${rootfs}/usr/share/udhcpc \ +${rootfs}/dev/pts \ +${rootfs}/dev/shm \ +${rootfs}/lib \ +${rootfs}/usr/lib \ +${rootfs}/lib64 \ +${rootfs}/usr/lib64" - mkdir -p $tree || return 1 - chmod 755 $tree || return 1 + # shellcheck disable=SC2086 + mkdir -p ${fstree} || return 1 + # shellcheck disable=SC2086 + chmod 755 ${fstree} || return 1 - pushd $rootfs/dev > /dev/null || return 1 + # minimal devices needed for busybox + if [ "${USERNS}" = "yes" ]; then + for dev in tty console tty0 tty1 ram0 null urandom; do + echo "lxc.mount.entry = /dev/${dev} dev/${dev} none bind,optional,create=file 0 0" >> "${path}/config" + done + else + mknod -m 666 "${rootfs}/tty" c 5 0 || res=1 + mknod -m 666 "${rootfs}/console" c 5 1 || res=1 + mknod -m 666 "${rootfs}/tty0" c 4 0 || res=1 + mknod -m 666 "${rootfs}/tty1" c 4 0 || res=1 + mknod -m 666 "${rootfs}/tty5" c 4 0 || res=1 + mknod -m 600 "${rootfs}/ram0" b 1 0 || res=1 + mknod -m 666 "${rootfs}/null" c 1 3 || res=1 + mknod -m 666 "${rootfs}/zero" c 1 5 || res=1 + mknod -m 666 "${rootfs}/urandom" c 1 9 || res=1 + fi - # minimal devices needed for busybox - if [ $in_userns -eq 1 ]; then - for dev in tty console tty0 tty1 ram0 null urandom; do - echo "lxc.mount.entry = /dev/$dev dev/$dev none bind,optional,create=file 0 0" >> $path/config - done - else - mknod -m 666 tty c 5 0 || res=1 - mknod -m 666 console c 5 1 || res=1 - mknod -m 666 tty0 c 4 0 || res=1 - mknod -m 666 tty1 c 4 0 || res=1 - mknod -m 666 tty5 c 4 0 || res=1 - mknod -m 600 ram0 b 1 0 || res=1 - mknod -m 666 null c 1 3 || res=1 - mknod -m 666 zero c 1 5 || res=1 - mknod -m 666 urandom c 1 9 || res=1 - fi - - popd > /dev/null - - # root user defined - cat <> $rootfs/etc/passwd + # root user defined + cat <> "${rootfs}/etc/passwd" root:x:0:0:root:/root:/bin/sh EOF - cat <> $rootfs/etc/group + cat <> "${rootfs}/etc/group" root:x:0:root EOF # mount everything - cat <> $rootfs/etc/init.d/rcS + cat <> "${rootfs}/etc/init.d/rcS" #!/bin/sh /bin/syslogd /bin/mount -a /bin/udhcpc EOF - # executable - chmod 744 $rootfs/etc/init.d/rcS || return 1 + # executable + chmod 744 "${rootfs}/etc/init.d/rcS" || return 1 - # launch rcS first then make a console available - # and propose a shell on the tty, the last one is - # not needed - cat <> $rootfs/etc/inittab + # launch rcS first then make a console available + # and propose a shell on the tty, the last one is + # not needed + cat <> "${rootfs}/etc/inittab" ::sysinit:/etc/init.d/rcS tty1::respawn:/bin/getty -L tty1 115200 vt100 console::askfirst:/bin/sh EOF - # writable and readable for other - chmod 644 $rootfs/etc/inittab || return 1 + # writable and readable for other + chmod 644 "${rootfs}/etc/inittab" || return 1 - cat <> $rootfs/usr/share/udhcpc/default.script + cat <> "${rootfs}/usr/share/udhcpc/default.script" #!/bin/sh case "\$1" in - deconfig) - ip addr flush dev \$interface - ;; + deconfig) + ip addr flush dev \$interface + ;; - renew|bound) - # flush all the routes - if [ -n "\$router" ]; then - ip route del default 2> /dev/null - fi + renew|bound) + # flush all the routes + if [ -n "\$router" ]; then + ip route del default 2> /dev/null + fi - # check broadcast - if [ -n "\$broadcast" ]; then - broadcast="broadcast \$broadcast" - fi + # check broadcast + if [ -n "\$broadcast" ]; then + broadcast="broadcast \$broadcast" + fi - # add a new ip address - ip addr add \$ip/\$mask \$broadcast dev \$interface + # add a new ip address + ip addr add \$ip/\$mask \$broadcast dev \$interface - if [ -n "\$router" ]; then - ip route add default via \$router dev \$interface - fi + if [ -n "\$router" ]; then + ip route add default via \$router dev \$interface + fi - [ -n "\$domain" ] && echo search \$domain > /etc/resolv.conf - for i in \$dns ; do - echo nameserver \$i >> /etc/resolv.conf - done - ;; + [ -n "\$domain" ] && echo search \$domain > /etc/resolv.conf + for i in \$dns ; do + echo nameserver \$i >> /etc/resolv.conf + done + ;; esac exit 0 EOF - chmod 744 $rootfs/usr/share/udhcpc/default.script + chmod 744 "${rootfs}/usr/share/udhcpc/default.script" - return $res -} - -install_dropbear() -{ - # copy dropbear binary - copy_binary dropbear || return 1 - - # make symlinks to various ssh utilities - utils="\ - $rootfs/usr/bin/dbclient \ - $rootfs/usr/bin/scp \ - $rootfs/usr/bin/ssh \ - $rootfs/usr/sbin/dropbearkey \ - $rootfs/usr/sbin/dropbearconvert \ - " - echo $utils | xargs -n1 ln -s /usr/sbin/dropbear - - # add necessary config files - mkdir $rootfs/etc/dropbear - dropbearkey -t rsa -f $rootfs/etc/dropbear/dropbear_rsa_host_key > /dev/null 2>&1 - dropbearkey -t dss -f $rootfs/etc/dropbear/dropbear_dss_host_key > /dev/null 2>&1 - - echo "'dropbear' ssh utility installed" - - return 0 -} - -install_openssh() -{ - # tools to be installed - server_utils="sshd" - client_utils="\ - ssh \ - scp \ - " - client_optional_utils="\ - sftp \ - ssh-add \ - ssh-agent \ - ssh-keygen \ - ssh-keyscan \ - ssh-argv0 \ - ssh-copy-id \ - " - - # new folders used by ssh - ssh_tree="\ -$rootfs/etc/ssh \ -$rootfs/var/empty/sshd \ -$rootfs/var/lib/empty/sshd \ -$rootfs/var/run/sshd \ -" - - # create folder structure - mkdir -p $ssh_tree - if [ $? -ne 0 ]; then - return 1 - fi - - # copy binaries - for bin in $server_utils $client_utils; do - copy_binary $bin || return 1 - done - - for bin in $client_optional_utils; do - tool_path=`which $bin` && copy_binary $bin - done - - # add user and group - cat <> $rootfs/etc/passwd -sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin -EOF - - cat <> $rootfs/etc/group -sshd:x:74: -EOF - - # generate container keys - ssh-keygen -t rsa -N "" -f $rootfs/etc/ssh/ssh_host_rsa_key >/dev/null 2>&1 - ssh-keygen -t dsa -N "" -f $rootfs/etc/ssh/ssh_host_dsa_key >/dev/null 2>&1 - - # by default setup root password with no password - cat < $rootfs/etc/ssh/sshd_config -Port 22 -Protocol 2 -HostKey /etc/ssh/ssh_host_rsa_key -HostKey /etc/ssh/ssh_host_dsa_key -UsePrivilegeSeparation yes -KeyRegenerationInterval 3600 -ServerKeyBits 768 -SyslogFacility AUTH -LogLevel INFO -LoginGraceTime 120 -PermitRootLogin yes -StrictModes yes -RSAAuthentication yes -PubkeyAuthentication yes -IgnoreRhosts yes -RhostsRSAAuthentication no -HostbasedAuthentication no -PermitEmptyPasswords yes -ChallengeResponseAuthentication no -EOF - - echo "'OpenSSH' utility installed" - - return 0 + return "${res}" } configure_busybox() { - rootfs=$1 + rootfs="${1}" - which busybox >/dev/null 2>&1 + if ! which busybox > /dev/null 2>&1; then + echo "ERROR: Failed to find busybox binary" + return 1 + fi - if [ $? -ne 0 ]; then - echo "busybox executable is not accessible" - return 1 - fi + # copy busybox in the rootfs + if ! cp "$(which busybox)" "${rootfs}/bin"; then + echo "ERROR: Failed to copy busybox binary" + return 1 + fi - # copy busybox in the rootfs - cp $(which busybox) $rootfs/bin - if [ $? -ne 0 ]; then - echo "failed to copy busybox in the rootfs" - return 1 - fi - - # symlink busybox for the commands it supports - # it would be nice to just use "chroot $rootfs busybox --install -s /bin" - # but that only works right in a chroot with busybox >= 1.19.0 - pushd $rootfs/bin > /dev/null || return 1 + # symlink busybox for the commands it supports + # it would be nice to just use "chroot $rootfs busybox --install -s /bin" + # but that only works right in a chroot with busybox >= 1.19.0 + ( + cd "${rootfs}/bin" || return 1 ./busybox --help | grep 'Currently defined functions:' -A300 | \ grep -v 'Currently defined functions:' | tr , '\n' | \ xargs -n1 ln -s busybox - popd > /dev/null + ) - # relink /sbin/init - ln $rootfs/bin/busybox $rootfs/sbin/init + # relink /sbin/init + ln "${rootfs}/bin/busybox" "${rootfs}/sbin/init" - # /etc/fstab must exist for "mount -a" - touch $rootfs/etc/fstab + # /etc/fstab must exist for "mount -a" + touch "${rootfs}/etc/fstab" - # passwd exec must be setuid - chmod +s $rootfs/bin/passwd - touch $rootfs/etc/shadow + # passwd exec must be setuid + chmod +s "${rootfs}/bin/passwd" + touch "${rootfs}/etc/shadow" - return 0 + return 0 } copy_configuration() { - path=$1 - rootfs=$2 - name=$3 + path="${1}" + rootfs="${2}" + name="${3}" -grep -q "^lxc.rootfs.path" $path/config 2>/dev/null || echo "lxc.rootfs.path = $rootfs" >> $path/config -cat <> $path/config +grep -q "^lxc.rootfs.path" "${path}/config" 2>/dev/null || echo "lxc.rootfs.path = ${rootfs}" >> "${path}/config" +cat <> "${path}/config" lxc.signal.halt = SIGUSR1 lxc.signal.reboot = SIGTERM -lxc.uts.name = $name +lxc.uts.name = "${name}" lxc.tty.max = 1 lxc.pty.max = 1 lxc.cap.drop = sys_module mac_admin mac_override sys_time @@ -355,130 +227,104 @@ lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed lxc.mount.entry = shm /dev/shm tmpfs defaults 0 0 EOF - libdirs="\ - lib \ - usr/lib \ - lib64 \ - usr/lib64" - - for dir in $libdirs; do - if [ -d "/$dir" ] && [ -d "$rootfs/$dir" ]; then - echo "lxc.mount.entry = /$dir $dir none ro,bind 0 0" >> $path/config - fi - done - echo "lxc.mount.entry = /sys/kernel/security sys/kernel/security none ro,bind,optional 0 0" >>$path/config + libdirs="\ + lib \ + usr/lib \ + lib64 \ + usr/lib64" + + for dir in ${libdirs}; do + if [ -d "/${dir}" ] && [ -d "${rootfs}/${dir}" ]; then + echo "lxc.mount.entry = /${dir} ${dir} none ro,bind 0 0" >> "${path}/config" + fi + done + echo "lxc.mount.entry = /sys/kernel/security sys/kernel/security none ro,bind,optional 0 0" >> "${path}/config" } remap_userns() { - path=$1 + path="${1}" - if [ -n "$LXC_MAPPED_UID" ] && [ "$LXC_MAPPED_UID" != "-1" ]; then - chown $LXC_MAPPED_UID $path/config >/dev/null 2>&1 - chown -R root $path/rootfs >/dev/null 2>&1 - fi + if [ -n "$LXC_MAPPED_UID" ] && [ "$LXC_MAPPED_UID" != "-1" ]; then + chown "${LXC_MAPPED_UID}" "${path}/config" > /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 >/dev/null 2>&1 - chgrp -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" > /dev/null 2>&1 + chgrp -R root "${path}/rootfs" > /dev/null 2>&1 + fi } -usage() -{ - cat < -s|--ssh={dropbear,openssh} +usage() { + cat < ]: The container name +[ --path ]: The path to the container +[ --rootfs ]: The path to the container's rootfs +[ --mapped-uid ]: A uid map (user namespaces) +[ --mapped-gid ]: A gid map (user namespaces) EOF - return 0 + return 0 } -options=$(getopt -o hp:n:s: -l help,rootfs:,path:,name:,mapped-uid:,mapped-gid:,ssh: -- "$@") -if [ $? -ne 0 ]; then - usage $(basename $0) - exit 1 +if ! options=$(getopt -o hp:n: -l help,rootfs:,path:,name:,mapped-uid:,mapped-gid: -- "$@"); then + usage + exit 1 fi eval set -- "$options" while true do - case "$1" in - -h|--help) usage $0 && exit 0;; - -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;; - -s|--ssh) SSH=$2; shift 2;; - --) shift 1; break ;; - *) break ;; - esac + case "$1" in + -h|--help) usage exit 1;; + -n|--name) name=$2; shift 2;; + -p|--path) path=$2; shift 2;; + --rootfs) rootfs=$2; shift 2;; + --mapped-uid) LXC_MAPPED_UID=$2; shift 2;; + --mapped-gid) LXC_MAPPED_GID=$2; shift 2;; + --) shift 1; break ;; + *) break ;; + esac done -if [ "$(id -u)" != "0" ]; then - echo "This script should be run as 'root'" - exit 1 -fi - -if [ -z "$path" ]; then - echo "'path' parameter is required" +# Check that we have all variables we need +if [ -z "${name}" ] || [ -z "${path}" ] || [ -z "${rootfs}" ]; then + echo "ERROR: Please pass the name, path, and rootfs for the container" 1>&2 exit 1 fi # detect rootfs config="$path/config" if [ -z "$rootfs" ]; then - if grep -q '^lxc.rootfs.path' $config 2>/dev/null ; then - rootfs=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $config) - else - rootfs=$path/rootfs - fi + if grep -q '^lxc.rootfs.path' "${config}" 2> /dev/null ; then + rootfs=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' "${config}") + else + rootfs="${path}/rootfs" + fi fi -install_busybox $rootfs $name -if [ $? -ne 0 ]; then - echo "failed to install busybox's rootfs" - exit 1 +if ! install_busybox "${rootfs}" "${name}"; then + echo "ERROR: Failed to install rootfs" + exit 1 fi -configure_busybox $rootfs -if [ $? -ne 0 ]; then - echo "failed to configure busybox template" - exit 1 +if ! configure_busybox "${rootfs}"; then + echo "ERROR: Failed to configure busybox" + exit 1 fi -copy_configuration $path $rootfs $name -if [ $? -ne 0 ]; then - echo "failed to write configuration file" - exit 1 +if ! copy_configuration "${path}" "${rootfs}" "${name}"; then + echo "ERROR: Failed to write config file" + exit 1 fi -remap_userns $path -if [ $? -ne 0 ]; then - echo "failed to remap files to user" - exit 1 -fi - -if [ -n "$SSH" ]; then - case "$SSH" in - "dropbear") - install_dropbear - if [ $? -ne 0 ]; then - echo "Unable to install 'dropbear' ssh utility" - exit 1 - fi ;; - "openssh") - install_openssh - if [ $? -ne 0 ]; then - echo "Unable to install 'OpenSSH' utility" - exit 1 - fi ;; - *) - echo "$SSH: unrecognized ssh utility" - exit 1 - esac -else - which dropbear >/dev/null 2>&1 - if [ $? -eq 0 ]; then - install_dropbear - fi +if ! remap_userns "${path}"; then + echo "ERROR: Failed to change idmappings" + exit 1 fi From a488502d83e27d27d35bb1392f989ed86028ec28 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Tue, 27 Feb 2018 11:55:22 +0100 Subject: [PATCH 10/12] lxc-local: coding style Signed-off-by: Christian Brauner --- templates/lxc-local.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/lxc-local.in b/templates/lxc-local.in index baea28043..20c0c35c3 100644 --- a/templates/lxc-local.in +++ b/templates/lxc-local.in @@ -114,7 +114,7 @@ USERNS="$(in_userns)" if [ "${USERNS}" != "no" ]; then if [ "${USERNS}" = "yes" ]; then if [ -z "${LXC_MAPPED_UID}" ] || [ "${LXC_MAPPED_UID}" = "-1" ]; then - echo "ERROR: In a user namespace without a map." 1>&2 + echo "ERROR: In a user namespace without a map" 1>&2 exit 1 fi MODE="user" From 4328e9e31691d520366e463a44fe6bf746686fd1 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Tue, 27 Feb 2018 12:21:02 +0100 Subject: [PATCH 11/12] lxc-oci: make shellcheck clean Signed-off-by: Christian Brauner --- templates/lxc-oci.in | 321 +++++++++++++++++++++++-------------------- 1 file changed, 172 insertions(+), 149 deletions(-) diff --git a/templates/lxc-oci.in b/templates/lxc-oci.in index daa4241f4..d843a079e 100644 --- a/templates/lxc-oci.in +++ b/templates/lxc-oci.in @@ -21,17 +21,16 @@ # USA set -eu -# set -x # debug # Make sure the usual locations are in PATH export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin # Check for required binaries for bin in skopeo umoci jq; do - if ! type $bin >/dev/null 2>&1; then - echo "ERROR: Missing required tool: $bin" 1>&2 - exit 1 - fi + if ! which $bin >/dev/null 2>&1; then + echo "ERROR: Missing required tool: $bin" 1>&2 + exit 1 + fi done LOCALSTATEDIR="@LOCALSTATEDIR@" @@ -40,86 +39,94 @@ LXC_HOOK_DIR="@LXCHOOKDIR@" # Some useful functions cleanup() { - if [ -d "${DOWNLOAD_TEMP}" ]; then - rm -Rf "${DOWNLOAD_TEMP}" - fi - if [ -d "${LXC_ROOTFS}.tmp" ]; then - rm -Rf "${LXC_ROOTFS}.tmp" - fi + if [ -d "${DOWNLOAD_TEMP}" ]; then + rm -Rf "${DOWNLOAD_TEMP}" + fi + + if [ -d "${LXC_ROOTFS}.tmp" ]; then + rm -Rf "${LXC_ROOTFS}.tmp" + fi } in_userns() { - [ -e /proc/self/uid_map ] || { echo no; return; } - while read line; do - fields=$(echo $line | awk '{ print $1 " " $2 " " $3 }') - [ "$fields" = "0 0 4294967295" ] && { echo no; return; } || true - echo $fields | grep -q " 0 1$" && { echo userns-root; return; } || true - done < /proc/self/uid_map + [ -e /proc/self/uid_map ] || { echo no; return; } + while read -r line; do + fields="$(echo "$line" | awk '{ print $1 " " $2 " " $3 }')" + if [ "${fields}" = "0 0 4294967295" ]; then + echo no; + return; + fi + if echo "${fields}" | grep -q " 0 1$"; then + echo userns-root; + return; + fi + done < /proc/self/uid_map - [ "$(cat /proc/self/uid_map)" = "$(cat /proc/1/uid_map)" ] && \ - { echo userns-root; return; } - echo yes + [ "$(cat /proc/self/uid_map)" = "$(cat /proc/1/uid_map)" ] && { echo userns-root; return; } + echo yes } getconfigpath() { - basedir="$1" - q="$2" + basedir="$1" + q="$2" - digest=`cat "${basedir}/index.json" | jq -c -r --arg q "$q" '.manifests[] | if .annotations."org.opencontainers.image.ref.name" == $q then .digest else empty end'` - if [ -z "${digest}" ]; then - echo "$q not found in index.json" >&2 - return - fi + digest=$(jq -c -r --arg q "$q" '.manifests[] | if .annotations."org.opencontainers.image.ref.name" == $q then .digest else empty end' < "${basedir}/index.json") + if [ -z "${digest}" ]; then + echo "$q not found in index.json" >&2 + return + fi - # Ok we have the image config digest, now get the config from that, - d=${digest:7} - cdigest=`cat "${basedir}/blobs/sha256/${d}" | jq -c -r '.config.digest'` - if [ -z "${cdigest}" ]; then - echo "container config not found" >&2 - return - fi + # Ok we have the image config digest, now get the config from that + # shellcheck disable=SC2039 + d=${digest:7} + cdigest=$(jq -c -r '.config.digest' < "${basedir}/blobs/sha256/${d}") + if [ -z "${cdigest}" ]; then + echo "container config not found" >&2 + return + fi - d2=${cdigest:7} - echo "${basedir}/blobs/sha256/${d2}" - return + # shellcheck disable=SC2039 + d2=${cdigest:7} + echo "${basedir}/blobs/sha256/${d2}" + return } -# get entrypoint from oci image. Use sh if unspecified +# Get entrypoint from oci image. Use sh if unspecified getep() { - if [ "$#" -eq 0 ]; then - echo "/bin/sh" - return - fi + if [ "$#" -eq 0 ]; then + echo "/bin/sh" + return + fi - configpath="$1" + configpath="$1" - ep=`cat "${configpath}" | jq -c -r '.config.Entrypoint[]?'` - cmd=`cat "${configpath}" | jq -c -r '.config.Cmd[]?'` - if [ -z "${ep}" ]; then - ep="${cmd}" - if [ -z "${ep}" ]; then - ep="/bin/sh" - fi - elif [ -n "${cmd}" ]; then - ep="${ep} ${cmd}" - fi + ep=$(jq -c -r '.config.Entrypoint[]?'< "${configpath}") + cmd=$(jq -c -r '.config.Cmd[]?' < "${configpath}") + if [ -z "${ep}" ]; then + ep="${cmd}" + if [ -z "${ep}" ]; then + ep="/bin/sh" + fi + elif [ -n "${cmd}" ]; then + ep="${ep} ${cmd}" + fi - echo ${ep} - return + echo "${ep}" + return } # get environment from oci image. getenv() { - if [ "$#" -eq 0 ]; then - return - fi + if [ "$#" -eq 0 ]; then + return + fi - configpath="$1" + configpath="$1" - env=`cat "${configpath}" | jq -c -r '.config.Env[]'` + env=$(jq -c -r '.config.Env[]'< "${configpath}") - echo "${env}" - return + echo "${env}" + return } # FIXME 1: only support numerical values in the configuration file. @@ -127,37 +134,38 @@ getenv() { # the default group and supplementary groups of the given user/uid in # /etc/passwd from the container are applied." getuidgid() { - if [ "$#" -eq 0 ]; then - echo "0 0" - return - fi + if [ "$#" -eq 0 ]; then + echo "0 0" + return + fi - configpath="$1" + configpath="$1" - uidgid=`cat "${configpath}" | jq -c -r '.config.User // "0:0"'` - uidgid=(${uidgid//:/ }) + uidgid=$(jq -c -r '.config.User // "0:0"' < "${configpath}") + # shellcheck disable=SC2039 + uidgid=(${uidgid//:/ }) - printf '%d %d' ${uidgid[0]:-0} ${uidgid[1]:-0} 2>/dev/null || true - return + printf '%d %d' "${uidgid[0]:-0}" "${uidgid[1]:-0}" 2>/dev/null || true + return } # get cwd from oci image. getcwd() { - if [ "$#" -eq 0 ]; then - echo "/" - return - fi + if [ "$#" -eq 0 ]; then + echo "/" + return + fi - configpath="$1" + configpath="$1" - cwd=`cat "${configpath}" | jq -c -r '.config.WorkingDir // "/"'` + cwd=$(jq -c -r '.config.WorkingDir // "/"' < "${configpath}") - echo "${cwd}" - return + echo "${cwd}" + return } usage() { - cat < ]: The path to the container's rootfs [ --mapped-uid ]: A uid map (user namespaces) [ --mapped-gid ]: A gid map (user namespaces) - EOF - return 0 + return 0 } -options=$(getopt -o u:h -l help,url:,username:,password:,no-cache,dhcp,\ -name:,path:,rootfs:,mapped-uid:,mapped-gid: -- "$@") - -if [ $? -ne 0 ]; then +if ! options=$(getopt -o u:h -l help,url:,username:,password:,no-cache,dhcp,name:,path:,rootfs:,mapped-uid:,mapped-gid: -- "$@"); then usage exit 1 fi @@ -203,136 +207,152 @@ LXC_PATH= LXC_ROOTFS= while :; do - case "$1" in - -h|--help) usage && exit 1;; - -u|--url) OCI_URL=$2; shift 2;; - --username) OCI_USERNAME=$2; shift 2;; - --password) OCI_PASSWORD=$2; shift 2;; - --no-cache) OCI_USE_CACHE="false"; shift 1;; - --dhcp) OCI_USE_DHCP="true"; shift 1;; - --name) LXC_NAME=$2; shift 2;; - --path) LXC_PATH=$2; shift 2;; - --rootfs) LXC_ROOTFS=$2; shift 2;; - --mapped-uid) LXC_MAPPED_UID=$2; shift 2;; - --mapped-gid) LXC_MAPPED_GID=$2; shift 2;; - *) break;; - esac + case "$1" in + -h|--help) usage && exit 1;; + -u|--url) OCI_URL=$2; shift 2;; + --username) OCI_USERNAME=$2; shift 2;; + --password) OCI_PASSWORD=$2; shift 2;; + --no-cache) OCI_USE_CACHE="false"; shift 1;; + --dhcp) OCI_USE_DHCP="true"; shift 1;; + --name) LXC_NAME=$2; shift 2;; + --path) LXC_PATH=$2; shift 2;; + --rootfs) LXC_ROOTFS=$2; shift 2;; + --mapped-uid) LXC_MAPPED_UID=$2; shift 2;; + --mapped-gid) LXC_MAPPED_GID=$2; shift 2;; + *) break;; + esac done # Check that we have all variables we need if [ -z "$LXC_NAME" ] || [ -z "$LXC_PATH" ] || [ -z "$LXC_ROOTFS" ]; then - echo "ERROR: Not running through LXC." 1>&2 - exit 1 + echo "ERROR: Not running through LXC" 1>&2 + exit 1 fi if [ -z "$OCI_URL" ]; then - echo "ERROR: no OCI URL given" - exit 1 + echo "ERROR: no OCI URL given" + exit 1 fi if [ -n "$OCI_PASSWORD" ] && [ -z "$OCI_USERNAME" ]; then - echo "ERROR: password given but no username specified" - exit 1 + echo "ERROR: password given but no username specified" + exit 1 fi if [ "${OCI_USE_CACHE}" = "true" ]; then - if ! skopeo copy --help | grep -q 'dest-shared-blob-dir'; then - echo "INFO: skopeo doesn't support blob caching" - OCI_USE_CACHE="false" - fi + if ! skopeo copy --help | grep -q 'dest-shared-blob-dir'; then + echo "INFO: skopeo doesn't support blob caching" + OCI_USE_CACHE="false" + fi fi USERNS=$(in_userns) if [ "$USERNS" = "yes" ]; then - if [ -z "$LXC_MAPPED_UID" ] || [ "$LXC_MAPPED_UID" = "-1" ]; then - echo "ERROR: In a user namespace without a map." 1>&2 - exit 1 - fi + if [ -z "$LXC_MAPPED_UID" ] || [ "$LXC_MAPPED_UID" = "-1" ]; then + echo "ERROR: In a user namespace without a map" 1>&2 + exit 1 + fi fi if [ "${OCI_USE_CACHE}" = "true" ]; then - if [ "$USERNS" = "yes" ]; then - DOWNLOAD_BASE="${HOME}/.cache/lxc" - else - DOWNLOAD_BASE="${LOCALSTATEDIR}/cache/lxc" - fi + if [ "$USERNS" = "yes" ]; then + DOWNLOAD_BASE="${HOME}/.cache/lxc" + else + DOWNLOAD_BASE="${LOCALSTATEDIR}/cache/lxc" + fi else - DOWNLOAD_BASE=/tmp + DOWNLOAD_BASE=/tmp fi # Trap all exit signals trap cleanup EXIT HUP INT TERM -if ! type mktemp >/dev/null 2>&1; then - DOWNLOAD_TEMP="${DOWNLOAD_BASE}/lxc-oci.$$" - mkdir -p $DOWNLOAD_TEMP +if ! which mktemp >/dev/null 2>&1; then + DOWNLOAD_TEMP="${DOWNLOAD_BASE}/lxc-oci.$$" + mkdir -p "${DOWNLOAD_TEMP}" else - DOWNLOAD_TEMP=$(mktemp -d -p "${DOWNLOAD_BASE}") + DOWNLOAD_TEMP=$(mktemp -d -p "${DOWNLOAD_BASE}") fi # Download the image +# shellcheck disable=SC2039 skopeo_args=("") if [ -n "$OCI_USERNAME" ]; then - CREDENTIALS="${OCI_USERNAME}" - if [ -n "$OCI_PASSWORD" ]; then - CREDENTIALS="${CREDENTIALS}:${OCI_PASSWORD}" - fi - skopeo_args+=(--src-creds "${CREDENTIALS}") + CREDENTIALS="${OCI_USERNAME}" + + if [ -n "$OCI_PASSWORD" ]; then + CREDENTIALS="${CREDENTIALS}:${OCI_PASSWORD}" + fi + + # shellcheck disable=SC2039 + skopeo_args+=(--src-creds "${CREDENTIALS}") fi + if [ "${OCI_USE_CACHE}" = "true" ]; then - skopeo_args+=(--dest-shared-blob-dir "${DOWNLOAD_BASE}") - skopeo copy ${skopeo_args[@]} "${OCI_URL}" "oci:${DOWNLOAD_TEMP}:latest" - ln -s "${DOWNLOAD_BASE}/sha256" "${DOWNLOAD_TEMP}/blobs/sha256" + # shellcheck disable=SC2039 + # shellcheck disable=SC2068 + skopeo_args+=(--dest-shared-blob-dir "${DOWNLOAD_BASE}") + # shellcheck disable=SC2039 + # shellcheck disable=SC2068 + skopeo copy ${skopeo_args[@]} "${OCI_URL}" "oci:${DOWNLOAD_TEMP}:latest" + ln -s "${DOWNLOAD_BASE}/sha256" "${DOWNLOAD_TEMP}/blobs/sha256" else - skopeo copy ${skopeo_args[@]} "${OCI_URL}" "oci:${DOWNLOAD_TEMP}:latest" + # shellcheck disable=SC2039 + # shellcheck disable=SC2068 + skopeo copy ${skopeo_args[@]} "${OCI_URL}" "oci:${DOWNLOAD_TEMP}:latest" fi echo "Unpacking the rootfs" +# shellcheck disable=SC2039 umoci_args=("") if [ -n "$LXC_MAPPED_UID" ] && [ "$LXC_MAPPED_UID" != "-1" ]; then - umoci_args+=(--rootless) + # shellcheck disable=SC2039 + umoci_args+=(--rootless) fi +# shellcheck disable=SC2039 +# shellcheck disable=SC2068 umoci unpack ${umoci_args[@]} --image "${DOWNLOAD_TEMP}:latest" "${LXC_ROOTFS}.tmp" rmdir "${LXC_ROOTFS}" mv "${LXC_ROOTFS}.tmp/rootfs" "${LXC_ROOTFS}" -OCI_CONF_FILE=$(getconfigpath ${DOWNLOAD_TEMP} latest) +OCI_CONF_FILE=$(getconfigpath "${DOWNLOAD_TEMP}" latest) LXC_CONF_FILE="${LXC_PATH}/config" -entrypoint=$(getep ${OCI_CONF_FILE}) +entrypoint=$(getep "${OCI_CONF_FILE}") echo "lxc.execute.cmd = '${entrypoint}'" >> "${LXC_CONF_FILE}" echo "lxc.mount.auto = proc:mixed sys:mixed cgroup:mixed" >> "${LXC_CONF_FILE}" -environment=$(getenv ${OCI_CONF_FILE}) +environment=$(getenv "${OCI_CONF_FILE}") +# shellcheck disable=SC2039 while read -r line; do - echo "lxc.environment = ${line}" >> "${LXC_CONF_FILE}" + echo "lxc.environment = ${line}" >> "${LXC_CONF_FILE}" done <<< "${environment}" if [ -e "${LXC_TEMPLATE_CONFIG}/common.conf" ]; then - echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/common.conf" >> "${LXC_CONF_FILE}" + echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/common.conf" >> "${LXC_CONF_FILE}" fi if [ -n "$LXC_MAPPED_UID" ] && [ "$LXC_MAPPED_UID" != "-1" ] && [ -e "${LXC_TEMPLATE_CONFIG}/userns.conf" ]; then - echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/userns.conf" >> "${LXC_CONF_FILE}" + echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/userns.conf" >> "${LXC_CONF_FILE}" fi if [ -e "${LXC_TEMPLATE_CONFIG}/oci.common.conf" ]; then - echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/oci.common.conf" >> "${LXC_CONF_FILE}" + echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/oci.common.conf" >> "${LXC_CONF_FILE}" fi if [ "${OCI_USE_DHCP}" = "true" ]; then - echo "lxc.hook.start-host = ${LXC_HOOK_DIR}/dhclient" >> "${LXC_CONF_FILE}" - echo "lxc.hook.stop = ${LXC_HOOK_DIR}/dhclient" >> "${LXC_CONF_FILE}" + echo "lxc.hook.start-host = ${LXC_HOOK_DIR}/dhclient" >> "${LXC_CONF_FILE}" + echo "lxc.hook.stop = ${LXC_HOOK_DIR}/dhclient" >> "${LXC_CONF_FILE}" fi echo "lxc.uts.name = ${LXC_NAME}" >> "${LXC_CONF_FILE}" # set the hostname -cat < ${LXC_ROOTFS}/etc/hostname +cat < "${LXC_ROOTFS}/etc/hostname" ${LXC_NAME} EOF # set minimal hosts -cat < ${LXC_ROOTFS}/etc/hosts +cat < "${LXC_ROOTFS}/etc/hosts" 127.0.0.1 localhost 127.0.1.1 ${LXC_NAME} ::1 localhost ip6-localhost ip6-loopback @@ -342,18 +362,21 @@ ff02::1 ip6-allnodes ff02::2 ip6-allrouters EOF -uidgid=($(getuidgid ${OCI_CONF_FILE})) +# shellcheck disable=SC2039 +uidgid=($(getuidgid "${OCI_CONF_FILE}")) +# shellcheck disable=SC2039 echo "lxc.init.uid = ${uidgid[0]}" >> "${LXC_CONF_FILE}" +# shellcheck disable=SC2039 echo "lxc.init.gid = ${uidgid[1]}" >> "${LXC_CONF_FILE}" -cwd=$(getcwd ${OCI_CONF_FILE}) +cwd=$(getcwd "${OCI_CONF_FILE}") echo "lxc.init.cwd = ${cwd}" >> "${LXC_CONF_FILE}" if [ -n "$LXC_MAPPED_UID" ] && [ "$LXC_MAPPED_UID" != "-1" ]; then - chown $LXC_MAPPED_UID $LXC_PATH/config $LXC_PATH/fstab >/dev/null 2>&1 || true + chown "$LXC_MAPPED_UID" "$LXC_PATH/config" "$LXC_PATH/fstab" > /dev/null 2>&1 || true fi if [ -n "$LXC_MAPPED_GID" ] && [ "$LXC_MAPPED_GID" != "-1" ]; then - chgrp $LXC_MAPPED_GID $LXC_PATH/config $LXC_PATH/fstab >/dev/null 2>&1 || true + chgrp "$LXC_MAPPED_GID" "$LXC_PATH/config" "$LXC_PATH/fstab" > /dev/null 2>&1 || true fi exit 0 From ea8fa04fc89ae566a336514ef069ee66cf5330d2 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Tue, 27 Feb 2018 14:12:50 +0100 Subject: [PATCH 12/12] lxc-local: add --mapped-{g,u}id flags Signed-off-by: Christian Brauner --- templates/lxc-local.in | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/templates/lxc-local.in b/templates/lxc-local.in index 20c0c35c3..552a4946d 100644 --- a/templates/lxc-local.in +++ b/templates/lxc-local.in @@ -69,7 +69,8 @@ LXC internal arguments (do not pass manually!): [ --name ]: The container name [ --path ]: The path to the container [ --rootfs ]: The path to the container's rootfs - +[ --mapped-uid ]: A uid map (user namespaces) +[ --mapped-gid ]: A gid map (user namespaces) EOF return 0 } @@ -88,6 +89,8 @@ while :; do --rootfs) LXC_ROOTFS="$2"; shift 2;; -m|--metadata) LXC_CONFIG="$2"; shift 2;; -f|--fstree) LXC_FSTREE="$2"; shift 2;; + --mapped-uid) LXC_MAPPED_UID="$2"; shift 2;; + --mapped-gid) LXC_MAPPED_GID="$2"; shift 2;; *) break;; esac done