]> git.proxmox.com Git - mirror_lxc.git/blobdiff - templates/lxc-centos.in
confile: rename lxc.devttydir to lxc.tty.dir
[mirror_lxc.git] / templates / lxc-centos.in
index 3126bba1b7a5d0bf555d736428a51dc99c3a3233..a211636dc06e92384d3ecde9c5762241647ca024 100644 (file)
@@ -1,7 +1,7 @@
 #!/bin/bash
 
 #
-# template script for generating centos container for LXC
+# template script for generating CentOS container for LXC
 
 #
 # lxc: linux Container library
@@ -19,7 +19,7 @@
 
 # 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
+# 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
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
 #Configurations
-arch=$(arch)
-cache_base=@LOCALSTATEDIR@/cache/lxc/centos/$arch
 default_path=@LXCPATH@
-# We really need something better here!
-root_password=root
 
+# 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?
+# 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.
@@ -89,8 +137,9 @@ if [ "${CPE_NAME}" != "" -a "${ID}" = "centos" -a "${VERSION_ID}" != "" ]
 then
     centos_host_ver=${VERSION_ID}
     is_centos=true
-elif [ "${CPE_NAME}" != "" -a "${ID}" = "redhat" -a "${VERSION_ID}" != "" ]
+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 ]
@@ -103,22 +152,6 @@ then
     fi
 fi
 
-# Map a few architectures to their generic Centos repository archs.
-#
-# CentOS currently doesn't support ARM but it's copied here from
-# the Fedora template for completeness and that it will in the future.
-#
-# 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) arch=i386 ;;
-armv3l|armv4l|armv5l) arch=arm ;;
-armv6l|armv7l|armv8l) arch=armhfp ;;
-esac
-
 force_mknod()
 {
     # delete a device node if exists, and create a new one
@@ -128,12 +161,12 @@ force_mknod()
 configure_centos()
 {
 
-    # disable selinux in 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 ]]
+    if [ -f $rootfs_path/etc/selinux/config ]
     then
         sed -i '/^SELINUX=/s/.*/SELINUX=disabled/' $rootfs_path/etc/selinux/config
     fi
@@ -177,6 +210,13 @@ configure_centos()
         )
     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
@@ -210,16 +250,17 @@ configure_centos()
 DEVICE=eth0
 BOOTPROTO=dhcp
 ONBOOT=yes
-HOSTNAME=${UTSNAME}
+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}
+HOSTNAME=${utsname}
 EOF
 
     # set minimal hosts
@@ -230,7 +271,6 @@ EOF
     # set minimal fstab
     cat <<EOF > $rootfs_path/etc/fstab
 /dev/root               /                       rootfs   defaults        0 0
-none                    /dev/shm                tmpfs    nosuid,nodev    0 0
 EOF
 
     # create lxc compatibility init script
@@ -240,14 +280,19 @@ start on startup
 env container
 
 pre-start script
-        if [ "x$container" != "xlxc" -a "x$container" != "xlibvirt" ]; then
+        if [ "x\$container" != "xlxc" -a "x\$container" != "xlibvirt" ]; then
                 stop;
         fi
-        initctl start tty TTY=console
+
         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;
+        exit 0
 end script
 EOF
     elif [ "$release" = "5" ]; then
@@ -260,7 +305,10 @@ 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
-        sed -i 's|^1:|co:2345:respawn:/sbin/mingetty console\n1:|' $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
 
@@ -284,9 +332,47 @@ EOF
     mknod -m 600 ${dev_path}/initctl p
     mknod -m 666 ${dev_path}/ptmx c 5 2
 
-    echo "setting root passwd to $root_password"
+    # 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.
+    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=|\/\/
 
@@ -301,12 +387,24 @@ configure_centos_init()
         chroot ${rootfs_path} chkconfig udev-post off
     fi
     chroot ${rootfs_path} chkconfig network on
+
+    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
+    # check the mini CentOS was not already downloaded
     INSTALL_ROOT=$cache/partial
     mkdir -p $INSTALL_ROOT
     if [ $? -ne 0 ]; then
@@ -314,23 +412,50 @@ download_centos()
     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 openssh-server openssh-clients dhclient chkconfig rootfiles policycoreutils"
+    # 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)
-    cat <<EOF > $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
-mirrorlist=http://mirrorlist.centos.org/?release=$release&arch=$arch&repo=os
+baseurl=http://mirror.centos.org/altarch/7/os/$basearch/
 
 [updates]
 name=CentOS-$release - Updates
-mirrorlist=http://mirrorlist.centos.org/?release=$release&arch=$arch&repo=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
@@ -339,6 +464,13 @@ EOF
 
     $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
@@ -374,7 +506,7 @@ EOF
         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 $YUM install $PKG_LIST
+        chroot $INSTALL_ROOT $YUM0 install $PKG_LIST
         if [ $? -ne 0 ]; then
             echo "Failed to download the rootfs, aborting."
             return 1
@@ -396,12 +528,13 @@ EOF
 copy_centos()
 {
 
-    # make a local copy of the mini 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 -a $cache/rootfs/ $rootfs_path/
+    echo
     return 0
 }
 
@@ -419,7 +552,7 @@ install_centos()
 {
     mkdir -p /var/lock/subsys/
     (
-    flock -x 200
+    flock -x 9
     if [ $? -ne 0 ]; then
         echo "Cache repository is busy."
         return 1
@@ -429,14 +562,14 @@ install_centos()
     if [ ! -e "$cache/rootfs" ]; then
         download_centos
         if [ $? -ne 0 ]; then
-            echo "Failed to download 'centos base'"
+            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"
+            echo "Failed to update 'CentOS base', continuing with last known good cache"
         else
             echo "Update finished"
         fi
@@ -451,63 +584,85 @@ install_centos()
 
     return 0
 
-    ) 200>/var/lock/subsys/lxc-centos
+    ) 9>/var/lock/subsys/lxc-centos
 
     return $?
 }
 
