Merge pull request #2164 from brauner/2018-02-14/add_flag_to_compile_tools

tree-wide: rm {lua,python3} bindings, rm deprecated binaries, rm deprecated templates, add --{disable,enable}-{commands,tools} flag
This commit is contained in:
Stéphane Graber 2018-02-28 14:13:52 -05:00 committed by GitHub
commit a98bd0bd8d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
96 changed files with 840 additions and 22786 deletions

6
.gitignore vendored
View File

@ -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
@ -69,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

View File

@ -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

View File

@ -13,14 +13,6 @@ EXTRA_DIST = \
RPMARGS =
if ENABLE_LUA
RPMARGS += --with lua
endif
if ENABLE_PYTHON
RPMARGS += --with python
endif
pcdatadir = $(libdir)/pkgconfig
pcdata_DATA = lxc.pc

View File

@ -20,7 +20,7 @@
# allow pre-mount hooks to stage mounts under /var/lib/lxc/<container>/
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,

View File

@ -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
}

View File

@ -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 \
templatesconfig_DATA = 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

View File

@ -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

View File

@ -1,2 +0,0 @@
# This derives from the global userns config.
lxc.include = @LXCTEMPLATECONFIG@/userns.conf

View File

@ -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

View File

@ -1,2 +0,0 @@
# This derives from the global userns config
lxc.include = @LXCTEMPLATECONFIG@/userns.conf

View File

@ -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

View File

@ -1,2 +0,0 @@
# This derives from the global userns config
lxc.include = @LXCTEMPLATECONFIG@/userns.conf

View File

@ -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

View File

@ -1,2 +0,0 @@
# This derives from the global userns config
lxc.include = @LXCTEMPLATECONFIG@/userns.conf

View File

@ -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

View File

@ -1,2 +0,0 @@
# This derives from the global userns config
lxc.include = @LXCTEMPLATECONFIG@/userns.conf

View File

@ -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

View File

@ -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.

View File

@ -1,2 +0,0 @@
# This derives from the global userns config
lxc.include = @LXCTEMPLATECONFIG@/userns.conf

View File

@ -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

View File

@ -1,2 +0,0 @@
# This derives from the global userns config
lxc.include = @LXCTEMPLATECONFIG@/userns.conf

View File

@ -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

View File

@ -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

View File

@ -1,2 +0,0 @@
# This derives from the global userns config
lxc.include = @LXCTEMPLATECONFIG@/userns.conf

View File

@ -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

View File

@ -1,2 +0,0 @@
# This derives from the global userns config
lxc.include = @LXCTEMPLATECONFIG@/userns.conf

View File

@ -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/

View File

@ -1,2 +0,0 @@
# This derives from the global userns config
lxc.include = @LXCTEMPLATECONFIG@/userns.conf

View File

@ -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

View File

@ -1,2 +0,0 @@
# This derives from the global userns config
lxc.include = @LXCTEMPLATECONFIG@/userns.conf

View File

@ -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

View File

@ -1,2 +0,0 @@
# This derives from the global userns config
lxc.include = @LXCTEMPLATECONFIG@/userns.conf

View File

@ -1,4 +0,0 @@
# This derives from the main Ubuntu config
lxc.include = @LXCTEMPLATECONFIG@/ubuntu.common.conf
lxc.hook.clone = @LXCHOOKDIR@/ubuntu-cloud-prep

View File

@ -1,2 +0,0 @@
# This derives from the main Ubuntu lucid config
lxc.include = @LXCTEMPLATECONFIG@/ubuntu.lucid.conf

View File

@ -1,2 +0,0 @@
# This derives from the main Ubuntu userns config
lxc.include = @LXCTEMPLATECONFIG@/ubuntu.userns.conf

View File

@ -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

View File

@ -1,2 +0,0 @@
# Ubuntu 10.04 LTS doesn't have /dev/lxc/
lxc.tty.dir =

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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]])],
@ -363,29 +356,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]])],
@ -416,53 +386,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]])],
@ -477,6 +400,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]])],
@ -731,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
@ -781,7 +682,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
@ -794,7 +694,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
@ -830,7 +729,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
@ -843,7 +741,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
@ -868,7 +765,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
@ -881,7 +777,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
@ -903,42 +798,17 @@ 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
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
src/lua-lxc/Makefile
src/tests/Makefile
src/tests/lxc-test-usernic
@ -950,6 +820,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
@ -968,10 +871,6 @@ PAM:
- PAM module: $enable_pam
- cgroup PAM module: $pamdir
Bindings:
- lua: $enable_lua
- python3: $enable_python
Documentation:
- examples: $enable_examples
- API documentation: $enable_api_docs

View File

@ -15,8 +15,13 @@ EXTRA_DIST = \
FAQ.txt
if ENABLE_DOCBOOK
man_MANS = \
lxc-attach.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 \
@ -38,23 +43,13 @@ man_MANS = \
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
lxc-wait.1
endif
if ENABLE_COMMANDS
man_MANS += lxc-update-config.1 \
lxc-user-nic.1 \
lxc-usernsexec.1
endif
%.1 : %.sgml

View File

@ -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

View File

@ -1,386 +0,0 @@
<!--
lxc: linux Container library
(C) Copyright IBM Corp. 2007, 2008
Authors:
Daniel Lezcano <daniel.lezcano at free.fr>
Serge Hallyn <serge.hallyn at ubuntu.com>
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
Translated into Japanese
by KATOH Yasufumi <karma at jazz.email.ne.jp>
-->
<!DOCTYPE refentry PUBLIC @docdtd@ [
<!ENTITY commonoptions SYSTEM "@builddir@/common_options.sgml">
<!ENTITY seealso SYSTEM "@builddir@/see_also.sgml">
]>
<refentry>
<docinfo><date>@LXC_GENERATE_DATE@</date></docinfo>
<refmeta>
<refentrytitle>lxc-clone</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>lxc-clone</refname>
<refpurpose>
<!--
clone a new container from an existing one.
-->
既存のコンテナからの新しいコンテナのクローン
</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>lxc-clone</command>
<arg choice="opt">-s </arg>
<arg choice="opt">-K </arg>
<arg choice="opt">-M </arg>
<arg choice="opt">-H </arg>
<arg choice="opt">-B <replaceable>backingstore</replaceable></arg>
<arg choice="opt">-L <replaceable>fssize</replaceable></arg>
<arg choice="opt">-p <replaceable>lxcpath</replaceable></arg>
<arg choice="opt">-P <replaceable>newlxcpath</replaceable></arg>
<arg choice="opt">-R </arg>
<arg choice="req">-o <replaceable>orig</replaceable></arg>
<arg choice="req">-n <replaceable>new</replaceable></arg>
<arg choice="opt">-- hook arguments</arg>
</cmdsynopsis>
<cmdsynopsis>
<command>lxc-clone</command>
<arg choice="opt">-s </arg>
<arg choice="opt">-K </arg>
<arg choice="opt">-M </arg>
<arg choice="opt">-H </arg>
<arg choice="opt">-B <replaceable>backingstore</replaceable></arg>
<arg choice="opt">-L <replaceable>fssize</replaceable></arg>
<arg choice="opt">-p <replaceable>lxcpath</replaceable></arg>
<arg choice="opt">-P <replaceable>newlxcpath</replaceable></arg>
<arg choice="opt">-R </arg>
<arg choice="req">orig</arg>
<arg choice="req">new</arg>
<arg choice="opt">-- hook arguments</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title><!-- Description -->説明</title>
<para>
<!--
<command>lxc-clone</command> 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.
-->
<command>lxc-clone</command> は、新しいコンテナを既に存在するコンテナのクローンとして作製します。
クローンは 2 つのタイプをサポートします: コピーとスナップショットです。
コピータイプのクローンは元のコンテナから新しいコンテナへ root ファイルシステムをコピーします。
スナップショットファイルシステムは、バッキングストアのスナップショット機能を使い、元のコンテナの非常に小さな copy-on-write でのスナップショットを作製します。
スナップショットでのクローンは、新しいコンテナのバッキングストアとしてスナップショット機能のサポートが必要になります。
現時点では、このようなバッキングストアとしては aufs, btrfs, lvm, overlayfs, zfs のみをサポートします。
LVM デバイスはスナップショットのスナップショットはサポートしていません。
</para>
<para>
<!--
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
<replaceable>-B overlayfs</replaceable> arguments.
-->
新しいコンテナのバッキングストアは、オーバーレイタイプのコンテナを除いては元のコンテナのタイプと同じになります。
ディレクトリバックエンドのコンテナのスナップショットを aufs もしくは overlayfs で作成することは可能です。
例えば、overlayfs の場合は <replaceable>-B overlayfs</replaceable> という引数を使って指定することが可能です。
</para>
<para>
<!--
The names of the original and new container can be given (in that order)
after all options, or can be specified with the
<replaceable>-o</replaceable> and <replaceable>-n</replaceable> options,
respectively.
-->
元のコンテナと新しいコンテナの名前は、全てのオプションの後に順番に与えることも、<replaceable>-o</replaceable> と <replaceable>-n</replaceable> オプションを使ってそれぞれ指定することも可能です。
</para>
</refsect1>
<refsect1>
<title><!-- Options -->オプション</title>
<variablelist>
<varlistentry>
<term>
<option>-s, --snapshot</option>
</term>
<listitem>
<para>
<!--
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.
-->
新しいコンテナの rootfs はオリジナルのスナップショットとなります。
このオプションはバッキングストアが LVM か btrfs か zfs の時に使用できます。
また、スナップショットを aufs か overlayfs で取得したい場合は指定する必要があります。
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-K, --keepname</option>
</term>
<listitem>
<para>
<!--
Do not change the hostname of the container (in the root
filesystem).
-->
(root ファイルシステム内では) コンテナのホスト名を変更しません。
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-M, --keepmac</option>
</term>
<listitem>
<para>
<!--
Use the same MAC address as the original container, rather than
generating a new random one.
-->
新しい MAC アドレスをランダムに生成せずに、元のコンテナと同じ MAC アドレスを使用します。
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-H, --copyhooks</option>
</term>
<listitem>
<para>
<!--
Copy all mount hooks into the new container's directory, and
update any lxcpaths and container names as needed.
-->
全てのマウントフックを新しいコンテナのディレクトリにコピーします。
そして、lxcpath とコンテナ名を必要に応じて更新します。
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-L, --fssize <replaceable>fssize</replaceable></option>
</term>
<listitem>
<para>
<!--
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.
-->
ブロックデバイスのバックエンドのコンテナの場合、新しいブロックデバイスのサイズ。
デフォルトでは、新しいデバイスは元のデバイスと同じサイズとなります。
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-p, --lxcpath <replaceable>lxcpath</replaceable></option>
</term>
<listitem>
<para>
<!--
The lxcpath of the original container. By default, the system
wide configured lxcpath will be used.
-->
オリジナルのコンテナの lxcpath。デフォルトでは、システム全体で設定された lxcpath が使われます。
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-P, --newpath <replaceable>newlxcpath</replaceable></option>
</term>
<listitem>
<para>
<!--
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.
-->
新しいコンテナの lxcpath。
デフォルトでは、オリジナルの lxcpath と同じものが使われます。
btrfs のスナップショットの場合は注意が必要で、lxcpath の変更はできない可能性があります。
これは subvolume のスナップショットが、同じ btrfs ファイルシステム上に存在しなければならないからです。
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-B, --backingstore <replaceable>backingstore</replaceable></option>
</term>
<listitem>
<para>
<!--
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.
-->
新しいコンテナで元のコンテナと違うバッキングストアを使う場合のバッキングストアを選択します。
デフォルトでは元のコンテナと同じものが使われます。
現時点では、バッキングストアの変更は、ディレクトリバックエンドのコンテナに対する aufs と overlayfs のスナップショットに対してのみサポートされます。
有効なバッキングストアは dir(directory), aufs, btrfs, lvm, zfs, loop, overlayfs です。
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-R, --rename</option>
</term>
<listitem>
<para>
<!--
Rename an existing container.
<replaceable>orig</replaceable> is renamed <replaceable>new</replaceable>.
-->
コンテナの名前を変更します。<replaceable>orig</replaceable> を <replaceable>new</replaceable> という名前に変更します。
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-o, --orig <replaceable>orig</replaceable></option>
</term>
<listitem>
<para>
<!--
The name of the original container to clone.
-->
クローンしたい元のコンテナの名前。
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-n, --new <replaceable>new</replaceable></option>
</term>
<listitem>
<para>
<!--
The name of the new container to create.
-->
作製する新しいコンテナの名前。
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Clone hook</title>
<para>
<!--
If the container being cloned has one or more <filename>lxc.hook.clone</filename>
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
<command>lxc-clone</command> will be passed to the hook program starting at
argument 4. The <filename>LXC_ROOTFS_MOUNT</filename> environment variable gives
the path under which the container's root filesystem is mounted. The
configuration file pathname is stored in <filename>LXC_CONFIG_FILE</filename>, the
new container name in <filename>LXC_NAME</filename>, the old container name in
<filename>LXC_SRC_NAME</filename>, and the path or device on which
the rootfs is located is in <filename>LXC_ROOTFS_PATH</filename>.
-->
クローンされるコンテナに 1 つ以上の <filename>lxc.hook.clone</filename> の指定が存在する場合、指定されたフックは新しいコンテナに対して呼ばれます。
クローンフックに渡される最初の 3 つの引数は、コンテナ名、セクション ('lxc')、フックタイプ ('clone') となります。
<command>lxc-clone</command> に渡される追加の引数は、フックプログラムに渡される引数の 4 番目以降となります。
<filename>LXC_ROOTFS_MOUNT</filename> 環境変数には、コンテナの root ファイルシステムがマウントされるパスが与えられます。
設定ファイルのパス名は <filename>LXC_CONFIG_FILE</filename> に、新しいコンテナ名は <filename>LXC_NAME</filename>、古いコンテナ名は <filename>LXC_SRC_NAME</filename> に、rootfs のあるパスまたはデバイスは <filename>LXC_ROOTFS_PATH</filename> に保存されます。
</para>
</refsect1>
<refsect1>
<title><!-- Notes -->注意</title>
<para>
<!--
<command>lxc-clone</command> is deprecated in favor of
<command>lxc-copy</command>.
-->
<command>lxc-clone</command> は <command>lxc-copy</command> に置き換えられ、廃止される予定です。
</para>
</refsect1>
&seealso;
<refsect1>
<title><!-- Author -->作者</title>
<para>Serge Hallyn <email>serge.hallyn@ubuntu.com</email></para>
</refsect1>
</refentry>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:2
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:nil
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
-->

