[lxc-devel] Not a Patch: 03/02... The follow-on script...
Michael H. Warfield
mhw at WittsEnd.com
Tue Nov 12 03:29:00 UTC 2013
Ok all...
This is my 3rd piece. It's "my script" that runs with "my setup" to
start up containers at boot with systemd on Fedora.
I don't want to step on the valuable work that Stéphane is doing in this
area but I hope this provides him with ideas. Installed
in /usr/libexec/lxc/lxc-startup, it provides the additional
functionality to start containers when Fedora restarts.
Out of respect for other people's work right now, I'm not offering this
as a patch to the source tree. It's just a suggestion how I would do
this. There are a lot of things in this script that is very maliable
and it depends on a couple of things that need to be refined (such as
LXC_PATH).
In this script, a formalized way of obtaining a list of containers (and
configuration files) qualified to be autobooted would be good. I
currently use the output of lxc-ls in combination of an arbitrary
LCM_PATH of /var/lib/lxc, neither of which may be optimal
Offered with the proviso that "it works for me"... Attached below the
jump.
Regards,
Mike
--
Michael H. Warfield (AI4NB) | (770) 978-7061 | mhw at WittsEnd.com
/\/\|=mhw=|\/\/ | (678) 463-0932 | http://www.wittsend.com/mhw/
NIC whois: MHW9 | An optimist believes we live in the best of all
PGP Key: 0x674627FF | possible worlds. A pessimist is sure of it!
--
#!/bin/sh -
# lxc-startup
# Start up a list of containers...
# lxc-run [-b] [-f] [-h] [vm list]
# Wrapper script to run a bunch of containers optionally at boot time
#
# -l n : Boot all stopped containers with bootlevel >= n
# : default 0
# -b : Only start the container if onboot is true
# : equivalent to "-l 1" (also sets -q)
# -F : Force boot a container even if disabled is true
# : equivalent to "-l -1"
# -h : Print this message and exit
# -q : Quiet (disable ECHO)
# -v : Enable debug prints (enable ECHO)
# -n : Optional individual VM (maybe be used multiple times)
# [vm list] - list of VM's to start. Default is any that are not disabled.
#
# Authors:
# Michael H. Warfield <mhw at wittsend.com>
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
declare -i VERBOSITY=1
START_LEVEL=0
LASTCONFIG=undefined
# Not sure what the deal is but it seems to be a problem if we
# start kicking off containers too soon and this is non-blocking
# anyways, so let's just give the system a little time to catch
# it's breath before kicking these babies off...
# This is a variable to start next delay and is fed from the configuration
# files...
#
# This sets the initial delay...
DELAY=5
DELAY_DEFAULT=2
# A few generic ECHO commands for verbosity...
# Most of these are not currently used...
ECHO_OFF=": echo"
ECHO=": echo"
ECHO1=": echo"
ECHO2=": echo"
ECHO3=": echo"
ECHO4=": echo"
# BOOTLIST will be a newline delimited prioritized list of our
# containers to be processed.
#
# Currently, this list is space delimited. This is not good if
# we allow white space in container names or paths. A '/' may
# be better as a delimiter just because it screws up pathnames
# and nobody in their right mind would use it in a name.
#
# Fields:
# Priority
# Post Start Delay
# Container Name
# Container Config file
BOOTLIST=
function usage() {
echo "usage: $0 [-b] [-F] [-h] [-q] [-v] [-l n] [-n VM] [--] [VM list]"
}
function help() {
usage
echo "
Run one or more containers with a halt monitor
Register a new container if necessary
Options:
-b : Only start the container if lxc.onboot is true
-F : Force boot a container even if lxc.disabled is true
-l n : Boot containers with bootlevel >= n
-h : Print this message and exit
-q : Quiet (disable ECHO)
-v : Enable debug prints (enable ECHO)
-n : Optional individual VM (maybe be used multiple times)
VM list : Optional list of VM's to start
If the list of VM names is empty, it defaults to all available
subject to boot and force options.
"
}
# Rotate log based on date
# argvs == logfile to rotate...
function log_rotate() {
local STAMP=$(date +%F-%T)
while [[ ${1} != "" ]]
do
local FNAME=$1
if [[ ${FNAME} != "" && -f ${FNAME} && ! -f ${FNAME}-${STAMP} ]]
then
mv ${FNAME} ${FNAME}-${STAMP}
fi
shift
done
}
# Checks the boot order priority in a config file and
# returns it plus the post start delay befoer starting
# the next container...
# This is my own convention... These are options in the config
# file under lxc-boot.* to control higher level boot options.
# For "legacy" reasons (my past efforts) this honors lxc-boot.disabled
# and lxc-boot.onboot, even though most of the functionality is
# subsumed under lxc-boot.autoboot. All of these parameters are,
# of course, maliable and adaptable to what ever we want.
CCG_GROUP=lxc-boot
# Function is called with the realpath to the configuration file.
# Function returns echoing the value of "priority delay" where
# pritority is the positive value boot order priority of the
# container and the delay to wait before starting another container.
function check_boot_level() {
local CNAME
local AUTOBOOT
local DISABLED
local ONBOOT
local MY_DELAY
local ret
CNAME=$1
ret=$2
DISABLED=`sed -e "/$CFG_GROUP\.disabled\s*=\s*/!d" -e 's/.*=\s*//' -e q ${CNAME}`
ONBOOT=`sed -e "/$CFG_GROUP\.onboot\s*=\s*/!d" -e 's/.*=\s*//' -e q ${CNAME}`
AUTOBOOT=`sed -e "/$CFG_GROUP\.autoboot\s*=\s*/!d" -e 's/.*=\s*//' -e q ${CNAME}`
MY_DELAY=`sed -e "/$CFG_GROUP\.delay\s*=\s*/!d" -e 's/.*=\s*//' -e q ${CNAME}`
# If disabled is true, then override everything...
# More severe disables can be applied more negative numbers.
if [[ "${DISABLED}" == true || "${DISABLED}" == yes ]]
then
AUTOBOOT=-1;
fi
# If onboot is set and autoboot is not set, set autoboot to 1
if [[ "${ONBOOT}" == true || "${ONBOOT}" == yes ]]
then
if [[ ${AUTOBOOT} == "" ]]
then
AUTOBOOT=1;
fi
fi
if [[ "${AUTOBOOT}" != "" ]]
then
ret=${AUTOBOOT}
fi
if [[ "${MY_DELAY}" == "" ]]
then
MY_DELAY=${DELAY_DEFAULT}
fi
echo "${ret} ${MY_DELAY}"
return 0
}
#
# Need to process our command line options
#
# We'll take a couple of shortcuts first.
# If there are no other parameters other than "start", "stop", or "restart",
# then we'll take that... That makes this compatible with System V init
# and Upstart.
if [[ ${1} == "start" ]]
then
shift
# This is an exect out of init. Make ssshhh...
VERBOSITY=0
START_LEVEL=1
fi
if [[ ${1} == "stop" ]]
then
echo "Stop is not currently implimented"
VERBOSITY=0
exit 0
fi
if [[ ${1} == "restart" ]]
then
echo "Restart is not currently implimented"
VERBOSITY=0
exit 0
fi
shortoptions='vqhl:n:Fb'
longoptions='verbose,quiet,help,level:,name:,force,boot'
getopt=$(getopt -o $shortoptions --longoptions $longoptions -- "$@")
if [[ $? != 0 ]]
then
usage
exit 1;
fi
eval set -- "$getopt"
while true; do
case "$1" in
-h|--help)
help
exit 1
;;
-n|--name)
shift
VM_LIST="$VM_LIST $1"
shift
;;
-F|--force)
shift
START_LEVEL=-1
;;
-v|--verbose)
shift
VERBOSITY=$(( $VERBOSITY + 1 ))
ECHO="echo"
;;
-q|--quiet)
shift
VERBOSITY=0
ECHO=": echo"
;;
-b|--boot)
VERBOSITY=0
shift
START_LEVEL=1
;;
-l|--level)
shift
START_LEVEL=$1
shift
;;
--)
shift
break
;;
-*)
echo $1
usage
exit 1
;;
*)
break
;;
esac
done
if [[ ${VERBOSITY} -gt 0 ]]
then
ECHO="echo"
else
ECHO=": echo"
fi
# What ever is left should be a list of VM's or NULL
if [[ "$*" ]]
then
VM_LIST="$VM_LIST $*"
for CNAME in $VM_LIST
do
if [[ -f /var/lib/lxc/${CNAME}/config ]]
then
STATUS=$(lxc-info -n ${CNAME} 2> /dev/null | sed -e '/[Ss]tate:/!d' -e 's/[Ss]tate:.*\s//')
FNAME=$(realpath /var/lib/lxc/${CNAME}/config)
BOOT=$(check_boot_level "${FNAME}" 0)
${ECHO_OFF} "${BOOT} ${CNAME} ${FNAME}"
BOOTLIST="${BOOTLIST}
${BOOT} ${CNAME} ${FNAME}"
fi
done
fi
if [[ ! "$VM_LIST" ]]
then
# Ubuntu convention...
# These should be links to conf files
# name format "container_name{.conf}
if [[ -d /etc/lxc/auto ]]
then
for f in $( ls /etc/lxc/auto )
do
if [[ -s /etc/lxc/auto/$f ]]
then
FNAME=$( realpath -e "/etc/lxc/auto/$f" )
CNAME="$(basename $f .conf)"
# Ok... Just for giggles, let's do a
# little comparison... The config file
# SHOULD be in a directory which matches
# the container name or maymhem may follow.
DIRNAME=$(dirname ${FNAME})
CDIR=$(basename ${DIRNAME})
STATUS=$(lxc-info -n ${CNAME} 2> /dev/null | sed -e '/[Ss]tate:/!d' -e 's/[Ss]tate:.*\s//')
if [[ "${CNAME}" != "${CDIR}" ]]
then
${ECHO} "Warning! Container directory does not match autoboot name - ${CNAME} != ${CDIR}"
NSTATUS=$(lxc-info -n ${CDIR} 2> /dev/null | sed -e '/[Ss]tate:/!d' -e 's/[Ss]tate:.*\s//')
if [[ ${STATUS} == "" && ${NSTATUS} != "" ]]
then
${ECHO} "Switching to $CDIR for container name"
# This is a bit of a heuristic but, if it fails,
# some chump is doing something stupid that they
# need to manually correct.
CNAME=$CDIR
STATUS=${NSTATUS}
fi
fi
if [[ ${STATUS} == "STOPPED" ]]
then
BOOT=$(check_boot_level "${FNAME}" 1)
${ECHO} "${BOOT} ${CNAME} ${FNAME}"
BOOTLIST="${BOOTLIST}
${BOOT} ${CNAME} ${FNAME}"
else
${ECHO} "Container ${CNAME} is ${STATUS} and not in state STOPPED, skipping"
fi
else
${ECHO} "/etc/lxc/auto/$f not a symlink"
fi
done
fi
VM_LIST=$(lxc-ls)
for CNAME in $VM_LIST
do
if [[ -f /var/lib/lxc/${CNAME}/config ]]
then
STATUS=$(lxc-info -n ${CNAME} 2> /dev/null | sed -e '/[Ss]tate:/!d' -e 's/[Ss]tate:.*\s//')
FNAME=$(realpath /var/lib/lxc/${CNAME}/config)
BOOT=$(check_boot_level "${FNAME}" 0)
${ECHO_OFF} "${BOOT} ${CNAME} ${FNAME}"
BOOTLIST="${BOOTLIST}
${BOOT} ${CNAME} ${FNAME}"
fi
done
fi
# Need to deal with the condition where VMLIST is not NULL...
SORTBOOT=$( echo -n "$BOOTLIST" | sort --key=1nr,4 )
${ECHO} "START_LEVEL = ${START_LEVEL} ${DELAY}"
echo "$SORTBOOT" | while read PRIORITY POST_DELAY CNAME CONFIG
do
if [[ ${PRIORITY} = "" ]]
then
continue;
fi
# Only one startup per config!
# We sorted on this but this is only good if
# it's within the same priority! Not robust!
if [[ "${CONFIG}" == "${LASTCONFIG}" ]]
then
continue
fi
LASTCONFIG="${CONFIG}"
if [[ ${PRIORITY} -ge ${START_LEVEL} ]]
then
STATUS=$(lxc-info -n ${CNAME} 2> /dev/null | sed -e '/[Ss]tate:/!d' -e 's/[Ss]tate:.*\s//')
if [[ ${STATUS} == "" ]]
then
${ECHO} "Unknown container: ${PRIORITY} ${POST_DELAY} \"${CNAME}\" \"${CONFIG}\""
elif [[ ${STATUS} != "STOPPED" ]]
then
${ECHO} "Not Stopped: ${PRIORITY} ${POST_DELAY} \"${CNAME}\" \"${CONFIG}\""
else
${ECHO} "Will boot: ${PRIORITY} ${POST_DELAY} \"${CNAME}\" \"${CONFIG}\""
LXC_LOGDIR=$(dirname "${CONFIG}")
log_rotate ${LXC_LOGDIR}/console_out.log ${LXC_LOGDIR}/console_log.log ${LXC_LOGDIR}/logfile.log
if [[ ${DELAY} != "" && ${DELAY} -gt 0 ]]
then
sleep ${DELAY}
fi
lxc-start -d -c ${LXC_LOGDIR}/console_out.log -L ${LXC_LOGDIR}/console_log.log -o ${LXC_LOGDIR}/logfile.log -n ${CNAME}
# Now set the delay to this container's delay...
DELAY=${POST_DELAY}
fi
else
${ECHO} "Won't boot: ${PRIORITY} ${POST_DELAY} \"${CNAME}\" \"${CONFIG}\""
fi
done
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 482 bytes
Desc: This is a digitally signed message part
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20131111/c36f9bbe/attachment.pgp>
More information about the lxc-devel
mailing list