-
-
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 <[email protected]> | |
| # Ramez Hanna <[email protected]> | |
| # 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" |
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
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).