]> git.proxmox.com Git - mirror_lxc.git/blobdiff - templates/lxc-oracle.in
confile: rename lxc.devttydir to lxc.tty.dir
[mirror_lxc.git] / templates / lxc-oracle.in
index 106150c9c25ab9727605e839f3e99c6ca5a56cba..f06b70ec37324987eabbafbbb017d21e424b7022 100644 (file)
@@ -1,15 +1,15 @@
-#!/bin/bash
+#!/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>
+# 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, combined OL4,5,6 into one template script
+# 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
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 #
 
-# use virbr0 that is setup by default by libvirtd
-lxc_network_type=veth
-lxc_network_link=virbr0
+# 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()
 {
@@ -46,10 +55,54 @@ is_btrfs_subvolume()
     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_configure()
+container_rootfs_patch()
 {
-    echo "Configuring container for Oracle Linux $container_release_major.$container_release_minor"
+    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
@@ -67,11 +120,17 @@ container_rootfs_configure()
     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
+        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
@@ -79,52 +138,73 @@ container_rootfs_configure()
         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
 
-    # 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=$name
-NM_CONTROLLED=no
-TYPE=Ethernet
-EOF
+    # 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
 
-    # set the hostname
-    cat <<EOF > $container_rootfs/etc/sysconfig/network
-NETWORKING=yes
-NETWORKING_IPV6=no
-HOSTNAME=$name
-EOF
-
     # 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
 
-    # set minimal hosts
-    echo "127.0.0.1 localhost $name" > $container_rootfs/etc/hosts
+    # 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
 
-    # this file has to exist for libvirt/Virtual machine monitor to boot the container
-    touch $container_rootfs/etc/mtab
-
-    # don't put devpts,proc, nor sysfs in here, it will already be mounted for us by lxc/libvirt
-    cat <<EOF > $container_rootfs/etc/fstab
-EOF
-
     # 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
@@ -151,17 +231,6 @@ EOF
         sed -i 's|action $"Setting network parameters|# LXC action $"Setting network parameters|' $container_rootfs/etc/init.d/NetworkManager 2>/dev/null
     fi
 
-    # 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
-        echo "mount -t tmpfs tmpfs /dev/shm" >>$container_rootfs/etc/rc.sysinit
-        echo "mount -t tmpfs tmpfs /dev/shm" >>$container_rootfs/etc/rc.d/rc.sysinit
-    fi
-
-    if [ $container_release_major = "6" ]; then
-        sed -i 's|mount -n -o remount /dev/shm >/dev/null 2>&1$|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$|mount -t tmpfs tmpfs /dev/shm # LXC|' $container_rootfs/etc/rc.d/rc.sysinit
-    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
@@ -200,8 +269,12 @@ EOF
     sed -i 's|^/sbin/hwclock|# LXC /sbin/nohwclock|' $container_rootfs/etc/rc.d/rc.sysinit
 
     # dont start lvm
-    sed -i 's|action $"Setting up Logical Volume Management:"|#action $"Setting up Logical Volume Management:"|' $container_rootfs/etc/rc.sysinit
-    sed -i 's|action $"Setting up Logical Volume Management:"|/bin/true #action $"Setting up Logical Volume Management:"|' $container_rootfs/etc/rc.d/rc.sysinit
+    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
@@ -210,31 +283,116 @@ EOF
     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.devttydir is specified in the config.
+    # 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
-    echo "lxc/tty1"    >>$container_rootfs/etc/securetty
-    echo "lxc/tty2"    >>$container_rootfs/etc/securetty
-    echo "lxc/tty3"    >>$container_rootfs/etc/securetty
-    echo "lxc/tty4"    >>$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
-    echo "pts/0"        >>$container_rootfs/etc/securetty
+    for i in 0 1 2 3 4; do
+        echo "pts/$i"        >>$container_rootfs/etc/securetty
+    done
 
-    # 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
+    # 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
 
-    # don't try to unmount swap
-    sed -i 's|\[ -f /proc/swaps \]|# LXC [ -f /proc/swaps ]|' $container_rootfs/etc/init.d/halt
+    # 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 '/1:2345:respawn/i cns:2345:respawn:/sbin/mingetty console' $container_rootfs/etc/inittab
+        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
@@ -248,9 +406,10 @@ EOF
 
 start on stopped rc RUNLEVEL=[2345]
 stop on runlevel [!2345]
+env container
 
 respawn
-exec /sbin/mingetty /dev/console
+exec /sbin/maygetty --nohangup --noclear /dev/console
 EOF
     fi
 
@@ -262,7 +421,7 @@ EOF
     # /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
-    else
+    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
 #
@@ -275,113 +434,55 @@ exec init 0
 EOF
     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
+    # start with a clean /var/log/messages
+    rm -f $container_rootfs/var/log/messages
 
-    # 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
-        mkdir -p $dev_path
-        if which chcon >/dev/null 2>&1 ; then
-            # ensure symlinks created in /dev have the right context
-            chcon -t device_t $dev_path
+    # 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
-    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 666  $dev_path/full c 1 7
-    mknod -m 600  $dev_path/initctl p
-
-    # set selinux labels same as host
-    if which chcon >/dev/null 2>&1 ; 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
-
-    # 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
 
-    # start with a clean /var/log/messages
-    rm -f $container_rootfs/var/log/messages
-
-    # add oracle user, set root password
+    # add oracle user
     chroot $container_rootfs useradd -m -s /bin/bash oracle
-    echo "oracle:oracle" | chroot $container_rootfs chpasswd
-    echo "root:root" | chroot $container_rootfs chpasswd
-    echo -e "Added container user:\033[1moracle\033[0m password:\033[1moracle\033[0m"
-    echo -e "Added container user:\033[1mroot\033[0m password:\033[1mroot\033[0m"
+    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"
-    # generate a hwaddr for the container with a high mac address
-    # see http://sourceforge.net/tracker/?func=detail&aid=3411497&group_id=163076&atid=826303
-    local hwaddr="fe:`dd if=/dev/urandom bs=8 count=1 2>/dev/null |od -t x8 | \
-                      head -1 |awk '{print $2}' | cut -c1-10 |\
-                      sed 's/\(..\)/\1:/g; s/.$//'`"
     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.utsname = $name
-lxc.devttydir = lxc
-lxc.tty = 4
-lxc.pts = 1024
-lxc.mount.auto = proc:mixed sys:ro
-lxc.hook.clone = @DATADIR@/lxc/hooks/clonehostname
-# 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 = mac_admin mac_override setfcap setpcap
-lxc.cap.drop = sys_module sys_nice sys_pacct
-lxc.cap.drop = sys_rawio sys_time
 EOF
     grep -q "^lxc.rootfs" $cfg_dir/config 2>/dev/null || echo "lxc.rootfs = $container_rootfs" >> $cfg_dir/config
 
@@ -389,31 +490,43 @@ EOF
         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 network settings were already specified
-    lxc_network_type=`grep '^lxc.network.type' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'`
-    if [ -z "$lxc_network_type" -a                     \
-        \( $host_distribution = "OracleServer" -o      \
-           $host_distribution = "Fedora" \) ]; then
-            echo "lxc.network.type = veth" >>$cfg_dir/config
-            echo "lxc.network.flags = up" >>$cfg_dir/config
-            echo "lxc.network.link = virbr0" >>$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.network.name = eth0
-lxc.network.mtu = 1500
-lxc.network.hwaddr = $hwaddr
-# Control Group devices: all denied except those whitelisted
-lxc.cgroup.devices.deny = a
-lxc.cgroup.devices.allow = c 1:3 rwm   # /dev/null
-lxc.cgroup.devices.allow = c 1:5 rwm   # /dev/zero
-lxc.cgroup.devices.allow = c 1:7 rwm   # /dev/full
-lxc.cgroup.devices.allow = c 5:0 rwm   # /dev/tty
-lxc.cgroup.devices.allow = c 1:8 rwm   # /dev/random
-lxc.cgroup.devices.allow = c 1:9 rwm   # /dev/urandom
-lxc.cgroup.devices.allow = c 136:* rwm # /dev/tty[1-4] ptys and lxc console
-lxc.cgroup.devices.allow = c 5:2 rwm   # /dev/ptmx pty master
+lxc.net.0.name = eth0
+lxc.net.0.mtu = 1500
 EOF
 }
 
@@ -431,21 +544,78 @@ container_rootfs_clone()
     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"
-            db_load_cmd="db4.3_load"
         fi
         if [ $host_distribution = "OracleServer" -o \
              $host_distribution = "Fedora" ]; then
             db_dump_cmd="db_dump"
-            db_load_cmd="db43_load"
         fi
 
-        cmds="$cmds $db_dump_cmd $db_load_cmd file"
+        cmds="$cmds $db_dump_cmd file"
     fi
     for cmd in $cmds; do
         which $cmd >/dev/null 2>&1
@@ -454,79 +624,104 @@ container_rootfs_create()
         fi
     done
 
-    mkdir -p @LOCALSTATEDIR@/lock/subsys/lxc
+    mkdir -p @LOCALSTATEDIR@/lock/subsys
     (
-        flock -x 200
+        flock -x 9
         if [ $? -ne 0 ]; then
             die "The template is busy."
         fi
 
-        echo "Downloading release $container_release_major.$container_release_minor for $basearch"
+        echo "Yum installing release $container_release_major.$container_release_minor for $basearch"
 
-        # get yum repo file
         if [ -n "$repourl" ]; then
             yum_url=$repourl
         else
             yum_url=http://public-yum.oracle.com
         fi
-        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
+        if [ $container_release_major = "4" -o $container_release_major = "5" ]; then
+            latest_L="el"
+            latest_U="EL"
         else
-            die "Unsupported release $container_release_major"
+            latest_L="ol"
+            latest_U="OL"
         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 "Failed to download repo file $yum_url/$repofile"
-        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
-            if [ $container_release_major = "4" -o $container_release_major = "5" ]; then
-                repo="el"$container_release_major"_"$container_release_minor
+        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
-                repo="ol"$container_release_major"_"$container_release_minor
+                die "Unsupported release $container_release_major"
             fi
-        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"
+
+            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
-        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
+
+            # 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
-                repo="ol"$container_release_major"_u"$container_release_minor"_base"
+                die "Unsupported release $container_release_major.$container_release_minor"
             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"
+            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
-        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
+
+        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
@@ -559,12 +754,21 @@ container_rootfs_create()
         fi
         if [ x"$redo_pkgs" != x ]; then
             rpm --root $container_rootfs --nodeps -e $redo_pkgs
-            yum $yum_args install $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
@@ -579,7 +783,7 @@ container_rootfs_create()
             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 |$db_load_cmd $db.new
+                $db_dump_cmd $db |chroot $container_rootfs db_load /var/lib/rpm/`basename $db`.new
                 mv $db.new $db
             done
         fi
@@ -590,7 +794,10 @@ container_rootfs_create()
         rm -f $container_rootfs/var/lib/rpm/__db*
         chroot $container_rootfs rpm --rebuilddb >/dev/null 2>&1
 
-    ) 200>@LOCALSTATEDIR@/lock/subsys/lxc-oracle-$name
+    ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-oracle-$name
+    if [ $? -ne 0 ]; then
+        exit 1
+    fi
 }
 
 container_release_get()
@@ -620,22 +827,25 @@ usage()
   -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. local yum mirror)
+  -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: -- "$@")
+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
 
-arch=$(uname -m)
 eval set -- "$options"
 while true
 do
@@ -649,6 +859,8 @@ do
         -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
@@ -660,6 +872,25 @@ if [ "$(id -u)" != "0" ]; then
     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
@@ -717,8 +948,8 @@ else
         if [ $host_distribution = "OracleServer" ]; then
             container_release_version=$host_release_version
         else
-            echo "No release specified with -R, defaulting to 6.4"
-            container_release_version="6.4"
+            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}'`