@ -17,7 +17,7 @@ TEXTDOMAIN=cl_lxc
export PATH="/lib/rc/bin:$PATH"
set -ueo pipefail
check_simultaneous_run() { # Проверим на повторный запуск
check_simultaneous_run(){ # Проверим на повторный запуск
lock=/tmp/cl-lxc.lock
if ! mkdir $lock &>/dev/null
then
@ -37,7 +37,7 @@ print_help(){
${0##*/} installation, configuration and update of an LXC container with Calculate Linux on board
Parameters:
-D, --distro select distribution flavour ('list' to view all that applies)
-P, --profile select profile flavour ('list' to view all that applies)
-c, --create create new container
--path path to container
-p, --prepare get rootfs ready for update
@ -61,7 +61,7 @@ get_args(){
exit 1
fi
}
distro _=
profile _=
create_=0
path_=
prepare_=0
@ -72,9 +72,9 @@ get_args(){
while (( $# > 0 ))
do
case "$1" in
-D|--distro )
-P|--profile )
check_val $@
distro _=$2
profile _=$2
shift
;;
-c|--create)
@ -121,9 +121,9 @@ get_args(){
esac
shift
done
if [ "$distro _" == 'list' ]
if [ "$profile _" == 'list' ]
then
print_distro
print_profile
exit 0
elif (( $# == 1 ))
then
@ -133,6 +133,11 @@ get_args(){
echo $"Container name contains wrong characters." >&2
exit 1
fi
if [[ $lxc_ = 'scratch' ]]
then
echo $"The name '$lxc_' is reserved. Use a different container name." >&2
exit 1
fi
else
print_help "usage"
exit 1
@ -141,31 +146,39 @@ get_args(){
true
}
print_distro(){
print_profile(){
local profile_dir
if [[ -e /var/db/repos/container/profiles/profiles.desc ]]
then
profile_dir=/var/db/repos/container
else
profile_dir=/var/calculate/tmp/update/container
if [[ ! -d $profile_dir ]]
then
git clone https://github.com/calculatelinux/container $profile_dir &>/dev/null
else
git -C $profile_dir pull &>/dev/null
fi
fi
# Отобразим список доступных профилей или проверим наличие запрошенного
if (( $# == 0 ))
then
echo $"Distributive:
[CCS] Calculate Container Scratch (by default)
[CDC] Calculate Directory Container
[CCG] Calculate Container Games"
return
fi
case "$1" in
CCS)
echo "Calculate Container Scratch"
;;
CDC)
echo "Calculate Directory Container"
;;
CCG)
echo "Calculate Container Games"
;;
esac
echo $"Profile:"
grep "^amd64" ${profile_dir}/profiles/profiles.desc | awk '{print " * " $2, $3}' OFS=' (' ORS=')\n'
return
else
if ! grep -q "^amd64\s*${1}/" ${profile_dir}/profiles/profiles.desc
then
return 1
fi
fi
}
set_vars(){
lxc_release=22.0.1
cl_lxc_ver=$(ls -d /var/db/pkg/sys-apps/calculate-toolkit-* 2>/dev/null) \
&& cl_lxc_ver=${cl_lxc_ver:39} \
|| cl_lxc_ver=
net_domain=$(hostname -f)
path_def=$(lxc-config lxc.lxcpath 2>/dev/null) || (
printf $"To run the script, install the '%s' package.\n" app-containers/lxc >&2
@ -239,38 +252,40 @@ set_vars(){
num_next=
fi
case "$distro_" in
CCS|ccs)
lxc_distro=CCS
;;
CDC|cdc)
lxc_distro=CDC
;;
CCG|ccg)
lxc_distro=CCG
;;
'')
if [ $prepare_ == 1 ] || [ $upgrade_ == 1 ]
# taiga/amd64/20 -> taiga
lxc_profile=${profile_%%/*}
if [[ $lxc_profile == "" ]]
then
if [[ $prepare_ == 1 || $upgrade_ == 1 ]]
then
lxc_distro =$(file $path_work/$lxc_/rootfs$num_cur/etc/portage/make.profile | \
lxc_profile=$(file $path_work/$lxc_/rootfs$num_cur/etc/portage/make.profile | \
awk -F '/profiles/' '{ print $2 }' | awk -F '/' '{ print $1 }')
# совместимость с о старыми системами
case "$lxc_profile" in
CCS|CDS)
lxc_profile=scratch
;;
CCG)
lxc_profile=games
;;
esac
else
lxc_distro=CCS
lxc_profile=scratch
fi
;;
*)
echo $"Wrong --distro parameter, use 'list' to view accepted values." >&2
exit 1
;;
esac
else
print_profile $lxc_profile || {
echo $"Wrong --profile parameter, use 'list' to view accepted values." >&2
exit 1
}
fi
true
}
debug_vars(){
local log=/var/log/calculate/cl-lxc.log
cat > /var/log/calculate/cl-lxc.log <<-EOF
lxc_release = $lxc_release
cl_ lxc_ve r = $cl_ lxc_ve r
net_domain = $net_domain
path_def = $path_def
name_lxc = $name_lxc
@ -285,11 +300,20 @@ debug_vars(){
type_fs = $type_fs
num_cur = $num_cur
num_next = $num_next
lxc_distro = $lxc_distro
lxc_profile = $lxc_profile
EOF
}
show(){
echo ---------------------------------------------
echo $@
echo ---------------------------------------------
}
launch_message(){
printf $"Your container is ready. To start it, please run 'lxc-start %s'.\n" $name_lxc
}
check_vars(){
program_name=${0##*/}
if [ "$path_" != '' ] && ! [ -d "$path_" ]
@ -355,8 +379,8 @@ check_vars(){
true
}
create_base() {
ebegin $"Downloading" $(print_distro $lxc_distro)
create_base(){
ebegin $"Downloading Calculate Linux"
# Создадим подтом, чтобы контейнер не участвовал в бэкапе btrbk
if [ ! -e $path_cache ]
@ -368,19 +392,21 @@ create_base() {
mkdir $path_cache
fi
fi
lxc-create -n $lxc_distro -t download -- --server $mirror_ \
--arch x86_64 --dist $lxc_distro --release $lxc_release &>/dev/null || {
lxc-create -n scratch -t download -- --server $mirror_ \
--arch x86_64 --dist scratch --release live \
2>>/var/log/calculate/cl-lxc-error.log >/dev/null || {
eend $? || true
eerror $"Failed to run lxc-create" >&2
rm -rf $path_cache
rm -rf $path_def/s cr at ch
exit $?
}
eend
mv $path_def/$lxc_distro $path_cache/$lxc_distro
mv $path_def/scratch $path_cache/scratch
true
}
create_lxc() {
create_lxc(){
echo $"Creating container $name_lxc"
if [ $type_fs = 'btrfs' ]
then
@ -402,7 +428,7 @@ create_lxc() {
eend
else
ebegin $"Copying base rootfs"
cp -a $reflink $path_cache/$lxc_distro /rootfs $path_lxc/rootfs
cp -a $reflink $path_cache/scratch /rootfs $path_lxc/rootfs
eend
fi
@ -433,9 +459,9 @@ create_lxc() {
then
ebegin $"Moving /var/calculate to a separate mount point"
# Очистка и создание пути для монтирования ресурсов из хостовой машины
mv $path_lxc/rootfs/var/calculate $path_lxc; mkdir $path_lxc/rootfs/var/calculate
calculate_mount="lxc.mount.entry = ${path_lxc}/calculate var/calculate none rw,bind 0 0
"
mv $path_lxc/rootfs/var/calculate $path_lxc
mkdir $path_lxc/rootfs/var/calculate
calculate_mount= "lxc.mount.entry = ${path_lxc}/calculate var/calculate none rw,bind 0 0"$'\n'
calculate_dir="${path_lxc}/calculate"
eend
else
@ -476,6 +502,9 @@ create_lxc() {
auto-sync = Yes
sync-type = git
EOF
else
rm -rf ${path_lxc}/rootfs/var/db/repos/container
mkdir ${path_lxc}/rootfs/var/db/repos/container
fi
ebegin $"Running container setup"
@ -485,11 +514,11 @@ create_lxc() {
net_conf=none
network_conf="lxc.net.0.type = none"
cp /etc/resolv.conf $path_lxc/rootfs/etc
echo -e "\nconfig_eth0=\"noop \"" >> $path_lxc/rootfs/etc/conf.d/net
echo -e "\nrc_provide=\"net \"" >> $path_lxc/rootfs/etc/conf.d/net
else
net_conf=veth
local random_mac=$(printf '06:%02X:%02X:%02X:%02X:%02X\n' \
$[RANDOM%256] $[RANDOM%256] $[RANDOM%256] $[RANDOM%256] $[RANDOM%256] )
$((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)) )
local veth_pair="lxc.net.0.veth.pair = lxc-${name_lxc::11}"
if grep -q "$veth_pair" -r ${path_def}/*/config &>/dev/null
then
@ -506,15 +535,25 @@ create_lxc() {
EOF
)
fi
cat <<- EOF >> ${path_lxc}/config
#------------------------------------------------------------------------------
# Modified cl-lxc-${cl_lxc_ver}
# For additional config options, please look at lxc.container.conf(5)
#------------------------------------------------------------------------------
# перенесем базовый config удалив настройку сети
cp $path_cache/$lxc_distro/config ${path_lxc}/config
sed -i '/lxc.net.0.type = empty/d' ${path_lxc}/config
sed -i -r 's/(lxc.mount.auto)/#\1/g' ${path_lxc}/config
sed -i "s/${lxc_distro}/${name_lxc}/g" ${path_lxc}/config
# Distribution configuration
lxc.include = /usr/share/lxc/config/common.conf
lxc.arch = x86_64
lxc.mount.entry = none dev/shm tmpfs rw,nosuid,nodev,create=dir
cat <<- EOF >> ${path_lxc}/config
# Container specific configuration
lxc.rootfs.path = dir:/var/calculate/lxc/${name_lxc}/rootfs
lxc.uts.name = ${name_lxc}
# Network configuration
${network_conf}
# Mount points
${calculate_mount}${portage_mount}
lxc.mount.entry = /var/db/repos/calculate var/db/repos/calculate none ro,bind 0 0
lxc.mount.entry = /var/db/repos/container var/db/repos/container none ro,bind 0 0
@ -526,12 +565,6 @@ create_lxc() {
ebegin $"Configuring utility variables"
cat <<- EOF > ${calculate_dir}/calculate.env
[install]
os_install_net_hostname = ${name_lxc}
os_install_net_domain = ${net_domain}
os_install_locale_lang = ${LANG/.UTF-8/}
os_install_clock_timezone = $(cat /etc/timezone)
[update]
cl_update_rep_name =
cl_update_rep_url =
@ -540,6 +573,23 @@ create_lxc() {
EOF
eend
ebegin $"Preparing first boot setup script"
cat <<- EOF > $path_lxc/rootfs/etc/local.d/firststart.start
rm /etc/local.d/firststart.start
rm /etc/calculate/calculate.env
EOF
chmod 755 $path_lxc/rootfs/etc/local.d/firststart.start
cat <<- EOF > $path_lxc/rootfs/etc/calculate/calculate.env
# Parameters for firststart.start
[install]
os_install_net_hostname = ${name_lxc}
os_install_net_domain = ${net_domain}
os_install_locale_lang = ${LANG/.UTF-8/}
os_install_clock_timezone = $(cat /etc/timezone)
EOF
eend
ebegin $"Creating templates"
mkdir -p ${calculate_dir}/templates/default
cat <<- EOF > ${calculate_dir}/templates/default/.calculate_directory
@ -556,13 +606,44 @@ create_lxc() {
$(emerge --info 2>/dev/null | grep PORTAGE_BINHOST)
EOF
eend
[ -z "$name_upgrading" ] && printf $"Your container is ready. To start it, please run 'lxc-start %s'.\n" $name_lxc
true
if [[ -z "$name_upgrading" && $lxc_profile == 'scratch' ]]
then
launch_message
fi
}
start_container(){
ebegin $"Starting container"
lxc-start $name_lxc
# ожидание первоначальной настройки контейнера
while ! lxc-attach $name_lxc -- ps ax | grep 'init \[3\]' > /dev/null
do
sleep 0.1
done
eend
}
update_prepare() {
printf $"Package update for container %s\n" $name_lxc
change_profile(){
echo
echo $"Change the profile to $lxc_profile"
start_container
cl-update -s
lxc-attach $name_lxc -- cl-update-profile -f $lxc_profile
echo
echo $"Install packages from profile $lxc_profile"
einfo $"Launching package update"
lxc-attach $name_lxc -- cl-update -f
eend
launch_message
}
update_prepare(){
#printf $"Package update for container %s\n" $name_lxc
ebegin $"Moving installed packages, flags and masks from main container"
for migrate_file in /etc/portage/package.accept_keywords/custom \
/etc/portage/package.mask/custom \
@ -570,7 +651,8 @@ update_prepare() {
/etc/portage/package.use/custom \
/etc/portage/sets/custom
do
cp ${path_work}/${name_upgrading}/rootfs${num_cur}${migrate_file} ${path_lxc}/rootfs${migrate_file} &>/dev/null || true
cp ${path_work}/${name_upgrading}/rootfs${num_cur}${migrate_file} \
${path_lxc}/rootfs${migrate_file} &>/dev/null || true
done
eend
@ -584,17 +666,50 @@ update_prepare() {
done
eend
ebegin $"Starting container"
lxc-start $name_lxc
# ожидание первоначальной настройки контейнера
while ! lxc-attach $name_lxc -- ps ax | grep 'init \[3\]' > /dev/null
do
sleep 0.1
done
ebegin $"Preparing first boot setup script"
cat <<- EOF > $path_lxc/rootfs/etc/local.d/firststart.start
rm /etc/local.d/firststart.start
rm /etc/calculate/calculate.env
EOF
chmod 755 $path_lxc/rootfs/etc/local.d/firststart.start
# если обновляемый контейнер ни разу не запускался, возьем временный конфиг
if [[ -e ${path_work}/${name_upgrading}/rootfs${num_cur}/etc/calculate/calculate.env ]]
then
cp ${path_work}/${name_upgrading}/rootfs${num_cur}/etc/calculate/calculate.env \
$path_lxc/rootfs/etc/calculate
else
local lxc_host=$(grep localhost ${path_work}/${name_upgrading}/rootfs${num_cur}/etc/hosts | awk '{print $2}')
local os_install_net_hostname=${lxc_host%%.*}
local os_install_net_domain=${lxc_host#*.}
local os_install_locale_lang=$(grep 'LANG=' ${path_work}/${name_upgrading}/rootfs${num_cur}/etc/env.d/02locale)
local os_install_clock_timezone=$(cat ${path_work}/${name_upgrading}/rootfs${num_cur}/etc/timezone)
cat <<- EOF > $path_lxc/rootfs/etc/calculate/calculate.env
# Parameters for firststart.start
[install]
os_install_net_hostname = ${os_install_net_hostname}
os_install_net_domain = ${os_install_net_domain}
os_install_locale_lang = ${os_install_locale_lang:6:5}
os_install_clock_timezone = ${os_install_clock_timezone}
EOF
fi
eend
start_container
cl-update -s
einfo $"Launching package update"
if [[ $(file $path_lxc/rootfs/etc/portage/make.profile | \
awk -F '/profiles/' '{ print $2 }' | awk -F '/' '{ print $1 }') != $lxc_profile ]]
then
echo
echo $"Change profile to $lxc_profile"
lxc-attach $name_lxc -- cl-update-profile -f $lxc_profile
fi
echo
echo $"Launching package update"
lxc-attach $name_lxc -- cl-update -f
rm -rf "$path_lxc/rootfs/var/calculate/{tmp/*,templates/*}"
find $path_lxc/rootfs/etc/init.d -type l -name net.* -exec unlink {} \;
@ -634,7 +749,7 @@ update_prepare() {
}
upgrade_lxc() {
upgrade_lxc(){
echo $"Preparing to start new root"
ebegin $"Moving image to $name_upgrading/rootfs$num_next"
@ -658,8 +773,8 @@ upgrade_lxc() {
eend
ebegin $"Copying ssh keys"
cp $path_work/$name_upgrading/rootfs$num_cur/etc/ssh/*_ key* \
$path_work/$name_upgrading/rootfs$num_next/etc/ssh 2>/dev/null | true
cp $path_work/$name_upgrading/rootfs$num_cur/etc/ssh/ssh_* key* \
$path_work/$name_upgrading/rootfs$num_next/etc/ssh 2>/dev/null || true
eend
ebegin $"Preparing first boot setup script"
@ -672,7 +787,8 @@ upgrade_lxc() {
eend
ebegin $"New root setup"
sed -i "s#$path_def/$name_upgrading/rootfs[0-9]*#$path_def/$name_upgrading/rootfs$num_next#" $path_work/$name_upgrading/config
sed -i "s#$path_def/$name_upgrading/rootfs[0-9]*#$path_def/$name_upgrading/rootfs$num_next#" \
$path_work/$name_upgrading/config
eend
if [ ! -z $(lxc-ls --running --filter "^$name_upgrading$") ]
@ -707,12 +823,12 @@ upgrade_lxc() {
true
}
diff_pkg() {
diff_pkg(){
# Считаем версии сборок
cur_ver=$(grep os_linux_build $path_work/$name_upgrading/rootfs$num_cur/var/lib/calculate/calculate.env | sed 's/.*os_linux_build\s*=\s*//')
next_ver=$(grep os_linux_build $path_lxc_prepare/var/lib/calculate/calculate.env | sed 's/.*os_linux_build\s*=\s*//')
printf $"Diffs between CSS %s and %s versions:\n" $cur_ver $next_ver
printf $"Diffs between %s and %s versions:\n" $cur_ver $next_ver
find $path_work/$name_upgrading/rootfs$num_cur/var/db/pkg/ -type d | sed 's/.*db\/pkg\///' | grep \/ | sort > $lock/cur
find $path_lxc_prepare/var/db/pkg/ -type d | sed 's/.*db\/pkg\///' | grep \/ | sort > $lock/new
cp $lock/new $lock/work
@ -775,15 +891,15 @@ clear_cache(){
}
# Проверка одновременного запуска
check_simultaneous_run
# Обработка параметров вызова скрипта
save=$IFS
IFS=$' =\n'
get_args $@
IFS=$save
# Проверка одновременного запуска
check_simultaneous_run
# Установка значений переменных
set_vars
@ -801,7 +917,7 @@ then
fi
# Создание базового контейнера
if [[ $create_ == 1 || $prepare_ == 1 ]] && [ ! -d "$path_cache/$lxc_distro " ]
if [[ $create_ == 1 || $prepare_ == 1 ]] && [ ! -d "$path_cache/scratch " ]
then
create_base
fi
@ -810,6 +926,13 @@ fi
if [[ $create_ == 1 || $prepare_ == 1 ]]
then
create_lxc
# если задан профиль при создании контейнера:
# запустим контейнер, обновим оверлеи (container), выберем профиль и обновим пакеты
if [[ $prepare_ == 0 && $lxc_profile != 'scratch' ]]
then
change_profile
fi
fi
# Обновление пакетов контейнера