diff --git a/cl-lxc b/cl-lxc index 2a13436..2e4c532 100755 --- a/cl-lxc +++ b/cl-lxc @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # Copyright 2022 Mir Calculate. http://www.calculate-linux.org # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -128,7 +128,7 @@ get_args(){ elif (( $# == 1 )) then lxc_=$1 - if [[ $lxc_ =~ [^A-Za-z0-9_\.] ]] + if [[ $lxc_ =~ [^A-Za-z0-9_\._\-] ]] then echo $"Container name contains wrong characters." >&2 exit 1 @@ -146,6 +146,7 @@ print_distro(){ then echo $"Distributive: [CCS] Calculate Container Scratch (by default) + [CDC] Calculate Directory Container [CCG] Calculate Container Games" return fi @@ -154,6 +155,9 @@ print_distro(){ CCS) echo "Calculate Container Scratch" ;; + CDC) + echo "Calculate Directory Container" + ;; CCG) echo "Calculate Container Games" ;; @@ -163,7 +167,10 @@ print_distro(){ set_vars(){ lxc_release=22.0.1 net_domain=$(hostname -f) - path_def=$(lxc-config lxc.lxcpath) + path_def=$(lxc-config lxc.lxcpath 2>/dev/null) || ( + printf $"To run the script, install the '%s' package.\n" app-containers/lxc >&2 + exit 1 + ) if ! [[ $prepare_ == 1 || $upgrade_ == 1 ]] then @@ -206,8 +213,17 @@ set_vars(){ if [ $path_def = "$path_work" ] then path_change= + if [ ! -d $path_work ] + then + mkdir -p $path_work + fi else path_change=$path_work + if [ ! -d $path_work ] + then + printf $"Directory '%s' is not found.\n" $path_work >&2 + exit 1 + fi fi type_fs=$(df -Th $path_work | awk 'NR==2 {print $2}') @@ -227,6 +243,9 @@ set_vars(){ CCS|ccs) lxc_distro=CCS ;; + CDC|cdc) + lxc_distro=CDC + ;; CCG|ccg) lxc_distro=CCG ;; @@ -250,25 +269,25 @@ set_vars(){ debug_vars(){ local log=/var/log/calculate/cl-lxc.log - cat > /var/log/calculate/cl-lxc.log < /var/log/calculate/cl-lxc.log <<-EOF + lxc_release = $lxc_release + net_domain = $net_domain + path_def = $path_def + name_lxc = $name_lxc + name_upgrading = $name_upgrading + name_rootfs = $name_rootfs + status_lxc = $status_lxc + path_work = $path_work + path_lxc = $path_lxc + path_cache = $path_cache + path_lxc_prepare = $path_lxc_prepare + path_change = $path_change + type_fs = $type_fs + num_cur = $num_cur + num_next = $num_next + lxc_distro = $lxc_distro + + EOF } check_vars(){ @@ -349,15 +368,8 @@ create_base() { mkdir $path_cache fi fi - - # Удалим кэш LXC - if [ $clear_ == 1 ] - then - rm -rf /var/cache/lxc/download/$lxc_distro - fi - lxc-create -n $lxc_distro -t download -- --server $mirror_ \ - --no-validate --arch x86_64 --dist $lxc_distro --release $lxc_release &>/dev/null || { + --arch x86_64 --dist $lxc_distro --release $lxc_release &>/dev/null || { eend $? || true eerror $"Failed to run lxc-create" >&2 rm -rf $path_cache @@ -400,13 +412,23 @@ create_lxc() { fi ebegin $"Preparing base mount paths" - rm -rf $path_lxc/rootfs/usr/portage; mkdir $path_lxc/rootfs/usr/portage - rm -rf $path_lxc/rootfs/var/db/repos/calculate; mkdir $path_lxc/rootfs/var/db/repos/calculate - rm -rf $path_lxc/rootfs/var/cache/edb/binhost; mkdir $path_lxc/rootfs/var/cache/edb/binhost - rm -rf $path_lxc/rootfs/var/calculate/packages; mkdir $path_lxc/rootfs/var/calculate/packages - rm -rf $path_lxc/rootfs/var/calculate/distfiles;mkdir $path_lxc/rootfs/var/calculate/distfiles + for path_res in usr/portage \ + var/cache/edb/binhost \ + var/calculate/distfiles \ + var/calculate/packages \ + var/db/repos/calculate \ + var/db/repos/gentoo + do + path_res=${path_lxc}/rootfs/${path_res} + if [ -e $path_res ] + then + rm -rf $path_res + mkdir $path_res + fi + done eend + local calculate_mount= calculate_dir= if [ $prepare_ == 0 ] then ebegin $"Moving /var/calculate to a separate mount point" @@ -417,20 +439,43 @@ create_lxc() { calculate_dir="${path_lxc}/calculate" eend else - calculate_mount="" calculate_dir="${path_lxc}/rootfs/var/calculate" fi - local container_mount="" - if ! [ -d /var/db/repos/container ] + local portage_mount= gentoo_from= gentoo_to= + if [ -d /var/db/repos/gentoo ] then - ewarn $"Skipping mounting Container overlay" - container_mount="#lxc.mount.entry = /var/db/repos/container var/db/repos/container none ro,bind 0 0 -" + gentoo_from='/var/db/repos/gentoo' else - rm -rf $path_lxc/rootfs/var/db/repos/container; mkdir $path_lxc/rootfs/var/db/repos/container - container_mount="lxc.mount.entry = /var/db/repos/container var/db/repos/container none ro,bind 0 0 -" + gentoo_from='/usr/portage' + fi + if [ -d $path_lxc/rootfs/var/db/repos/gentoo ] + then + gentoo_to='var/db/repos/gentoo' + else + gentoo_to='usr/portage' + fi + portage_mount="lxc.mount.entry = ${gentoo_from} ${gentoo_to} none ro,bind 0 0" + + if [ ! -e /var/db/repos/container ] + then + mv $path_lxc/rootfs/var/db/repos/container /var/db/repos + mkdir $path_lxc/rootfs/var/db/repos/container + + if grep -q github.com $path_lxc/rootfs/etc/portage/repos.conf/zz-calculate.conf + then + local repo_container='https://github.com/calculatelinux/container' + else + local repo_container='https://git.calculate-linux.org/calculate/container-overlay' + fi + cat <<- EOF > /etc/portage/repos.conf/cl-lxc.conf + [container] + priority = 50 + sync-uri = $repo_container + location = /var/db/repos/container + auto-sync = Yes + sync-type = git + EOF fi ebegin $"Running container setup" @@ -440,65 +485,76 @@ 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 else net_conf=veth - local random_mac=$(echo -n '02:'; hexdump -n5 -e '/1 ":%02X"' /dev/random | sed s/^://g) - network_conf="lxc.net.0.type = veth -lxc.net.0.flags = up -lxc.net.0.name = eth0 -lxc.net.0.link = br0 -lxc.net.0.hwaddr = ${random_mac} -lxc.net.0.veth.pair = lxc-${name_lxc}" + local random_mac=$(printf '06:%02X:%02X:%02X:%02X:%02X\n' \ + $[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 + # исключим настройку сетевого имени, если такое уже используется + veth_pair="#${veth_pair}" + fi + network_conf=$(cat <<- EOF + lxc.net.0.type = veth + lxc.net.0.flags = up + lxc.net.0.name = eth0 + lxc.net.0.link = br0 + lxc.net.0.hwaddr = ${random_mac} + ${veth_pair} + EOF + ) fi # перенесем базовый 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 - cat << EOL >> ${path_lxc}/config -${network_conf} - -${calculate_mount}lxc.mount.entry = /usr/portage usr/portage none ro,bind 0 0 -lxc.mount.entry = /var/db/repos/calculate var/db/repos/calculate none ro,bind 0 0 -${container_mount}lxc.mount.entry = /var/cache/edb/binhost var/cache/edb/binhost none ro,bind 0 0 -lxc.mount.entry = /var/calculate/packages var/calculate/packages none rw,bind 0 0 -lxc.mount.entry = /var/calculate/distfiles var/calculate/distfiles none rw,bind 0 0 -EOL + cat <<- EOF >> ${path_lxc}/config + ${network_conf} + ${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 + lxc.mount.entry = /var/cache/edb/binhost var/cache/edb/binhost none ro,bind 0 0 + lxc.mount.entry = /var/calculate/packages var/calculate/packages none rw,bind 0 0 + lxc.mount.entry = /var/calculate/distfiles var/calculate/distfiles none rw,bind 0 0 + EOF eend ebegin $"Configuring utility variables" - cat << EOL > ${calculate_dir}/calculate.env -[install] -os_install_net_hostname = ${name_lxc} -os_install_net_domain = ${net_domain} -os_install_locale_lang = ${LANG/.utf8/} -os_install_clock_timezone = $(cat /etc/timezone) - -[update] -cl_update_rep_name = -cl_update_rep_url = -cl_update_rep_sync = -cl_update_eixupdate_force = force -cl_update_force_fix_set = on -EOL + 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 = + cl_update_eixupdate_force = force + cl_update_force_fix_set = on + EOF eend ebegin $"Creating templates" mkdir -p ${calculate_dir}/templates/default - cat << EOL > ${calculate_dir}/templates/default/.calculate_directory -# Calculate env=install ac_install_live==on append=skip -EOL + cat <<- EOF > ${calculate_dir}/templates/default/.calculate_directory + # Calculate env=install ac_install_live==on append=skip + EOF if [ $net_conf == veth ] then - cat << EOL > ${calculate_dir}/templates/default/runlevel.eth0 -# Calculate mergepkg(sys-apps/openrc)!= path=/etc/runlevels/default name=net.eth0 protected link=/etc/init.d/net.lo symbolic -EOL + cat <<- EOF > ${calculate_dir}/templates/default/runlevel.eth0 + # Calculate mergepkg(sys-apps/openrc)!= path=/etc/runlevels/default name=net.eth0 protected link=/etc/init.d/net.lo symbolic + EOF fi - cat << EOL > ${calculate_dir}/templates/default/portage.binhost -# Calculate mergepkg(sys-apps/portage)!= path=/etc/portage/make.conf name=binhost protected comment=# -$(emerge --info | grep PORTAGE_BINHOST) -EOL + cat <<- EOF > ${calculate_dir}/templates/default/portage.binhost + # Calculate mergepkg(sys-apps/portage)!= path=/etc/portage/make.conf name=binhost protected comment=# + $(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 @@ -508,21 +564,23 @@ update_prepare() { printf $"Package update for container %s\n" $name_lxc ebegin $"Moving installed packages, flags and masks from main container" - cp $path_work/$name_upgrading/rootfs$num_cur/etc/portage/sets/custom $path_lxc/rootfs/etc/portage/sets/custom &>/dev/null || true - cp $path_work/$name_upgrading/rootfs$num_cur/etc/portage/package.accept_keywords/custom \ - $path_lxc/rootfs/etc/portage/package.accept_keywords/custom &>/dev/null || true - cp $path_work/$name_upgrading/rootfs$num_cur/etc/portage/package.use/custom \ - $path_lxc/rootfs/etc/portage/package.use/custom &>/dev/null || true - cp $path_work/$name_upgrading/rootfs$num_cur/etc/portage/package.mask/custom \ - $path_lxc/rootfs/etc/portage/package.mask/custom &>/dev/null || true - cp $path_work/$name_upgrading/rootfs$num_cur/etc/portage/package.unmask/custom \ - $path_lxc/rootfs/etc/portage/package.unmask/custom &>/dev/null || true + for migrate_file in /etc/portage/package.accept_keywords/custom \ + /etc/portage/package.mask/custom \ + /etc/portage/package.unmask/custom \ + /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 + done eend ebegin $"Creating mount points" - for mount_point in $(grep lxc.mount.entry $path_work/$name_upgrading/config | awk {'print $4'}) + for mount_point in $(grep '^lxc.mount.entry' $path_work/$name_upgrading/config | awk {'print $4'}) do - mkdir -p "$path_lxc/rootfs/$mount_point" + if [ ! -e "$path_lxc/rootfs/$mount_point" ] + then + mkdir -p "$path_lxc/rootfs/$mount_point" + fi done eend @@ -538,6 +596,11 @@ update_prepare() { cl-update -s einfo $"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 {} \; + cd $path_lxc/rootfs/etc/runlevels/boot + ln -s /etc/init.d/calculate . + cd - &>/dev/null ebegin $"Stopping container" lxc-stop $name_lxc @@ -554,7 +617,7 @@ update_prepare() { ebegin $"Removing temporary container directory $name_lxc" if [ $type_fs = 'btrfs' ] then - btrfs subvolume delete $path_lxc >&/dev/null + btrfs subvolume delete $path_lxc &>/dev/null if [ -n "$path_change" ] then rm $path_def/$name_lxc # удалим символическую ссылку @@ -581,6 +644,7 @@ upgrade_lxc() { reflink='--reflink' fi cp -a $reflink $path_lxc_prepare $path_work/$name_upgrading/rootfs$num_next + rm -rf $path_work/$name_upgrading/rootfs$num_next/var/calculate/* eend ebegin $"Copying network settings from main container" @@ -588,12 +652,22 @@ upgrade_lxc() { $path_work/$name_upgrading/rootfs$num_next/etc/conf.d/net eend + ebegin $"Copying hash of root password" + root=$(grep '^root:' $path_work/$name_upgrading/rootfs$num_cur/etc/shadow | sed 's/:/\\:/g') + sed -i "s:^root\:.*$:$root:" $path_work/$name_upgrading/rootfs$num_next/etc/shadow + 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 + eend + ebegin $"Preparing first boot setup script" -cat << EOL > $path_work/$name_upgrading/rootfs$num_next/etc/local.d/firststart.start -cl-core --method setup_system --no-progress --usenew-conf --network on -openrc -#rm /etc/local.d/firststart.start -EOL + cat <<- EOF > $path_work/$name_upgrading/rootfs$num_next/etc/local.d/firststart.start + cl-core --method setup_system --no-progress --usenew-conf --network on + openrc + rm /etc/local.d/firststart.start + EOF chmod 755 $path_work/$name_upgrading/rootfs$num_next/etc/local.d/firststart.start eend @@ -661,6 +735,45 @@ diff_pkg() { true } +clear_cache(){ + ebegin $"Clearing cache" + rm -rf /var/cache/lxc/download/* + + if [[ -e /var/calculate/lxc/.cache ]] + then + if [[ $(df -Th /var/calculate/lxc | awk 'NR==2 {print $2}') == btrfs ]] + then + btrfs subvolume delete /var/calculate/lxc/.cache > /dev/null + else + rm -rf /var/calculate/lxc/.cache + fi + fi + + for i in /var/calculate/lxc/* + do + if [[ $i == /var/calulate/lxc/* ]] + then + break + fi + # разыменуем символические ссылки чтобы почистить кэши на других разделах + if [[ -L $i ]] + then + cache_dir=$(realpath $i) + cache_dir=${cache_dir%/*} + if [[ -e $cache_dir/.cache ]] + then + if [[ $(df -Th $cache_dir | awk 'NR==2 {print $2}') == btrfs ]] + then + btrfs subvolume delete $cache_dir/.cache > /dev/null + else + rm -rf $cache_dir/.cache + fi + fi + fi + done + eend +} + # Проверка одновременного запуска check_simultaneous_run @@ -680,18 +793,15 @@ debug_vars # Проверка параметров запуска check_vars -# Чистка кэша базового контейнера +# Чистка кэша # пустой файл partial когда lxc-create был прерван -if [[ $clear_ == 1 && -d "$path_cache/$lxc_distro" ]] +if [[ $clear_ == 1 ]] then - ebegin $"Clearing Calculate Container cache" - rm -rf "$path_cache/$lxc_distro" - eend + clear_cache fi # Создание базового контейнера -if [[ $create_ == 1 || $prepare_ == 1 || $clear_ == 1 ]] && - [ ! -d "$path_cache/$lxc_distro" ] +if [[ $create_ == 1 || $prepare_ == 1 ]] && [ ! -d "$path_cache/$lxc_distro" ] then create_base fi @@ -699,15 +809,6 @@ fi # Создание контейнера if [[ $create_ == 1 || $prepare_ == 1 ]] then - if [ -d "$path_lxc_prepare" ] - then - if [ $clear_ == 1 ] - then - ebegin $"Clearing container cache" - rm -r "$path_lxc_prepare" - eend - fi - fi create_lxc fi