View File

@ -1,316 +0,0 @@
<!--
(C) Copyright Canonical Ltd. 2013
Authors:
Stéphane Graber <stgraber@ubuntu.com>
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
Translated into Japanese
by KATOH Yasufumi <karma at jazz.email.ne.jp>
-->
<!DOCTYPE refentry PUBLIC @docdtd@ [
<!ENTITY seealso SYSTEM "@builddir@/see_also.sgml">
]>
<refentry>
<docinfo><date>@LXC_GENERATE_DATE@</date></docinfo>
<refmeta>
<refentrytitle>lxc-start-ephemeral</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>lxc-start-ephemeral</refname>
<refpurpose>
<!--
start an ephemeral copy of an existing container
-->
存在するコンテナの一時的なコピーを起動
</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>lxc-start-ephemeral</command>
<arg choice="opt">-o</arg>
<arg choice="opt">-n</arg>
<arg choice="opt">-d</arg>
<arg choice="opt">--bdir</arg>
<arg choice="opt">--user</arg>
<arg choice="opt">--key</arg>
<arg choice="opt">--storage-type</arg>
<arg choice="opt">--union-type</arg>
<arg choice="opt">--keep-data</arg>
<arg choice="opt">COMMAND</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title><!-- Description -->説明</title>
<para>
<!--
<command>lxc-start-ephemeral</command> start an ephemeral copy of an
existing container.
-->
<command>lxc-start-ephemeral</command> は、存在するコンテナの一時的なコピーからコンテナを起動します。
</para>
</refsect1>
<refsect1>
<title><!-- Options -->オプション</title>
<variablelist>
<varlistentry>
<term>
<option>-o, --orig <replaceable>orig</replaceable></option>
</term>
<listitem>
<para>
<!--
Original container name
-->
コピー元のコンテナ名
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-n, --name <replaceable>name</replaceable></option>
</term>
<listitem>
<para>
<!--
Name of the ephemeral container (defaults to a random suffix).
-->
一時的なコンテナの名前 (デフォルトではランダムなサフィックスが付与されます)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-d, --daemon</option>
</term>
<listitem>
<para>
<!--
Start the container in background and print the name and IP.
This option can't be used if a command is passed.
-->
コンテナをバックグラウンドで実行し、名前と IP アドレスを表示します。
このオプションはコマンドを実行させたいときには使用することはできません。
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-b, --bdir <replaceable>bdir</replaceable></option>
</term>
<listitem>
<para>
<!--
Directory to bind mount into container.
Can be passed multiple times.
-->
コンテナ内にバインドマウントするためのディレクトリ。
複数回指定できます。
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-u, --user <replaceable>user</replaceable></option>
</term>
<listitem>
<para>
<!--
The user to connect to the container as.
Used when passing a command to lxc-start-ephemeral.
-->
コンテナに接続するためのユーザ。
lxc-start-ephemeral にコマンドを指定するときに使います。
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-S, --key <replaceable>key</replaceable></option>
</term>
<listitem>
<para>
<!--
Copy the provided SSH public key into the container.
-->
コンテナ内にコピーする既存の SSH 公開鍵。
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-s, --storage-type <replaceable>storage type</replaceable></option>
</term>
<listitem>
<para>
<!--
Specify the type of storage used by the container. Valid types are tmpfs or dir.
-->
コンテナが使うストレージのタイプ。tmpfs か dir を指定できます。
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-U, --union-type <replaceable>union type</replaceable></option>
</term>
<listitem>
<para>
<!--
Force a specific union file system.
Can be one of: overlayfs aufs
-->
指定した union ファイルシステムを使用します。
overlayfs か aufs のどちらかが使用できます。
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-k, --keep-data</option>
</term>
<listitem>
<para>
<!--
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).
-->
tmpfs の代わりに永続的なバックエンドを使用します。このオプションを使うことにより、もはや一時的なコンテナではないので、lxc-stop や lxc-start を使用することができます (オーバーレイな状態ですが、永続的です)。
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>COMMAND</option>
</term>
<listitem>
<para>
<!--
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.
-->
即座に指定したコマンドをコンテナ内で実行します。
コマンドを実行する際、カーネルがサポートしている場合は lxc-start-ephemeral は attach を使います。
カーネルがサポートしていない場合は ssh を使います。
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>See Also</title>
<simpara>
<citerefentry>
<refentrytitle>lxc-start</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>,
</simpara>
</refsect1>
<refsect1>
<title><!-- Examples -->例</title>
<variablelist>
<varlistentry>
<term>lxc-start-ephemeral -o p1</term>
<listitem>
<para>
<!--
Simply start an ephemeral container and attach to the console.
This container will be based on existing container "p1".
-->
単に一時的なコンテナを開始させ、コンソールにアタッチします。
このコンテナは "p1" という既存のコンテナを基にします。
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>lxc-start-ephemeral -o p1 -n p1-ephemeral -d</term>
<listitem>
<para>
<!--
Start an ephemeral container based on p1 called p1-ephemeral and
print its IP and name to the console instead of attaching.
-->
p1 を基にした一時的なコンテナを開始し、コンソールにアタッチする代わりに IP アドレスと名前を表示します。
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title><!-- Notes -->注意</title>
<para>
<!--
<command>lxc-start-ephemeral</command> is deprecated in favor of
<command>lxc-copy</command>.
-->
<command>lxc-start-ephemeral</command> は <command>lxc-copy</command> に置き換えられ、廃止される予定です。
</para>
</refsect1>
&seealso;
<refsect1>
<title><!-- Author -->作者</title>
<para>Stéphane Graber <email>stgraber@ubuntu.com</email></para>
</refsect1>
</refentry>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:2
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:nil
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
-->

View File

@ -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

View File