-copy_configuration()
+create_hwaddr()
 {
+    openssl rand -hex 5 | sed -e 's/\(..\)/:\1/g; s/^/fe/'
+}
 
+copy_configuration()
+{
     mkdir -p $config_path
+
+    grep -q "^lxc.rootfs" $config_path/config 2>/dev/null || echo "
+lxc.rootfs = $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.utsname = $utsname
-lxc.tty = 4
-lxc.pts = 1024
-lxc.rootfs = $rootfs_path
-lxc.mount  = $config_path/fstab
-lxc.cap.drop = sys_module mac_admin mac_override sys_time
 
-lxc.autodev = $auto_dev
+# When using LXC with apparmor, uncomment the next line to run unconfined:
+#lxc.aa_profile = unconfined
 
 # example simple networking setup, uncomment to enable
-#lxc.network.type = $lxc_network_type
-#lxc.network.flags = up
-#lxc.network.link = $lxc_network_link
-#lxc.network.name = eth0
-# additional example for veth network type, static MAC address,
-# and persistent veth device name on host side
-#lxc.network.hwaddr = 00:16:3e:77:52:20
-#lxc.network.veth.pair = v-$name-e0
-
-#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
+#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
 
-    cat <<EOF > $config_path/fstab
-proc            proc         proc    nodev,noexec,nosuid 0 0
-devpts          dev/pts      devpts defaults 0 0
-sysfs           sys          sysfs defaults  0 0
 EOF
 
     if [ $? -ne 0 ]; then
-    echo "Failed to add configuration"
-    return 1
+        echo "Failed to add configuration"
+        return 1
     fi
 
     return 0
@@ -517,22 +672,22 @@ clean()
 {
 
     if [ ! -e $cache ]; then
-    exit 0
+        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
+        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
+        echo -n "Purging the download cache for CentOS-$release..."
+        rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
+        exit 0
 
-    ) 200>/var/lock/subsys/lxc-centos
+    ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-centos
 }
 
 usage()
@@ -540,37 +695,41 @@ usage()
     cat <<EOF
 usage:
     $1 -n|--name=<container_name>
-        [-p|--path=<path>] [-c|--clean] [-R|--release=<CentOS_release>] [-A|--arch=<arch of the container>]
+        [-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
+  -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 defaultto the host's release.
+  -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
-  -A,--arch         NOT USED YET. Define what arch the container will be [i686,x86_64]
+     --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 hp:n:cR: -l help,path:,rootfs:,name:,clean,release:,fqdn: -- "$@")
+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
-eval set -- "$options"
 
+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=$2; shift 2;;
+        --rootfs)       rootfs_path=$2; shift 2;;
         -n|--name)      name=$2; shift 2;;
-        -c|--clean)     clean=$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 ;;
@@ -582,6 +741,74 @@ if [ ! -z "$clean" -a -z "$path" ]; then
     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
@@ -600,7 +827,7 @@ fi
 #    utsname and hostname = Container_Name.Domain_Name
 
 if [ $(expr "$utsname" : '.*\..*\.') = 0 ]; then
-    if [ -n "$(dnsdomainname)" ]; then
+    if [[ "$(dnsdomainname)" != "" && "$(dnsdomainname)" != "localdomain" ]]; then
         utsname=${utsname}.$(dnsdomainname)
     fi
 fi
@@ -622,39 +849,25 @@ if [ -z "$release" ]; 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 Redhat host and release is missing, defaulting to 6 use -R|--release to specify release"
-        release=6
+        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
 
-# CentOS 7 and above should run systemd.  We need autodev enabled to keep
-# systemd from causing problems.
-#
-# There is some ambiguity here due to the differnce between versioning
-# of point specific releases such as 6.5 and the rolling release 6.  We
-# only want the major number here if it's a point release...
-
-mrelease=$(expr $release : '\([0-9]*\)')
-if [ $mrelease -gt 6 ]; then
-    auto_dev="1"
-else
-    auto_dev="0"
-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' passed in through default config by lxc-create
     if grep -q '^lxc.rootfs' $path/config 2>/dev/null ; then
-        rootfs_path=`grep 'lxc.rootfs =' $path/config | awk -F= '{ print $2 }'`
+        rootfs_path=$(sed -e '/^lxc.rootfs\s*=/!d' -e 's/\s*#.*//' \
+            -e 's/^lxc.rootfs\s*=\s*//' -e q $path/config)
     fi
 fi
-config_path=$default_path/$name
+config_path=$path
 cache=$cache_base/$release
 
 revert()
@@ -663,7 +876,6 @@ revert()
     lxc-destroy -n $name
     # maybe was interrupted before copy config
     rm -rf $path
-    rm -rf $default_path/$name
     echo "exiting..."
     exit 1
 }
@@ -678,21 +890,71 @@ fi
 
 install_centos
 if [ $? -ne 0 ]; then
-    echo "failed to install centos"
+    echo "failed to install CentOS"
     exit 1
 fi
 
 configure_centos
 if [ $? -ne 0 ]; then
-    echo "failed to configure centos for a container"
+    echo "failed to configure CentOS for a container"
     exit 1
 fi
 
 configure_centos_init
 
-if [ ! -z $clean ]; then
+if [ ! -z "$clean" ]; then
     clean || exit 1
     exit 0
 fi
-echo "container rootfs and config created, default root password is '$root_password'"
-echo "edit the config file to check/enable networking setup"
+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