-
-
Save hagix9/3514296 to your computer and use it in GitHub Desktop.
#!/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> | |
# 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 | |
arch=$(arch) | |
release=6 | |
cache_base=/var/cache/lxc/centos/$arch | |
default_path=/var/lib/lxc | |
root_password=password | |
# is this centos? | |
[ -f /etc/redhat-release ] && is_centos=true | |
if [ "$arch" = "i686" ]; then | |
arch=i386 | |
fi | |
configure_centos() | |
{ | |
# disable selinux in centos | |
mkdir -p $rootfs_path/selinux | |
echo 0 > $rootfs_path/selinux/enforce | |
# configure the network using the dhcp | |
cat <<EOF > ${rootfs_path}/etc/sysconfig/network-scripts/ifcfg-eth0 | |
DEVICE=eth0 | |
BOOTPROTO=dhcp | |
ONBOOT=yes | |
TYPE=Ethernet | |
USERCTL=yes | |
PEERDNS=yes | |
IPV6INIT=no | |
DHCP_HOSTNAME="$(if [ -x /etc/hostname ] && [ ! -z `cat /etc/hostname` ] ; then cat /etc/hostname ; else hostname ; fi )" | |
EOF | |
# set the dns | |
cat > ${rootfs_path}/etc/resolv.conf << END | |
# Google public DNS | |
nameserver 8.8.8.8 | |
nameserver 8.8.4.4 | |
END | |
# set the hostname | |
cat <<EOF > ${rootfs_path}/etc/sysconfig/network | |
NETWORKING=yes | |
HOSTNAME=${name} | |
EOF | |
# set minimal hosts | |
cat <<EOF > $rootfs_path/etc/hosts | |
127.0.0.1 localhost $name | |
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 | |
EOF | |
sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc/rc.sysinit | |
sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc/rc.d/rc.sysinit | |
# don't mount devpts, for pete's sake | |
sed -i 's/^.*dev.pts.*$/#\0/' ${rootfs_path}/etc/rc.sysinit | |
sed -i 's/^.*dev.pts.*$/#\0/' ${rootfs_path}/etc/rc.d/rc.sysinit | |
sed -i 's/^.*dev.pts.*$/#\0/' ${rootfs_path}/etc/rc.d/rc.sysinit | |
sed -i 's/^.*dev.pts.*$/#\0/' ${rootfs_path}/etc/rc.d/rc.sysinit | |
sed -i 's/^.*dev.pts.*$/#\0/' ${rootfs_path}/etc/rc.d/rc.sysinit | |
sed -i 's/^#baseurl/baseurl/g' ${rootfs_path}/etc/yum.repos.d/CentOS-Base.repo | |
sed -i "s/\$releasever/$release.$releaseminor/g" ${rootfs_path}/etc/yum.repos.d/CentOS-Base.repo | |
sed -i '115,126s/^/#/' ${rootfs_path}/etc/rc.d/init.d/halt | |
chroot ${rootfs_path} chkconfig udev-post off | |
chroot ${rootfs_path} chkconfig network on | |
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 | |
echo "setting root passwd to $root_password" | |
echo "root:$root_password" | chroot $rootfs_path chpasswd | |
# specifying this in the initial packages doesn't always work. | |
# echo "installing centos-release package" | |
# if [ ! -f ${rootfs_path}/etc/resolv.conf ]; then | |
# cp /etc/resolv.conf ${rootfs_path}/etc/resolv.conf | |
# remove_resolv=1 | |
# fi | |
# chroot ${rootfs_path} rpm --rebuilddb | |
# chroot ${rootfs_path} yum --releasever=${release} -y install centos-release | |
# if [ ! -z $remove_resolv ]; then | |
# rm ${rootfs_path}/etc/resolv.conf | |
# fi | |
# silence some needless startup errors | |
touch ${rootfs_path}/etc/fstab | |
# give us a console on /dev/console | |
sed -i 's/ACTIVE_CONSOLES=.*$/ACTIVE_CONSOLES="\/dev\/console \/dev\/tty[1-4]"/' \ | |
${rootfs_path}/etc/sysconfig/init | |
return 0 | |
} | |
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 ..." | |
YUM="yum --installroot $INSTALL_ROOT -y --nogpgcheck" | |
PKG_LIST="yum initscripts passwd rsyslog vim-minimal dhclient chkconfig" | |
PKG_LIST="$PKG_LIST rootfiles policycoreutils centos-release openssh-server avahi" | |
PKG_LIST="$PKG_LIST openssh-clients sudo plymouth" | |
MIRRORLIST_URL="http://mirrorlist.centos.org/?release=$release&arch=$arch&repo=os" | |
DOWNLOAD_OK=no | |
for trynumber in 1 2 3; do | |
[ $trynumber != 1 ] && echo "Trying again..." | |
MIRROR_URL=$(curl -s -S -f "$MIRRORLIST_URL" | head -n2 | tail -n1) | |
if [ $? -ne 0 ] || [ -z "$MIRROR_URL" ]; then | |
echo "Failed to get a mirror" | |
continue | |
fi | |
RELEASE_URL="$MIRROR_URL/Packages/centos-release-$release-$releaseminor.el6.centos.10.$arch.rpm" | |
echo "Fetching from $RELEASE_URL" | |
curl -f "$RELEASE_URL" > $INSTALL_ROOT/centos-release-$release-$releaseminor.centos.$arch.rpm | |
if [ $? -ne 0 ]; then | |
echo "Failed to download centos release rpm" | |
continue | |
fi | |
DOWNLOAD_OK=yes | |
break | |
done | |
if [ $DOWNLOAD_OK != yes ]; then | |
echo "Aborting" | |
return 1 | |
fi | |
mkdir -p $INSTALL_ROOT/var/lib/rpm | |
rpm --root $INSTALL_ROOT --initdb | |
rpm --root $INSTALL_ROOT -ivh $INSTALL_ROOT/centos-release-$release-$releaseminor.centos.$arch.rpm | |
$YUM install $PKG_LIST | |
chroot $INSTALL_ROOT rm -f /var/lib/rpm/__* | |
chroot $INSTALL_ROOT rpm --rebuilddb | |
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_centos() | |
{ | |
# make a local copy of the minicentos | |
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 -a $cache/rootfs/ $rootfs_path/ | |
return 0 | |
} | |
update_centos() | |
{ | |
# chroot $cache/rootfs yum -y update | |
echo "Updates disabled" | |
} | |
install_centos() | |
{ | |
mkdir -p /var/lock/subsys/ | |
( | |
flock -x 200 | |
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 | |
) 200>/var/lock/subsys/lxc | |
return $? | |
} | |
copy_configuration() | |
{ | |
mkdir -p $config_path | |
cat <<EOF >> $config_path/config | |
lxc.utsname = $name | |
lxc.tty = 4 | |
lxc.pts = 1024 | |
lxc.rootfs = $rootfs_path | |
lxc.mount = $config_path/fstab | |
# uncomment the next line to run the container unconfined: | |
#lxc.aa_profile = unconfined | |
#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 254:0 rwm | |
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 200 | |
if [ $? != 0 ]; then | |
echo "Cache repository is busy." | |
exit 1 | |
fi | |
echo -n "Purging the download cache for Centos-$release-$releaseminor..." | |
rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1 | |
exit 0 | |
) 200>/var/lock/subsys/lxc | |
} | |
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. The container config will go under /var/lib/lxc in that case | |
-c,--clean clean the cache | |
-R,--release Centos release for the new container. if the host is Fedora, then it will defaultto the host's release. | |
-m,--release-minor Minor release number for the new containar | |
-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:m: -l help,path:,name:,clean,release:,releaseminor: -- "$@") | |
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|--clean) clean=$2; shift 2;; | |
-R|--release) release=$2; shift 2;; | |
-m|--releaseminor) releaseminor=$2; shift 2;; | |
--) shift 1; break ;; | |
*) break ;; | |
esac | |
done | |
if [ ! -z "$clean" -a -z "$path" ]; then | |
clean || exit 1 | |
exit 0 | |
fi | |
needed_pkgs="" | |
type yum >/dev/null 2>&1 | |
if [ $? -ne 0 ]; then | |
needed_pkgs="yum $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 apt-get install $needed_pkgs\"" | |
exit 1 | |
fi | |
if [ -z "$path" ]; then | |
path=$default_path | |
fi | |
if [ -z "$release" ]; then | |
if [ "$is_centos" ]; then | |
release=$(cat /etc/centos-release |awk '/^Fedora/ {print $3}') | |
else | |
echo "This is not a centos host and release missing, defaulting to 6.4. use -R|--release to specify release" | |
release=6 | |
fi | |
fi | |
if [ -z "$releaseminor" ]; then | |
releaseminor=4 | |
fi | |
if [ "$(id -u)" != "0" ]; then | |
echo "This script should be run as 'root'" | |
exit 1 | |
fi | |
rootfs_path=$path/rootfs | |
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/$name | |
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_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 | |
if [ ! -z $clean ]; then | |
clean || exit 1 | |
exit 0 | |
fi | |
echo "container rootfs and config created" |
The script seems to overwrite the host's resolv.conf file. I just commented that part out, as the dhclient-script will generate the file in the container anyway. Then it works fine on Ubuntu (if using lxcbr0).
i recommend making the following changes
at https://gist.github.com/hagix9/3514296#file-lxc-centos-L57 add
cat <<"EOF" > ${rootfs_path}/etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=dhcp
ONBOOT=yes
TYPE=Ethernet
USERCTL=yes
PEERDNS=yes
IPV6INIT=no
DHCP_HOSTNAME="$(if [ -x /etc/hostname ] && [ ! -z `cat /etc/hostname` ] ; then cat /etc/hostname ; else hostname ; fi )"
EOF
this way you can discover the new ip by checking /var/lib/misc/dnsmasq.leases
and install the extra packages
openssh-clients openssl sudo curl
Thank you
It has been changed to incorporate the opinions of everyone
It is better to append '-L' option for curl command (ex. Line 172), because a mirror server may return code 301 (, 302, or 303).
curl -f -L "$RELEASE_URL" > $INSTALL_ROOT/centos-release-$release-$releaseminor.centos.$arch.rpm
I've tried this template but it looks like the rpm db is not being rebuilt correctly. 'rpm -qa' gives no output as rpm thinks nothing is installed. Any ideas?
Very nice! Worked first time on my Ubuntu 13.04 box. One problem: uname -a says:
Linux centos 3.8.0-30-generic #44-Ubuntu SMP Thu Aug 22 20:52:24 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
instead of what my Vagrant CentOS 6.x box says:
Linux localhost.localdomain 2.6.32-279.22.1.el6.x86_64 #1 SMP Wed Feb 6 03:10:46 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
This prevents me from installing EPEL (which checks for RedHat 6.x) from installing and getting access to all the additional EPEL goodies.
This template is really good; however, the container gets broken after updating initscripts from the base repo. I don't know why this is happening, but after the update and following the reboot it freezes saying /etc/fstab is mounted.
Also, if I check in the rootfs/var/log/messages, I found this errors:
Sep 16 19:03:14 localhost init: tty (/dev/tty2) main process (359) terminated with status 1
Sep 16 19:03:14 localhost init: tty (/dev/tty2) main process ended, respawning
Sep 16 19:03:14 localhost init: tty (/dev/tty3) main process (360) terminated with status 1
Sep 16 19:03:14 localhost init: tty (/dev/tty3) main process ended, respawning
Sep 16 19:03:14 localhost /sbin/mingetty[362]: tty2: cannot open tty: Operation not permitted
Sep 16 19:03:14 localhost init: tty (/dev/tty4) main process (361) terminated with status 1
Sep 16 19:03:14 localhost init: tty (/dev/tty4) main process ended, respawning
Sep 16 19:03:14 localhost /sbin/mingetty[363]: tty3: cannot open tty: Operation not permitted
Sep 16 19:03:14 localhost /sbin/mingetty[364]: tty4: cannot open tty: Operation not permitted
rpm db fix
mkdir -p $INSTALL_ROOT/var/lib/rpm
rpm --root $INSTALL_ROOT --initdb
rpm --root $INSTALL_ROOT -ivh $INSTALL_ROOT/centos-release-$release-$releaseminor.centos.$arch.rpm
$YUM install $PKG_LIST
+cp $INSTALL_ROOT/root/.rpmdb/Packages $INSTALL_ROOT/var/lib/rpm/
chroot $INSTALL_ROOT rm -f /var/lib/rpm/__*
chroot $INSTALL_ROOT rpm --rebuilddb
fix init scripts after a yum upgrade...
comment
/sbin/start_udev
in /var/lib/lxc/CONTAINER/rootfs/etc/rc.d/rc.sysinit.
I am also getting the error reported by clvx about mingetty respawning. Any ideas?
on ubuntu 12.04, you'll need to patch the getopt line to include the rootfs long argument.
df -Th
df: no file systems processed
How to create '$cache/rootfs/' ?
To allow nfs mounts from the container I had to add the following to the config
lxc.aa_profile = unconfined
lxc.cgroup.devices.allow = b 7:* rwm
lxc.cgroup.devices.allow = c 10:237 rwm
getting 404 error form curl.
any ideas?
Did some changes to get the container working on 14.04. Also changed the default minor version to be 5
Also changed the looping do be done for all the sites in the mirror list till a working one is found.
https://gist.github.com/buksy/76574f8d4296b081bf65
Be warned that it may not work with Fedora and similar (rpm-based) hosts. For me it overwrote many critical parts of the host such as the rpm db, libc,..., effectively making the host unusable.
Forked to support 6.5-11.1 final release
This script is not working for Ubuntu 14.04, so I used @buksy's script from the link provided above. The script starts to work but gives this error:
curl: (7) Failed to connect to 6.5 is not a valid and current release or hasnt been released yet port 80: Connection timed out.
I am trying to install Centos LXC on Ubuntu 14.04 Virtual Machine (on Virtual Box). Any help is much appreciated.
Take a look at this scripts: https://github.com/tpokorra/lxc-scripts
centos-release-6-3.el6.centos.9.i386.rpm gives error 404
because i386 arch package no more exist so fetching error.