@ -1,377 +0,0 @@
<!--
lxc: linux Container library
(C) Copyright IBM Corp. 2007, 2008
Authors:
Daniel Lezcano <daniel.lezcano at free.fr>
Serge Hallyn <serge.hallyn at ubuntu.com>
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
Translated into Korean
by Sungbae Yoo <sungbae.yoo at samsung.com>
-->
<!DOCTYPE refentry PUBLIC @docdtd@ [
<!ENTITY commonoptions SYSTEM "@builddir@/common_options.sgml">
<!ENTITY seealso SYSTEM "@builddir@/see_also.sgml">
]>
<refentry>
<docinfo><date>@LXC_GENERATE_DATE@</date></docinfo>
<refmeta>
<refentrytitle>lxc-clone</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>lxc-clone</refname>
<refpurpose>
<!--
clone a new container from an existing one.
-->
존재하는 컨테이너를 새로운 컨테이너로 복제
</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>lxc-clone</command>
<arg choice="opt">-s </arg>
<arg choice="opt">-K </arg>
<arg choice="opt">-M </arg>
<arg choice="opt">-H </arg>
<arg choice="opt">-B <replaceable>backingstore</replaceable></arg>
<arg choice="opt">-L <replaceable>fssize</replaceable></arg>
<arg choice="opt">-p <replaceable>lxcpath</replaceable></arg>
<arg choice="opt">-P <replaceable>newlxcpath</replaceable></arg>
<arg choice="opt">-R </arg>
<arg choice="req">-o <replaceable>orig</replaceable></arg>
<arg choice="req">-n <replaceable>new</replaceable></arg>
<arg choice="opt">-- hook arguments</arg>
</cmdsynopsis>
<cmdsynopsis>
<command>lxc-clone</command>
<arg choice="opt">-s </arg>
<arg choice="opt">-K </arg>
<arg choice="opt">-M </arg>
<arg choice="opt">-H </arg>
<arg choice="opt">-B <replaceable>backingstore</replaceable></arg>
<arg choice="opt">-L <replaceable>fssize</replaceable></arg>
<arg choice="opt">-p <replaceable>lxcpath</replaceable></arg>
<arg choice="opt">-P <replaceable>newlxcpath</replaceable></arg>
<arg choice="opt">-R </arg>
<arg choice="req">orig</arg>
<arg choice="req">new</arg>
<arg choice="opt">-- hook arguments</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title><!-- Description -->설명</title>
<para>
<!--
<command>lxc-clone</command> 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.
-->
<command>lxc-clone</command>는 존재하는 컨테이너를 복제하여 새로운 컨테이너를 생성한다. 복사, 스냅샷의 두가지 형태의 복제가 지원된다.
복사는 원본 컨테이너의 루트 파일시스템을 그대로 새 컨테이너로 복사한다..
스냅샷은 저장소의 스냅샷 기능을 이용하여 원본 컨테이너의 copy-on-write 형태로 매우 작은 스냅샷을 생성한다. 스냅샷을 사용하기 위해서는 새 컨테이너의 저장소가 스냅샷 기능을 지원하여야 한다. 현재 스냅샷 기능을 지원하는 것은 aufs, btrfs, lvm, overlayfs, zfs 정도이다. lvm은 스냅샷의 스냅샷은 지원하지 않는다.
</para>
<para>
<!--
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
<replaceable>-B overlayfs</replaceable> arguments.
-->
오버레이 컨테이너들을 제외하면, 새 컨테이너의 저장소는 원본과 같은 종류를 사용한다.
aufs와 overlayfs의 스냅샷은 디렉토리로 구성된 컨테이너로 생성할 수 있다. overlayfs의 경우 <replaceable>-B overlayfs</replaceable> 인수를 통해 이를 지정할 수 있다.
</para>
<para>
<!--
The names of the original and new container can be given (in that order)
after all options, or can be specified with the
<replaceable>-o</replaceable> and <replaceable>-n</replaceable> options,
respectively.
-->
원본 컨테이너와 새 컨테이너의 이름은 모든 옵션 뒤에 원본, 새 컨테이너 순으로 지정할 수 있다. 또는 <replaceable>-o</replaceable>과 <replaceable>-n</replaceable> 옵션을 사용하여 지정할 수 있다.
</para>
</refsect1>
<refsect1>
<title><!-- Options -->옵션</title>
<variablelist>
<varlistentry>
<term>
<option>-s, --snapshot</option>
</term>
<listitem>
<para>
<!--
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.
-->
새로 생성하는 컨테이너의 루트 파일시스템은 원본의 스냅샷으로 한다. 이 옵션은 저장소가 lvm, btrfs, zfs 일때 지정할 수 있다. 또한 aufs나 overlayfs를 이용한 스냅샷을 원할때만 지정해야 한다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-K, --keepname</option>
</term>
<listitem>
<para>
<!--
Do not change the hostname of the container (in the root
filesystem).
-->
(루트 파일시스템에서) 컨테이너의 호스트 이름을 변경하지 않는다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-M, --keepmac</option>
</term>
<listitem>
<para>
<!--
Use the same MAC address as the original container, rather than
generating a new random one.
-->
새로 무작위한 주소를 만들지 않고, 원본과 같은 MAC 주소를 사용한다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-H, --copyhooks</option>
</term>
<listitem>
<para>
<!--
Copy all mount hooks into the new container's directory, and
update any lxcpaths and container names as needed.
-->
모든 마운트 훅들을 새 컨테이너의 디렉토리로 복사한다. 그리고 lxcpath와 컨테이너 이름을 필요에 따라 갱신한다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-L, --fssize <replaceable>fssize</replaceable></option>
</term>
<listitem>
<para>
<!--
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.
-->
블록장치로 구성된 컨테이너의 경우, 새로운 블록 장치의 크기.
기본으로 새 디바이스는 원본과 같은 크기로 만들어진다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-p, --lxcpath <replaceable>lxcpath</replaceable></option>
</term>
<listitem>
<para>
<!--
The lxcpath of the original container. By default, the system
wide configured lxcpath will be used.
-->
원본 컨테이너의 lxcpath. 기본값은 시스템 전역으로 설정되어 잇는 lxcpath를 사용한다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-P, --newpath <replaceable>newlxcpath</replaceable></option>
</term>
<listitem>
<para>
<!--
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.
-->
새로 생성될 컨테이너의 lxcpath.
기본값은 원본 컨테이너의 lxcpath와 같다.
btrfs의 스냅샷의 경우 lxcpath 변경이 불가능 할 수 있음을 주의해야 한다. 왜냐하면 서브볼륨 스냅샷이 같은 btrfs 파일시스템 내에 있어야 하기 때문이다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-B, --backingstore <replaceable>backingstore</replaceable></option>
</term>
<listitem>
<para>
<!--
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.
-->
새 컨테이너의 저장소를 선택한다.
기본 값은 원본 컨테이너가 쓰던 것과 같은 것으로 되어 있다.
현재 저장소를 다른 것으로 변경하는 것은 디렉토리로 구성된 컨테이너의 aufs와 overlayfs 스냅샷에서만 지원된다.
가능한 값은 dir(디렉토리), aufs, btrfs, lvm zfs, loop 그리고 ovelayfs 이다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-R, --rename</option>
</term>
<listitem>
<para>
<!--
Rename an existing container.
<replaceable>orig</replaceable> is renamed <replaceable>new</replaceable>.
-->
컨테이너의 이름을 변경한다. <replaceable>orig</replaceable>를 <replaceable>new</replaceable>로 이름을 바꾼다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-o, --orig <replaceable>orig</replaceable></option>
</term>
<listitem>
<para>
<!--
The name of the original container to clone.
-->
복제할 원본 컨테이너의 이름.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-n, --new <replaceable>new</replaceable></option>
</term>
<listitem>
<para>
<!--
The name of the new container to create.
-->
생성할 새 컨테이너의 이름.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Clone hook</title>
<para>
<!--
If the container being cloned has one or more <filename>lxc.hook.clone</filename>
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
<command>lxc-clone</command> will be passed to the hook program starting at
argument 4. The <filename>LXC_ROOTFS_MOUNT</filename> environment variable gives
the path under which the container's root filesystem is mounted. The
configuration file pathname is stored in <filename>LXC_CONFIG_FILE</filename>, the
new container name in <filename>LXC_NAME</filename>, the old container name in
<filename>LXC_SRC_NAME</filename>, and the path or device on which
the rootfs is located is in <filename>LXC_ROOTFS_PATH</filename>.
-->
만약 복제되는 컨테이너가 1개 이상의 <filename>lxc.hook.clone</filename>을 지정했다면, 지정된 훅은 새 컨테이너가 생성될 때 실행될 것이다.
먼저 컨테이너 이름, 섹션('lxc'), 훅 종류('clone') 3개의 인수가 복제 훅에 전달 된다. 그리고 4번째 인수 부터는 <command>lxc-clone</command>로 넘겨줄 수 있다.
<filename>LXC_ROOTFS_MOUNT</filename> 환경변수는 컨테이너의 루트 파일시스템이 마운트되어 있는 경로를 넘겨준다.
새 컨테이너의 이름은 <filename>LXC_NAME</filename> 변수에, 이전 컨테이너의 이름은 <filename>LXC_SRC_NAME</filename> 환경변수에 담겨 있다. 그리고 루트 파일시스템이 위치하고 있는 곳은 <filename>LXC_ROOTFS_PATH</filename>로 넘겨준다.
</para>
</refsect1>
<refsect1>
<title><!-- Notes -->주의</title>
<para>
<!--
<command>lxc-clone</command> is deprecated in favor of
<command>lxc-copy</command>.
-->
<command>lxc-clone</command>는 <command>lxc-copy</command>로 대체되었으며, 제거될 예정이다.
</para>
</refsect1>
&seealso;
<refsect1>
<title><!-- Author -->저자</title>
<para>Serge Hallyn <email>serge.hallyn@ubuntu.com</email></para>
</refsect1>
</refentry>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:2
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:nil
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
-->

View File

