forked from neil/lxc-templates
Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
4899eb526e | ||
|
27df421530 | ||
|
2e7bf59535 |
@ -38,4 +38,7 @@ templatesconfig_DATA = \
|
||||
voidlinux.common.conf \
|
||||
voidlinux.userns.conf \
|
||||
sabayon.common.conf \
|
||||
sabayon.userns.conf
|
||||
sabayon.userns.conf \
|
||||
rocky.common.conf \
|
||||
rocky.userns.conf
|
||||
|
||||
|
20
config/rocky.common.conf.in
Normal file
20
config/rocky.common.conf.in
Normal file
@ -0,0 +1,20 @@
|
||||
# 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
|
2
config/rocky.userns.conf.in
Normal file
2
config/rocky.userns.conf.in
Normal file
@ -0,0 +1,2 @@
|
||||
# This derives from the global userns config
|
||||
lxc.include = @LXCTEMPLATECONFIG@/userns.conf
|
@ -27,6 +27,7 @@ if test "z$with_distro" = "z"; then
|
||||
AC_CHECK_FILE(/etc/oracle-release,with_distro="oracle")
|
||||
AC_CHECK_FILE(/etc/sparclinux-release,with_distro="sparclinux")
|
||||
AC_CHECK_FILE(/etc/centos-release,with_distro="centos")
|
||||
AC_CHECK_FILE(/etc/rocky-release,with_distro="rocky")
|
||||
AC_CHECK_FILE(/etc/fedora-release,with_distro="fedora")
|
||||
AC_CHECK_FILE(/etc/SuSE-release,with_distro="suse")
|
||||
AC_CHECK_FILE(/etc/gentoo-release,with_distro="gentoo")
|
||||
@ -54,7 +55,7 @@ case $with_distro in
|
||||
ubuntu|raspbian)
|
||||
distrosysconf="$sysconfdir/default"
|
||||
;;
|
||||
redhat|centos|fedora|oracle|oracleserver|sparclinux|altlinux|suse|opensuse*|plamo|pld)
|
||||
redhat|centos|rocky|fedora|oracle|oracleserver|sparclinux|altlinux|suse|opensuse*|plamo|pld)
|
||||
distrosysconf="$sysconfdir/sysconfig"
|
||||
;;
|
||||
*)
|
||||
@ -183,6 +184,8 @@ AC_CONFIG_FILES([
|
||||
config/ubuntu.lucid.conf
|
||||
config/ubuntu.userns.conf
|
||||
config/openwrt.common.conf
|
||||
config/rocky.common.conf
|
||||
config/rocky.userns.conf
|
||||
config/sparclinux.common.conf
|
||||
config/sparclinux.userns.conf
|
||||
config/voidlinux.common.conf
|
||||
@ -209,6 +212,7 @@ AC_CONFIG_FILES([
|
||||
templates/lxc-pld
|
||||
templates/lxc-slackware
|
||||
templates/lxc-sshd
|
||||
templates/lxc-rocky
|
||||
templates/lxc-ubuntu
|
||||
templates/lxc-ubuntu-cloud
|
||||
templates/lxc-sparclinux
|
||||
|
@ -19,6 +19,7 @@ templates_SCRIPTS = \
|
||||
lxc-pld \
|
||||
lxc-slackware \
|
||||
lxc-sshd \
|
||||
lxc-rocky \
|
||||
lxc-ubuntu \
|
||||
lxc-ubuntu-cloud \
|
||||
lxc-sparclinux \
|
||||
|
968
templates/lxc-rocky.in
Normal file
968
templates/lxc-rocky.in
Normal file
@ -0,0 +1,968 @@
|
||||
#!/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
|
Loading…
Reference in New Issue
Block a user