@ -1,318 +0,0 @@
<!--
(C) Copyright Canonical Ltd. 2013
Authors:
Stéphane Graber <stgraber@ubuntu.com>
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
Translated into Korean
by Sungbae Yoo <sungbae.yoo at samsung.com>
-->
<!DOCTYPE refentry PUBLIC @docdtd@ [
<!ENTITY seealso SYSTEM "@builddir@/see_also.sgml">
]>
<refentry>
<docinfo><date>@LXC_GENERATE_DATE@</date></docinfo>
<refmeta>
<refentrytitle>lxc-start-ephemeral</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>lxc-start-ephemeral</refname>
<refpurpose>
<!--
start an ephemeral copy of an existing container
-->
존재하는 컨테이너를 임시 복사본으로 시작
</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>lxc-start-ephemeral</command>
<arg choice="opt">-o</arg>
<arg choice="opt">-n</arg>
<arg choice="opt">-d</arg>
<arg choice="opt">--bdir</arg>
<arg choice="opt">--user</arg>
<arg choice="opt">--key</arg>
<arg choice="opt">--storage-type</arg>
<arg choice="opt">--union-type</arg>
<arg choice="opt">--keep-data</arg>
<arg choice="opt">COMMAND</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title><!-- Description -->설명</title>
<para>
<!--
<command>lxc-start-ephemeral</command> start an ephemeral copy of an
existing container.
-->
<command>lxc-start-ephemeral</command>는 존재하는 컨테이너를 임시 복사본으로 시작시킨다.
</para>
</refsect1>
<refsect1>
<title><!-- Options -->옵션</title>
<variablelist>
<varlistentry>
<term>
<option>-o, --orig <replaceable>orig</replaceable></option>
</term>
<listitem>
<para>
<!--
Original container name
-->
원본 컨테이너 이름
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-n, --name <replaceable>name</replaceable></option>
</term>
<listitem>
<para>
<!--
Name of the ephemeral container (defaults to a random suffix).
-->
임시 컨테이너의 이름 (기본값은 무작위한 접미사를 붙이는 것)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-d, --daemon</option>
</term>
<listitem>
<para>
<!--
Start the container in background and print the name and IP.
This option can't be used if a command is passed.
-->
컨테이너를 백그라운드로 시작한다. 그리고 이름과 IP를 표시한다.
옵션으로 명령어를 넘길 경우, 이 옵션은 사용하지 못한다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-b, --bdir <replaceable>bdir</replaceable></option>
</term>
<listitem>
<para>
<!--
Directory to bind mount into container.
Can be passed multiple times.
-->
컨테이너로 바인드 마운트할 디렉토리.
여러번 인자로 넘겨줄 수 있다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-u, --user <replaceable>user</replaceable></option>
</term>
<listitem>
<para>
<!--
The user to connect to the container as.
Used when passing a command to lxc-start-ephemeral.
-->
컨테이너에 연결할 사용자.
lxc-start-ephemeral로 명령어를 넘길때 사용한다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-S, --key <replaceable>key</replaceable></option>
</term>
<listitem>
<para>
<!--
Copy the provided SSH public key into the container.
-->
컨테이너 안으로 지정한 SSH 공개키를 복사한다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-s, --storage-type <replaceable>storage type</replaceable></option>
</term>
<listitem>
<para>
<!--
Specify the type of storage used by the container. Valid types are tmpfs or dir.
-->
컨테이너가 사용하는 저장소 형태를 지정한다. 가능한 형태는 tmpfs, dir이다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-U, --union-type <replaceable>union type</replaceable></option>
</term>
<listitem>
<para>
<!--
Force a specific union file system.
Can be one of: overlayfs aufs
-->
지정한 union 파일시스템을 사용한다.
가능한 파일시스템은 overlayfs, aufs이다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-k, --keep-data</option>
</term>
<listitem>
<para>
<!--
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).
-->
tmpfs 대신 영구적인 백엔드를 사용한다.
이 옵션을 사용하면, 더이상 임시 컨테이너가 아니기 때문에 lxc-stop이나 lxc-start를 사용할 수 있게 된다. (여전히 오버레이 상태이지만 영구적이다)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>COMMAND</option>
</term>
<listitem>
<para>
<!--
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.
-->
지정한 명령어를 컨테이너 안에서 바로 실행한다.
커널이 attach를 지원하면 attach를 사용하고, 지원하지 않으면 ssh를 사용한다.
이 옵션은 데몬 모드와 같이 사용할 수 없다.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title><!-- See Also -->참조</title>
<simpara>
<citerefentry>
<refentrytitle>lxc-start</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>,
</simpara>
</refsect1>
<refsect1>
<title><!-- Examples -->예제</title>
<variablelist>
<varlistentry>
<term>lxc-start-ephemeral -o p1</term>
<listitem>
<para>
<!--
Simply start an ephemeral container and attach to the console.
This container will be based on existing container "p1".
-->
단순히 임시 복사본 컨테이너를 시작하고, console에 연결한다.
임시 컨테이너는 컨테이너 p1을 기반으로 한다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>lxc-start-ephemeral -o p1 -n p1-ephemeral -d</term>
<listitem>
<para>
<!--
Start an ephemeral container based on p1 called p1-ephemeral and
print its IP and name to the console instead of attaching.
-->
컨테이너 p1을 기반으로 임시 컨테이너 p1-ephemeral을 시작한다.
console에 연결하지 않고, 컨테이너의 IP와 이름을 출력한다.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title><!-- Notes -->주의</title>
<para>
<!--
<command>lxc-start-ephemeral</command> is deprecated in favor of
<command>lxc-copy</command>.
-->
<command>lxc-start-ephemeral</command>는 <command>lxc-copy</command>로 대체되었으며, 제거될 예정이다.
</para>
</refsect1>
&seealso;
<refsect1>
<title><!-- Author -->저자</title>
<para>Stéphane Graber <email>stgraber@ubuntu.com</email></para>
</refsect1>
</refentry>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:2
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:nil
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
-->

View File

@ -1,310 +0,0 @@
<!--
lxc: linux Container library
(C) Copyright IBM Corp. 2007, 2008
Authors:
Daniel Lezcano <daniel.lezcano at free.fr>
Serge Hallyn <serge.hallyn at ubuntu.com>
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
-->
<!DOCTYPE refentry PUBLIC @docdtd@ [
<!ENTITY commonoptions SYSTEM "@builddir@/common_options.sgml">
<!ENTITY seealso SYSTEM "@builddir@/see_also.sgml">
]>
<refentry>
<docinfo><date>@LXC_GENERATE_DATE@</date></docinfo>
<refmeta>
<refentrytitle>lxc-clone</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>lxc-clone</refname>
<refpurpose>
clone a new container from an existing one.
</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>lxc-clone</command>
<arg choice="opt">-s </arg>
<arg choice="opt">-K </arg>
<arg choice="opt">-M </arg>
<arg choice="opt">-H </arg>
<arg choice="opt">-B <replaceable>backingstore</replaceable></arg>
<arg choice="opt">-L <replaceable>fssize</replaceable></arg>
<arg choice="opt">-p <replaceable>lxcpath</replaceable></arg>
<arg choice="opt">-P <replaceable>newlxcpath</replaceable></arg>
<arg choice="opt">-R </arg>
<arg choice="req">-o <replaceable>orig</replaceable></arg>
<arg choice="req">-n <replaceable>new</replaceable></arg>
<arg choice="opt">-- hook arguments</arg>
</cmdsynopsis>
<cmdsynopsis>
<command>lxc-clone</command>
<arg choice="opt">-s </arg>
<arg choice="opt">-K </arg>
<arg choice="opt">-M </arg>
<arg choice="opt">-H </arg>
<arg choice="opt">-B <replaceable>backingstore</replaceable></arg>
<arg choice="opt">-L <replaceable>fssize</replaceable></arg>
<arg choice="opt">-p <replaceable>lxcpath</replaceable></arg>
<arg choice="opt">-P <replaceable>newlxcpath</replaceable></arg>
<arg choice="opt">-R </arg>
<arg choice="req">orig</arg>
<arg choice="req">new</arg>
<arg choice="opt">-- hook arguments</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
<command>lxc-clone</command> 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.
</para>
<para>
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
<replaceable>-B overlayfs</replaceable> arguments.
</para>
<para>
The names of the original and new container can be given (in that order)
after all options, or can be specified with the
<replaceable>-o</replaceable> and <replaceable>-n</replaceable> options,
respectively.
</para>
</refsect1>
<refsect1>
<title>Options</title>
<variablelist>
<varlistentry>
<term>
<option>-s, --snapshot</option>
</term>
<listitem>
<para>
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.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-K, --keepname</option>
</term>
<listitem>
<para>
Do not change the hostname of the container (in the root
filesystem).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-M, --keepmac</option>
</term>
<listitem>
<para>
Use the same MAC address as the original container, rather than
generating a new random one.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-H, --copyhooks</option>
</term>
<listitem>
<para>
Copy all mount hooks into the new container's directory, and
update any lxcpaths and container names as needed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-L, --fssize <replaceable>fssize</replaceable></option>
</term>
<listitem>
<para>
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.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-p, --lxcpath <replaceable>lxcpath</replaceable></option>
</term>
<listitem>
<para>
The lxcpath of the original container. By default, the system
wide configured lxcpath will be used.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-P, --newpath <replaceable>newlxcpath</replaceable></option>
</term>
<listitem>
<para>
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.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-B, --backingstore <replaceable>backingstore</replaceable></option>
</term>
<listitem>
<para>
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.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-R, --rename</option>
</term>
<listitem>
<para>
Rename an existing container.
<replaceable>orig</replaceable> is renamed <replaceable>new</replaceable>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-o, --orig <replaceable>orig</replaceable></option>
</term>
<listitem>
<para>
The name of the original container to clone.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-n, --new <replaceable>new</replaceable></option>
</term>
<listitem>
<para>
The name of the new container to create.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Clone hook</title>
<para>
If the container being cloned has one or more <filename>lxc.hook.clone</filename>
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
<command>lxc-clone</command> will be passed to the hook program starting at
argument 4. The <filename>LXC_ROOTFS_MOUNT</filename> environment variable gives
the path under which the container's root filesystem is mounted. The
configuration file pathname is stored in <filename>LXC_CONFIG_FILE</filename>, the
new container name in <filename>LXC_NAME</filename>, the old container name in
<filename>LXC_SRC_NAME</filename>, and the path or device on which
the rootfs is located is in <filename>LXC_ROOTFS_PATH</filename>.
</para>
</refsect1>
<refsect1>
<title>Notes</title>
<para>
<command>lxc-clone</command> is deprecated in favor of
<command>lxc-copy</command>.
</para>
</refsect1>
&seealso;
<refsect1>
<title>Author</title>
<para>Serge Hallyn <email>serge.hallyn@ubuntu.com</email></para>
</refsect1>
</refentry>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:2
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:nil
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
-->

View File

@ -105,8 +105,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
<para>
<command>lxc-copy</command> creates and optionally starts (ephemeral or
non-ephemeral) copies of existing containers. It replaces
<command>lxc-clone</command> and <command>lxc-start-ephemeral</command>.
non-ephemeral) copies of existing containers.
</para>
<para>
<command>lxc-copy</command> creates copies of existing containers. Copies

View File

@ -1,261 +0,0 @@
<!--
(C) Copyright Canonical Ltd. 2013
Authors:
Stéphane Graber <stgraber@ubuntu.com>
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
-->
<!DOCTYPE refentry PUBLIC @docdtd@ [
<!ENTITY seealso SYSTEM "@builddir@/see_also.sgml">
]>
<refentry>
<docinfo><date>@LXC_GENERATE_DATE@</date></docinfo>
<refmeta>
<refentrytitle>lxc-start-ephemeral</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>lxc-start-ephemeral</refname>
<refpurpose>
start an ephemeral copy of an existing container
</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>lxc-start-ephemeral</command>
<arg choice="opt">-o</arg>
<arg choice="opt">-n</arg>
<arg choice="opt">-d</arg>
<arg choice="opt">--bdir</arg>
<arg choice="opt">--user</arg>
<arg choice="opt">--key</arg>
<arg choice="opt">--storage-type</arg>
<arg choice="opt">--union-type</arg>
<arg choice="opt">--keep-data</arg>
<arg choice="opt">COMMAND</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
<command>lxc-start-ephemeral</command> start an ephemeral copy of an
existing container.
</para>
</refsect1>
<refsect1>
<title>Options</title>
<variablelist>
<varlistentry>
<term>
<option>-o, --orig <replaceable>orig</replaceable></option>
</term>
<listitem>
<para>
Original container name
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-n, --name <replaceable>name</replaceable></option>
</term>
<listitem>
<para>
Name of the ephemeral container (defaults to a random suffix).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-d, --daemon</option>
</term>
<listitem>
<para>
Start the container in background and print the name and IP.
This option can't be used if a command is passed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-b, --bdir <replaceable>bdir</replaceable></option>
</term>
<listitem>
<para>
Directory to bind mount into container.
Can be passed multiple times.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-u, --user <replaceable>user</replaceable></option>
</term>
<listitem>
<para>
The user to connect to the container as.
Used when passing a command to lxc-start-ephemeral.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-S, --key <replaceable>key</replaceable></option>
</term>
<listitem>
<para>
Copy the provided SSH public key into the container.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-s, --storage-type <replaceable>storage type</replaceable></option>
</term>
<listitem>
<para>
Specify the type of storage used by the container. Valid types are tmpfs or dir.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-U, --union-type <replaceable>union type</replaceable></option>
</term>
<listitem>
<para>
Force a specific union file system.
Can be one of: overlayfs aufs
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-k, --keep-data</option>
</term>
<listitem>
<para>
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).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>COMMAND</option>
</term>
<listitem>
<para>
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.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>See Also</title>
<simpara>
<citerefentry>
<refentrytitle>lxc-start</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>,
</simpara>
</refsect1>
<refsect1>
<title>Examples</title>
<variablelist>
<varlistentry>
<term>lxc-start-ephemeral -o p1</term>
<listitem>
<para>
Simply start an ephemeral container and attach to the console.
This container will be based on existing container "p1".
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>lxc-start-ephemeral -o p1 -n p1-ephemeral -d</term>
<listitem>
<para>
Start an ephemeral container based on p1 called p1-ephemeral and
print its IP and name to the console instead of attaching.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Notes</title>
<para>
<command>lxc-start-ephemeral</command> is deprecated in favor of
<command>lxc-copy</command>.
</para>
</refsect1>
&seealso;
<refsect1>
<title>Author</title>
<para>Stéphane Graber <email>stgraber@ubuntu.com</email></para>
</refsect1>
</refentry>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:2
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:nil
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
-->

View File

@ -1897,11 +1897,10 @@ dev/null proc/kcore none bind,relative 0 0
<listitem><para> Section (always 'lxc'). </para></listitem>
<listitem><para> The hook type (i.e. 'clone' or 'pre-mount'). </para></listitem>
<listitem><para> Additional arguments. In the
case of the clone hook, any extra arguments passed to
lxc-clone will appear as further arguments to the hook.
In the case of the stop hook, paths to filedescriptors
for each of the container's namespaces along with their types
are passed. </para></listitem>
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. </para></listitem>
</itemizedlist>
The following environment variables are set:
<itemizedlist>

View File

@ -20,9 +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}
%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
%if 0%{?fedora} >= 14 || 0%{?rhel} >= 7 || 0%{?suse_version} >= 1210
@ -94,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
@ -124,26 +115,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
%if "x%{_unitdir}" != "x"
--with-systemdsystemunitdir=%{_unitdir} \
%endif
@ -280,17 +255,6 @@ fi
%attr(555,root,root) %{_libexecdir}/%{name}/lxc-containers
%endif
%if %{with_python}
%{python3_sitearch}/*
%endif
%if %{with_lua}
%files lua
%defattr(-,root,root)
%{_datadir}/lua
%{_libdir}/lua
%endif
%files devel
%defattr(-,root,root)
%{_includedir}/%{name}/*

View File

@ -1 +1 @@
SUBDIRS = lxc tests python-lxc lua-lxc
SUBDIRS = lxc tests

View File

@ -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

View File

@ -1,614 +0,0 @@
/*
* lua-lxc: lua bindings for lxc
*
* Copyright © 2012 Oracle.
*
* Authors:
* Dwight Engen <dwight.engen@oracle.com>
*
* 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 <lua.h>
#include <lauxlib.h>
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <libgen.h>
#include <lxc/lxccontainer.h>
#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;
}

View File

@ -1,421 +0,0 @@
--
-- lua lxc module
--
-- Copyright © 2012 Oracle.
--
-- Authors:
-- Dwight Engen <dwight.engen@oracle.com>
--
-- 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

View File

@ -1,353 +0,0 @@
#!/usr/bin/env lua
--
-- test the lxc lua api
--
-- Copyright © 2012 Oracle.
--
-- Authors:
-- Dwight Engen <dwight.engen@oracle.com>
--
-- 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 <options>\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")

View File

@ -200,18 +200,14 @@ liblxc_la_LDFLAGS = \
liblxc_la_LIBADD = $(CAP_LIBS) $(SELINUX_LIBS) $(SECCOMP_LIBS)
bin_SCRIPTS = cmd/lxc-checkconfig \
bin_SCRIPTS=
if ENABLE_COMMANDS
bin_SCRIPTS += cmd/lxc-checkconfig \
cmd/lxc-update-config
EXTRA_DIST = \
tools/lxc-top.lua
if ENABLE_DEPRECATED
if ENABLE_PYTHON
bin_SCRIPTS += tools/lxc-start-ephemeral
endif
endif
if ENABLE_TOOLS
bin_PROGRAMS = \
lxc-attach \
lxc-autostart \
@ -236,15 +232,14 @@ bin_PROGRAMS = \
lxc-unshare \
lxc-usernsexec \
lxc-wait
if ENABLE_DEPRECATED
bin_PROGRAMS += lxc-clone
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 +247,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,21 +270,24 @@ 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
if ENABLE_DEPRECATED
lxc_clone_SOURCES = tools/lxc_clone.c tools/arguments.c
endif
if ENABLE_TOOLS
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 +303,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

View File

@ -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 <stgraber@ubuntu.com>
#
# 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)

View File

@ -1,243 +0,0 @@
#!/usr/bin/env lua
--
-- top(1) like monitor for lxc containers
--
-- Copyright © 2012 Oracle.
--
-- Authors:
-- Dwight Engen <dwight.engen@oracle.com>
--
-- 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

View File

@ -1,246 +0,0 @@
/*
*
* Copyright © 2013 Serge Hallyn <serge.hallyn@ubuntu.com>.
* 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 <ctype.h>
#include <errno.h>
#include <getopt.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <lxc/lxccontainer.h>
/* 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);
}

View File

@ -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

View File

@ -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 <stgraber@ubuntu.com>
#
# 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)

View File

@ -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 <dwight.engen@oracle.com>
#
# 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)

View File

@ -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 <dwight.engen@oracle.com>
#
# 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")

File diff suppressed because it is too large Load Diff

View File

@ -1,510 +0,0 @@
#
# -*- coding: utf-8 -*-
# python-lxc: Python bindings for LXC
#
# (C) Copyright Canonical Ltd. 2012
#
# Authors:
# Stéphane Graber <stgraber@ubuntu.com>
#
# 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

View File

@ -1,89 +0,0 @@
#!/usr/bin/env python3
#
# python-lxc: Python bindings for LXC
#
# (C) Copyright Canonical Ltd. 2012
#
# Authors:
# Stéphane Graber <stgraber@ubuntu.com>
#
# 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},
)

View File

@ -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

View File

@ -1,28 +1,6 @@
templatesdir=@LXCTEMPLATEDIR@
templates_SCRIPTS = \
lxc-alpine \
lxc-altlinux \
lxc-archlinux \
lxc-busybox \
lxc-centos \
lxc-cirros \
lxc-debian \
templates_SCRIPTS = lxc-busybox \
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
lxc-oci

View File

@ -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 <jakub@jirutka.cz>
# 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

View File

@ -1,498 +0,0 @@
#!/bin/bash
#
# template script for generating altlinux container for LXC
#
#
# lxc: linux Container library
# Authors:
# Alexey Shabalin <shaba@altlinux.org>
# 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 <<EOF > ${rootfs_path}/etc/net/ifaces/eth0/options
BOOTPROTO=${BOOTPROTO}
ONBOOT=yes
NM_CONTROLLED=yes
TYPE=eth
EOF
if [ ${BOOTPROTO} != "dhcp" ]; then
# ip address
cat <<EOF > ${rootfs_path}/etc/net/ifaces/eth0/ipv4address
${ipv4}
EOF
cat <<EOF > ${rootfs_path}/etc/net/ifaces/eth0/ipv4route
${gw}
EOF
cat <<EOF > ${rootfs_path}/etc/net/ifaces/eth0/resolv.conf
nameserver ${dns}
EOF
cat <<EOF > ${rootfs_path}/etc/net/ifaces/eth0/ipv6address
${ipv6}
EOF
cat <<EOF > ${rootfs_path}/etc/net/ifaces/eth0/ipv6route
${gw6}
EOF
fi
# set the hostname
cat <<EOF > ${rootfs_path}/etc/sysconfig/network
NETWORKING=yes
CONFMETHOD=etcnet
HOSTNAME=${UTSNAME}
RESOLV_MODS=yes
EOF
# set minimal hosts
cat <<EOF > $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 <<EOF >> $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 <<EOF >> $config_path/config
lxc.net.0.ipv4.address = $ipv4
EOF
fi
if [ ! -z ${gw} ]; then
cat <<EOF >> $config_path/config
lxc.net.0.ipv4.gateway = $gw
EOF
fi
if [ ! -z ${ipv6} ]; then
cat <<EOF >> $config_path/config
lxc.net.0.ipv6.address = $ipv6
EOF
fi
if [ ! -z ${gw6} ]; then
cat <<EOF >> $config_path/config
lxc.net.0.ipv6.gateway = $gw6
EOF
fi
cat <<EOF >> $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 <<EOF
usage:
$1 -n|--name=<container_name>
[-p|--path=<path>] [-c|--clean] [-R|--release=<ALTLinux_release>]
[-4|--ipv4=<ipv4 address>] [-6|--ipv6=<ipv6 address>]
[-g|--gw=<gw address>] [-d|--dns=<dns address>]
[-P|--profile=<name of the profile>] [--rootfs=<path>]
[-a|--apt-conf=<apt-conf>]
[-A|--arch=<arch of the container>]
[-h|--help]
Mandatory args:
-n,--name container name, used to as an identifier for that container from now on
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"

View File

@ -1,334 +0,0 @@
#!/bin/bash
#
# template script for generating Arch Linux container for LXC
#
#
# lxc: linux Container library
# Authors:
# Alexander Vladimirov <alexander.idkfa.vladimirov@gmail.com>
# John Lane <lxc@jelmail.com>
# 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/<devttydir>/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 <<EOF
usage:
${1} -n|--name=<container_name> [-p|--path=<path>] [-a|--arch=<arch of the container>]
[-r|--root_password=<root password>] [-P|--packages=<pkg1,pkg2,...>]
[-e|--enable_units=unit1,unit2...] [-d|--disable_units=unit1,unit2...]
[-c|--config=<pacman config path>] [-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

View File

@ -1,11 +1,10 @@
#!/bin/bash
#!/bin/sh
# Client script for LXC container images.
#
# Copyright @ Daniel Lezcano <daniel.lezcano@free.fr>
# Copyright © 2018 Christian Brauner <christian.brauner@ubuntu.com>
#
# lxc: linux Container library
# Authors:
# Daniel Lezcano <daniel.lezcano@free.fr>
# 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
@ -18,115 +17,97 @@
# 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
# 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() {
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; }
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
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"
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
pushd $rootfs/dev > /dev/null || return 1
# shellcheck disable=SC2086
mkdir -p ${fstree} || return 1
# shellcheck disable=SC2086
chmod 755 ${fstree} || return 1
# minimal devices needed for busybox
if [ $in_userns -eq 1 ]; then
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
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
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
popd > /dev/null
# root user defined
cat <<EOF >> $rootfs/etc/passwd
cat <<EOF >> "${rootfs}/etc/passwd"
root:x:0:0:root:/root:/bin/sh
EOF
cat <<EOF >> $rootfs/etc/group
cat <<EOF >> "${rootfs}/etc/group"
root:x:0:root
EOF
# mount everything
cat <<EOF >> $rootfs/etc/init.d/rcS
cat <<EOF >> "${rootfs}/etc/init.d/rcS"
#!/bin/sh
/bin/syslogd
/bin/mount -a
@ -134,20 +115,20 @@ EOF
EOF
# executable
chmod 744 $rootfs/etc/init.d/rcS || return 1
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 <<EOF >> $rootfs/etc/inittab
cat <<EOF >> "${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
chmod 644 "${rootfs}/etc/inittab" || return 1
cat <<EOF >> $rootfs/usr/share/udhcpc/default.script
cat <<EOF >> "${rootfs}/usr/share/udhcpc/default.script"
#!/bin/sh
case "\$1" in
deconfig)
@ -181,169 +162,60 @@ 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 <<EOF >> $rootfs/etc/passwd
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
EOF
cat <<EOF >> $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 <<EOF > $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 [ $? -ne 0 ]; then
echo "busybox executable is not accessible"
if ! which busybox > /dev/null 2>&1; then
echo "ERROR: Failed to find 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"
if ! cp "$(which busybox)" "${rootfs}/bin"; then
echo "ERROR: Failed to copy busybox binary"
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
(
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
ln "${rootfs}/bin/busybox" "${rootfs}/sbin/init"
# /etc/fstab must exist for "mount -a"
touch $rootfs/etc/fstab
touch "${rootfs}/etc/fstab"
# passwd exec must be setuid
chmod +s $rootfs/bin/passwd
touch $rootfs/etc/shadow
chmod +s "${rootfs}/bin/passwd"
touch "${rootfs}/etc/shadow"
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 <<EOF >> $path/config
grep -q "^lxc.rootfs.path" "${path}/config" 2>/dev/null || echo "lxc.rootfs.path = ${rootfs}" >> "${path}/config"
cat <<EOF >> "${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
@ -361,40 +233,48 @@ EOF
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
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
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
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
chgrp "${LXC_MAPPED_GID}" "${path}/config" > /dev/null 2>&1
chgrp -R root "${path}/rootfs" > /dev/null 2>&1
fi
}
usage()
{
usage() {
cat <<EOF
$1 -h|--help -p|--path=<path> -s|--ssh={dropbear,openssh}
LXC busybox image builder
Special arguments:
[ -h | --help ]: Print this help message and exit.
LXC internal arguments (do not pass manually!):
[ --name <name> ]: The container name
[ --path <path> ]: The path to the container
[ --rootfs <rootfs> ]: The path to the container's rootfs
[ --mapped-uid <map> ]: A uid map (user namespaces)
[ --mapped-gid <map> ]: A gid map (user namespaces)
EOF
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)
if ! options=$(getopt -o hp:n: -l help,rootfs:,path:,name:,mapped-uid:,mapped-gid: -- "$@"); then
usage
exit 1
fi
eval set -- "$options"
@ -402,83 +282,49 @@ eval set -- "$options"
while true
do
case "$1" in
-h|--help) usage $0 && exit 0;;
-h|--help) usage exit 1;;
-n|--name) name=$2; shift 2;;
-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
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)
if grep -q '^lxc.rootfs.path' "${config}" 2> /dev/null ; then
rootfs=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' "${config}")
else
rootfs=$path/rootfs
rootfs="${path}/rootfs"
fi
fi
install_busybox $rootfs $name
if [ $? -ne 0 ]; then
echo "failed to install busybox's rootfs"
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"
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"
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"
if ! remap_userns "${path}"; then
echo "ERROR: Failed to change idmappings"
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
fi

View File

@ -1,968 +0,0 @@
#!/bin/bash
#
# template script for generating CentOS container for LXC
#
# lxc: linux Container library
# Authors:
# Daniel Lezcano <daniel.lezcano@free.fr>
# Ramez Hanna <rhanna@informatiq.org>
# Fajar A. Nugraha <github@fajar.net>
# Michael H. Warfield <mhw@WittsEnd.com>
# 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 <<EOF > ${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 <<EOF > ${rootfs_path}/etc/sysconfig/network
NETWORKING=yes
HOSTNAME=${utsname}
EOF
# set minimal hosts
cat <<EOF > $rootfs_path/etc/hosts
127.0.0.1 localhost $name
EOF
# set minimal fstab
cat <<EOF > $rootfs_path/etc/fstab
/dev/root / rootfs defaults 0 0
EOF
# create lxc compatibility init script
if [ "$release" = "6" ]; then
cat <<EOF > $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 <<EOF > $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 <<EOF >${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 <<EOF > $REPO_FILE
[base]
name=local repository
baseurl="$repo"
EOF
elif [ ${basearch} = 'i386' ] || [ ${basearch} = 'x86_64' ]; then
cat <<EOF > $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 <<EOF > $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 <<EOF >> $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 <<EOF
usage:
$1 -n|--name=<container_name>
[-p|--path=<path>] [-c|--clean] [-R|--release=<CentOS_release>] [-a|--arch=<arch of the container>]
[-h|--help]
Mandatory args:
-n,--name container name, used to as an identifier for that container from now on
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

View File

@ -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 <scott.moser@canonical.com>
#
# 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 <<EOF
${0##*/} [options]
-a | --arch A architecture to use [${ARCHES[*]}]
default: ${DEF_ARCH}
-h | --help this usage
-v | --verbose increase verbosity
-S | --auth-key K insert auth key 'K'
-v | --version V version [${STREAMS[*]}]
default: ${DEF_VERSION}
-u | --userdata U user-data file
--tarball T read from tarball 'T' rather than downloading
or using cache.
--source S insert userdata/metadata via source S
[${SOURCES[*]}]
EOF
}
bad_Usage() { Usage 1>&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" <<EOF
# Template used to create this container: cirros
lxc.rootfs.path = $rootfs
lxc.tty.max = 4
lxc.pty.max = 1024
lxc.uts.name = $name
lxc.arch = $arch
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.auto = cgroup:mixed proc:mixed sys:mixed
lxc.cgroup.devices.deny = a
# Allow any mknod (but not using the node)
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
# /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 rwm
# fuse
lxc.cgroup.devices.allow = c 10:229 rwm
# tun
lxc.cgroup.devices.allow = c 10:200 rwm
# full
lxc.cgroup.devices.allow = c 1:7 rwm
# hpet
lxc.cgroup.devices.allow = c 10:228 rwm
# kvm
lxc.cgroup.devices.allow = c 10:232 rwm
EOF
if [ $in_userns -eq 1 ] && [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.userns.conf" ]; then
echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu.userns.conf" >> $path/config
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

View File

@ -1,824 +0,0 @@
#!/bin/bash
#
# lxc: linux Container library
# Authors:
# Daniel Lezcano <daniel.lezcano@free.fr>
# 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 <<EOF > $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 <<EOF > $rootfs/etc/network/interfaces
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet dhcp
EOF
# set the hostname
cat <<EOF > $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 <<EOF >> $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 <<EOF
Template specific options can be passed to lxc-create after a '--' like this:
lxc-create --name=NAME [-lxc-create-options] -- [-template-options]
Usage: $1 -h|--help -p|--path=<path> [-c|--clean] [-a|--arch=<arch>] [-r|--release=<release>]
[--mirror=<mirror>] [--security-mirror=<security mirror>]
[--package=<package_name1,package_name2,...>]
[-I|--interpreter-path=<interpreter path>]
[-F | --flush-cache] [-S|--auth-key=<keyfile>]
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

View File

@ -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"
@ -74,7 +74,7 @@ cleanup() {
}
wget_wrapper() {
for i in $(seq 3); do
for _ in $(seq 3); do
if wget "$@"; then
return 0
fi
@ -94,8 +94,8 @@ download_file() {
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 "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
@ -132,7 +132,7 @@ gpg_setup() {
export GNUPGHOME="${DOWNLOAD_TEMP}/gpg"
success=
for i in $(seq 3); do
for _ in $(seq 3); do
if gpg --keyserver "${DOWNLOAD_KEYSERVER}" \
--recv-keys "${DOWNLOAD_KEYID}" >/dev/null 2>&1; then
success=1
@ -142,7 +142,7 @@ gpg_setup() {
done
if [ -z "${success}" ]; then
echo "ERROR: Unable to fetch GPG key from keyserver."
echo "ERROR: Unable to fetch GPG key from keyserver"
exit 1
fi
@ -178,16 +178,17 @@ in_userns() {
fi
done < /proc/self/uid_map
[ "$(cat /proc/self/uid_map)" = "$(cat /proc/1/uid_map)" ] && \
{ echo userns-root; return; }
[ "$(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
@ -200,8 +201,8 @@ usage() {
LXC container image downloader
Special arguments:
[ -h | --help ]: Print this help message and exit.
[ -l | --list ]: List all available images and exit.
[ -h | --help ]: Print this help message and exit
[ -l | --list ]: List all available images and exit
Required arguments:
[ -d | --dist <distribution> ]: The name of the distribution
@ -275,7 +276,7 @@ done
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
echo "You can workaround this by using --no-validate" 1>&2
exit 1
fi
fi
@ -283,7 +284,7 @@ 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
echo "ERROR: Please pass the name, path, and rootfs for the container" 1>&2
exit 1
fi
fi
@ -293,7 +294,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
DOWNLOAD_MODE="user"
@ -304,8 +305,7 @@ if [ "${USERNS}" != "no" ]; then
fi
fi
if [ -z "${DOWNLOAD_DIST}" ] || [ -z "${DOWNLOAD_RELEASE}" ] || \
[ -z "${DOWNLOAD_ARCH}" ]; then
if [ -z "${DOWNLOAD_DIST}" ] || [ -z "${DOWNLOAD_RELEASE}" ] || [ -z "${DOWNLOAD_ARCH}" ]; then
DOWNLOAD_INTERACTIVE="true"
fi
@ -324,8 +324,7 @@ else
fi
# Simply list images
if [ "${DOWNLOAD_LIST_IMAGES}" = "true" ] || \
[ "${DOWNLOAD_INTERACTIVE}" = "true" ]; then
if [ "${DOWNLOAD_LIST_IMAGES}" = "true" ] || [ "${DOWNLOAD_INTERACTIVE}" = "true" ]; then
# Initialize GPG
gpg_setup
@ -333,13 +332,10 @@ if [ "${DOWNLOAD_LIST_IMAGES}" = "true" ] || \
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
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
download_sig "${DOWNLOAD_INDEX_PATH}.asc" "${DOWNLOAD_TEMP}/index.asc" normal
fi
gpg_validate "${DOWNLOAD_TEMP}/index.asc"
@ -350,7 +346,6 @@ if [ "${DOWNLOAD_LIST_IMAGES}" = "true" ] || \
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
@ -426,20 +421,16 @@ if [ "${DOWNLOAD_USE_CACHE}" = "false" ]; then
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
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
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}" ] || \
@ -456,28 +447,24 @@ if [ "${DOWNLOAD_USE_CACHE}" = "false" ]; then
done < "${DOWNLOAD_TEMP}/index"
if [ -z "${DOWNLOAD_URL}" ]; then
echo "ERROR: Couldn't find a matching image." 1>&1
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 "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
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
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
@ -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/"
@ -537,35 +523,40 @@ if [ ! -e "${configfile}" ]; then
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"
@ -590,7 +581,6 @@ 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}"
@ -607,6 +597,7 @@ 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 || :
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 || :
fi

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,833 +0,0 @@
#!/bin/bash
#
# LXC template for gentoo
#
# Author: Guillaume Zitta <lxc@zitta.fr>
#
# 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 <<EOF
$1 -h|--help [-a|--arch <arch>] [-v|--variant <variant>] [-P|--private-portage] [--portage-dir <protagedir>] [-t|--tarball <stage3file>]
[-F|--flush-cache] [-c|--cache-only] [-u|--user <username>] [-w|--password <password>] [--autologin] [-S|--auth-key <keyfile>]
[-s|--settings <name>] [-m|--mirror <gentoomirror>] [--tty <number>]
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

View File

@ -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
@ -69,7 +69,8 @@ LXC internal arguments (do not pass manually!):
[ --name <name> ]: The container name
[ --path <path> ]: The path to the container
[ --rootfs <rootfs> ]: The path to the container's rootfs
[ --mapped-uid <map> ]: A uid map (user namespaces)
[ --mapped-gid <map> ]: 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
@ -114,7 +117,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"

View File

@ -21,14 +21,13 @@
# 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
if ! which $bin >/dev/null 2>&1; then
echo "ERROR: Missing required tool: $bin" 1>&2
exit 1
fi
@ -43,6 +42,7 @@ cleanup() {
if [ -d "${DOWNLOAD_TEMP}" ]; then
rm -Rf "${DOWNLOAD_TEMP}"
fi
if [ -d "${LXC_ROOTFS}.tmp" ]; then
rm -Rf "${LXC_ROOTFS}.tmp"
fi
@ -50,14 +50,19 @@ cleanup() {
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
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; }
[ "$(cat /proc/self/uid_map)" = "$(cat /proc/1/uid_map)" ] && { echo userns-root; return; }
echo yes
}
@ -65,26 +70,28 @@ getconfigpath() {
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'`
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,
# Ok we have the image config digest, now get the config from that
# shellcheck disable=SC2039
d=${digest:7}
cdigest=`cat "${basedir}/blobs/sha256/${d}" | jq -c -r '.config.digest'`
cdigest=$(jq -c -r '.config.digest' < "${basedir}/blobs/sha256/${d}")
if [ -z "${cdigest}" ]; then
echo "container config not found" >&2
return
fi
# 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"
@ -93,8 +100,8 @@ getep() {
configpath="$1"
ep=`cat "${configpath}" | jq -c -r '.config.Entrypoint[]?'`
cmd=`cat "${configpath}" | jq -c -r '.config.Cmd[]?'`
ep=$(jq -c -r '.config.Entrypoint[]?'< "${configpath}")
cmd=$(jq -c -r '.config.Cmd[]?' < "${configpath}")
if [ -z "${ep}" ]; then
ep="${cmd}"
if [ -z "${ep}" ]; then
@ -104,7 +111,7 @@ getep() {
ep="${ep} ${cmd}"
fi
echo ${ep}
echo "${ep}"
return
}
@ -116,7 +123,7 @@ getenv() {
configpath="$1"
env=`cat "${configpath}" | jq -c -r '.config.Env[]'`
env=$(jq -c -r '.config.Env[]'< "${configpath}")
echo "${env}"
return
@ -134,10 +141,11 @@ getuidgid() {
configpath="$1"
uidgid=`cat "${configpath}" | jq -c -r '.config.User // "0:0"'`
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
printf '%d %d' "${uidgid[0]:-0}" "${uidgid[1]:-0}" 2>/dev/null || true
return
}
@ -150,7 +158,7 @@ getcwd() {
configpath="$1"
cwd=`cat "${configpath}" | jq -c -r '.config.WorkingDir // "/"'`
cwd=$(jq -c -r '.config.WorkingDir // "/"' < "${configpath}")
echo "${cwd}"
return
@ -176,15 +184,11 @@ LXC internal arguments (do not pass manually!):
[ --rootfs <rootfs> ]: The path to the container's rootfs
[ --mapped-uid <map> ]: A uid map (user namespaces)
[ --mapped-gid <map> ]: A gid map (user namespaces)
EOF
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
@ -221,7 +225,7 @@ 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
echo "ERROR: Not running through LXC" 1>&2
exit 1
fi
@ -246,7 +250,7 @@ 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
echo "ERROR: In a user namespace without a map" 1>&2
exit 1
fi
fi
@ -264,46 +268,62 @@ fi
# Trap all exit signals
trap cleanup EXIT HUP INT TERM
if ! type mktemp >/dev/null 2>&1; then
if ! which mktemp >/dev/null 2>&1; then
DOWNLOAD_TEMP="${DOWNLOAD_BASE}/lxc-oci.$$"
mkdir -p $DOWNLOAD_TEMP
mkdir -p "${DOWNLOAD_TEMP}"
else
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
# shellcheck disable=SC2039
skopeo_args+=(--src-creds "${CREDENTIALS}")
fi
if [ "${OCI_USE_CACHE}" = "true" ]; then
# 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
# 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
# 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}"
done <<< "${environment}"
@ -327,12 +347,12 @@ fi
echo "lxc.uts.name = ${LXC_NAME}" >> "${LXC_CONF_FILE}"
# set the hostname
cat <<EOF > ${LXC_ROOTFS}/etc/hostname
cat <<EOF > "${LXC_ROOTFS}/etc/hostname"
${LXC_NAME}
EOF
# set minimal hosts
cat <<EOF > ${LXC_ROOTFS}/etc/hosts
cat <<EOF > "${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

View File

@ -1,484 +0,0 @@
#!/bin/bash
#
# template script for generating openmandriva container for LXC
#
#
# lxc: linux Container library
# Authors:
# Alexander Khryukin <alexander@mezon.ru>
# Vokhmin Alexey V <avokhmin@gmail.com>
# 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 <<EOF > ${rootfs_path}/etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
ONBOOT=yes
BOOTPROTO=dhcp
NM_CONTROLLED=no
HOSTNAME=${utsname}
EOF
# set the hostname
cat <<EOF > ${rootfs_path}/etc/sysconfig/network
NETWORKING=yes
HOSTNAME=${utsname}
EOF
echo "${utsname}" > ${rootfs_path}/etc/hostname
# set minimal hosts
cat <<EOF > $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 <<EOF >> $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 <<EOF >> $config_path/config
lxc.net.0.ipv4.address = $ipv4
EOF
fi
if [ ! -z ${gw} ]; then
cat <<EOF >> $config_path/config
lxc.net.0.ipv4.gateway = $gw
EOF
fi
if [ ! -z ${ipv6} ]; then
cat <<EOF >> $config_path/config
lxc.net.0.ipv6.address = $ipv6
EOF
fi
if [ ! -z ${gw6} ]; then
cat <<EOF >> $config_path/config
lxc.net.0.ipv6.gateway = $gw6
EOF
fi
cat <<EOF >> $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 <<EOF
usage:
$1 -n|--name=<container_name>
[-p|--path=<path>] [-c|--clean] [-R|--release=<openmandriva2013.0/rosa2012.1/cooker/ release>]
[-4|--ipv4=<ipv4 address>] [-6|--ipv6=<ipv6 address>]
[-g|--gw=<gw address>] [-d|--dns=<dns address>]
[-P|--profile=<name of the profile>] [--rootfs=<path>]
[-A|--arch=<arch of the container>]
[-h|--help]
Mandatory args:
-n,--name container name, used to as an identifier for that container from now on
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"

View File

@ -1,557 +0,0 @@
#!/bin/bash
#
# template script for generating OpenSUSE container for LXC
#
#
# lxc: linux Container library
# Authors:
# Daniel Lezcano <daniel.lezcano@free.fr>
# Frederic Crozat <fcrozat@suse.com>
# Michael H. Warfield <mhw@WittsEnd.com>
# Johannes Kastl <mail@ojkastl.de>
# Thomas Lamprecht <t.lamprecht@proxmox.com>
# 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 <<EOF > $rootfs/etc/sysconfig/network/ifcfg-eth0
STARTMODE='auto'
BOOTPROTO='dhcp'
EOF
# create empty fstab
touch $rootfs/etc/fstab
# set the hostname
cat <<EOF > $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 <<EOF >> $rootfs/etc/sysconfig/cron
unset HOSTNAME
EOF
# set minimal hosts
cat <<EOF > $rootfs/etc/hosts
127.0.0.1 localhost $hostname
EOF
# disable yast->bootloader in container
cat <<EOF > $rootfs/etc/sysconfig/bootloader
LOADER_TYPE=none
LOADER_LOCATION=none
EOF
# set /dev/console as securetty
cat << EOF >> $rootfs/etc/securetty
console
EOF
cat <<EOF >> $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 <<EOF >> $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 <<EOF
$1 -h|--help -p|--path=<path> -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

View File

@ -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 <wim.coekaerts@oracle.com>
# Copyright © 2012 Dwight Engen <dwight.engen@oracle.com>
#
# Modified for Oracle Linux 5
# Wim Coekaerts <wim.coekaerts@oracle.com>
#
# Modified for Oracle Linux 6,7 combined OL4,5,6 into one template script
# Dwight Engen <dwight.engen@oracle.com>
#
# 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 <<EOF > $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 <<EOF > $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 <<EOF > $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 <<EOF >$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 <<EOF > $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 <<EOF > $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 <<EOF >> $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 <<EOF >> $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 <<EOF
-a|--arch=<arch> architecture (ie. i386, x86_64)
-R|--release=<release> release to download for the new container
--rootfs=<path> rootfs path
-r|--rpms=<rpm name> additional rpms to install into container
-u|--url=<url> replace yum repo url (ie. Oracle public-yum mirror)
--baseurl=<url> use package repository (ie. file:///mnt)
arch and release must also be specified
-t|--templatefs=<path> copy/clone rootfs at path instead of downloading
-P|--patch=<path> 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"

View File

@ -1,384 +0,0 @@
#!/bin/bash -eu
#
# template script for generating Plamo Linux container for LXC
#
#
# lxc: linux Container library
# Authors:
# KATOH Yasufumi <karma@jazz.email.ne.jp>
# TAMUKI Shoichi <tamuki@linet.gr.jp>
# 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=<path> -n|--name=<name> --rootfs=<rootfs>
[-c|--clean] [-r|--release=<release>] [-a|--arch=<arch>]
[-b|--bindhome=<user>]
release: $release
arch: x86 or x86_64: defaults to host arch
bindhome: bind <user>'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

View File

@ -1,484 +0,0 @@
#!/bin/sh
#
# template script for generating PLD Linux container for LXC
#
#
# lxc: Linux Container library
# Authors:
# Elan Ruusamäe <glen@pld-linux.org>
# 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 <<EOF > $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 <<EOF >> $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 <<EOF > $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 <<EOF
usage:
$1 -n|--name=<container_name>
[-p|--path=<path>] [-c|--clean] [-R|--release=<PLD Release>] [--fqdn=<network name of container>] [-A|--arch=<arch of the container>]
[-h|--help]
Mandatory args:
-n,--name container name, used to as an identifier for that container from now on
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"

View File

@ -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 <geaaru@gmail.com>
# 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 <<EOF > 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 <<EOF > ${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

View File

@ -1,793 +0,0 @@
#!/bin/bash
#
# lxc: linux Container library
# Authors:
# Daniel Lezcano <daniel.lezcano@free.fr>
# Template for slackware by Matteo Bernardini <ponce@slackbuilds.org>
# 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 <<EOF > $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 <<EOF
none /run tmpfs defaults,mode=0755 0 0
EOF
# simplify rc.6 and rc.S, http://www.vislab.uq.edu.au/howto/lxc/create_container.html
# and some other small fixes for a clean boot
cat >$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 <miquels@drinkel.nl.mugnet.org>
# Modified by: Patrick J. Volkerding, <volkerdi@slackware.com>
#
+# minor tweaks for an lxc container
+# by Matteo Bernardini <ponce@slackbuilds.org>,
+# 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, <volkerdi@slackware.com>
#
+# minor tweaks for an lxc container
+# by Matteo Bernardini <ponce@slackbuilds.org>,
+# 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, <waltje@uwalt.nl.mugnet.org>
# Heavily modified by Patrick Volkerding <volkerdi@slackware.com>
#
+# minor tweaks for an lxc container
+# by Matteo Bernardini <ponce@slackbuilds.org>:
+# 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 <ponce@slackbuilds.org>:
+# 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 <<EOF > $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 <<EOF > $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 <<EOF >> $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 <<EOF
$1 -h|--help -p|--path=<path> --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

View File

@ -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 <wim.coekaerts@oracle.com>
# Copyright © 2012 Dwight Engen <dwight.engen@oracle.com>
# Copyright <20> 2015 Wim Coekaerts <wim.coekaerts@oracle.com>
#
# Modified for Oracle Linux 5
# Wim Coekaerts <wim.coekaerts@oracle.com>
#
# Modified for Oracle Linux 6,7 combined OL4,5,6 into one template script
# Dwight Engen <dwight.engen@oracle.com>
#
# Modified for Linux for SPARC 1.0
# Wim Coekaerts <wim.coekaerts@oracle.com>
#
# 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 <<EOF > $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 <<EOF > $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 <<EOF > $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 <<EOF >$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 <<EOF > $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 <<EOF > $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 <<EOF >> $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 <<EOF >> $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 <<EOF
-a|--arch=<arch> architecture (sparc64)
-R|--release=<release> release to download for the new container
--rootfs=<path> rootfs path
-r|--rpms=<rpm name> additional rpms to install into container
-u|--url=<url> replace yum repo url (ie. Oracle public-yum mirror)
--baseurl=<url> use package repository (ie. file:///mnt)
arch and release must also be specified
-t|--templatefs=<path> copy/clone rootfs at path instead of downloading
-P|--patch=<path> 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"

View File

@ -1,276 +0,0 @@
#!/bin/bash
#
# lxc: linux Container library
# Authors:
# Daniel Lezcano <daniel.lezcano@free.fr>
# 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 <<EOF > $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 <<EOF > $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 <<EOF > $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 <<EOF >> $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 <<EOF >> $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 <<EOF >> $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 <<EOF >> $path/config
lxc.mount.entry = /lib64 lib64 none ro,bind 0 0
EOF
fi
}
usage()
{
cat <<EOF
$1 -h|--help -p|--path=<path> [--rootfs=<path>]
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

View File

@ -1,374 +0,0 @@
#!/bin/bash
# template script for generating ubuntu container for LXC based on released
# cloud images.
#
# Copyright © 2012 Serge Hallyn <serge.hallyn@canonical.com>
#
# 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 <<EOF >> $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 <<EOF
LXC Container configuration for Ubuntu Cloud images.
Generic Options
[ -r | --release <release> ]: Release name of container, defaults to host
[ --rootfs <path> ]: 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

View File

@ -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 <serge.hallyn@canonical.com>
# Copyright © 2010 Wilhelm Meier
# Author: Wilhelm Meier <wilhelm.meier@fh-kl.de>
#
# 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 <<EOF > $rootfs/etc/netplan/10-lxc.yaml
network:
ethernets:
eth0: {dhcp4: true}
version: 2
EOF
else
cat <<EOF > $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 <<EOF > $rootfs/etc/hostname
$hostname
EOF
# set minimal hosts
cat <<EOF > $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 <<EOF >> $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 <<EOF
$1 -h|--help [-a|--arch] [-b|--bindhome <user>] [-d|--debug]
[-F | --flush-cache] [-r|--release <release>] [-v|--variant] [ -S | --auth-key <keyfile>]
[--rootfs <rootfs>] [--packages <packages>] [-u|--user <user>] [--password <password>]
[--mirror <url>] [--security-mirror <url>]
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 <user>'s home into the container
The ubuntu user will not be created, and <user> 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 ""

View File

@ -1,199 +0,0 @@
#!/bin/bash
#
# template script for generating Void Linux container for LXC
#
#
# lxc: linux Container library
# Authors:
# Gregor Reitzenstein <dean4devil@paranoidlabs.org>
# Based on lxc-archlinux template by:
# Alexander Vladimirov <alexander.idkfa.vladimirov@gmail.com>
# John Lane <lxc@jelmail.com>
# 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 <<EOF
usage:
${1} -n|--name=<container_name> [-p|--path=<path>] [-a|--arch=<arch of the container>]
[-r|--root_password=<root password>] [-P|--packages=<pkg1,pkg2,...>] [-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