[make-initrd] [PATCH v6 16/22] bootchain-core: new logic of the daemon main loop

Alexey Gladkov gladkov.alexey at gmail.com
Tue Oct 26 22:21:47 MSK 2021


On Sun, Oct 24, 2021 at 08:22:31PM +0300, Leonid Krivoshein wrote:
> - Adds the ability to overload the boot chain new steps;
> - Limits the number of repeated runs of steps-scripts to five;
> - Adds a switch for allow/disallow to retry steps-scripts;
> - Introduces the difference between the modes "NATIVE"
>   and "COMPATIBILITY" with the pipeline;
> - Offers a new way of ending the daemon main loop;
> - Saves the names of the steps taken.
> 
> See README.md for more details.
> 
> Signed-off-by: Leonid Krivoshein <klark.devel at gmail.com>
> ---
>  features/bootchain-core/README.md             | 62 +++++++++++++
>  .../data/bin/bootchain-sh-functions           |  2 +
>  features/bootchain-core/data/sbin/chaind      | 91 ++++++++++++++-----
>  3 files changed, 131 insertions(+), 24 deletions(-)
> 
> diff --git a/features/bootchain-core/README.md b/features/bootchain-core/README.md
> index db73c0a..bde5c9b 100644
> --- a/features/bootchain-core/README.md
> +++ b/features/bootchain-core/README.md
> @@ -54,6 +54,11 @@ us to optimize fill in `initramfs` only which we are need.
>    Such pseudo-steps allow you to control, basically, the internal state of the
>    daemon and should not be taken into account in the boot chain, as if they are
>    hidden.
> +- The `chaind` daemon allows you to overload the chain with a new set of steps,
> +  thanks to this, you can change the logic of work "on the fly", support loops
> +  and conditional jumps, in text dialogs it is an opportunity to go back.
> +- Keeps records of the steps taken at least once and allows you to prevent their
> +  re-launch.
>  - `bootchain-sh-functions` extends the API of the original `pipeline-sh-functions`,
>    see the details in the corresponding section.
>  - Via resolve_target() supports not only forward, but also reverse addressing,
> @@ -68,6 +73,11 @@ us to optimize fill in `initramfs` only which we are need.
>    of the previous step through symbolic links to mount points inside initramfs,
>    outside the tree the results of the steps, which provides, if necessary, the
>    overlap mounting mechanism inherent in the program `propagator`.
> +- Along with the NATIVE mode of operation, the `chaind` daemon can work in
> +  COMPATIBILITY WITH `pipeline`. In the NATIVE mode of operation, the daemon
> +  imposes another an approach to processing the status code of the completed
> +  step and the method of premature completion of the boot chain, see the details
> +  in the corresponding section.
>  - The daemon can be configured when building initramfs via the included file
>    configurations of `/etc/sysconfig/bootchain`, and not only through boot
>    parameters, see the details in the corresponding section.
> @@ -81,6 +91,50 @@ Despite the differences, `chaind` is backward compatible with previously
>  written steps for the `pipelined` daemon and does not require changes for
>  configurations with `root=pipeline`.
>  
> +## Features of the pipelined work
> +
> +If the step-script will be finished with code of status 2, the original daemon
> +`pipelined` will understand it like a must to stop chains and finish work.
> +(meaning that system is ready to go stage2). If the step-script does not
> +process this code from an external command, and stage2 is not ready to work
> +yet, a situation with premature termination of the daemon will arise.
> +
> +If the step-script will be finished with non-null code of status (different
> +from 2), daemon `pipelined` will understand it like a fail and will repeat this
> +failure-step with pause in one second in infinity cycle (until common timeout
> +rootdelay=180). But, sometimes repeat steps are unnecessary because the
> +situation is incorrigible and repeating will just waste of time and make a
> +system log is filling up. But the daemon `pipelined` don't know how to work
> +with this situations.
> +
> +## New approach in chaind daemon
> +
> +For steps-scripts are suggested before finish work with code of status 0 call
> +break_bc_loop() for tell to the daemon about ready stage2 and needed finish
> +work this daemon after the current step.In case of a failure in the step-by-step
> +scenario, the daemon can repeat it, but no more than four times with a pause of
> +two seconds. In order for a failure in the step-by-step scenario to lead to an
> +immediate shutdown of the daemon, it is necessary to use the internal step
> +`noretry`.
> +
> +## Daemon operation mode
> +
> +### NATIVE mode of operation
> +
> +NATIVE mode is activated by the `root=bootchain` parameter. In this mode, the
> +daemon will perceive the status code 2 from the step script in the same way as
> +any other non-zero code and then act according to the internal state: if
> +repetitions are allowed, the step script will be called again with a pause
> +of 2 seconds, but no more than four times. If repetitions are prohibited,
> +the daemon itself will immediately terminate.
> +
> +### Pipeline COMPATIBILITY mode
> +
> +Compatibility mode is activated by the `root=pipeline` parameter. In this mode,
> +the daemon behaves the same as the original `pipelined`, except that it limits
> +the number of re-runs of the failed step. He perceives the status code 2 not as
> +a failure, but as a command to end the main daemon cycle.
> +
>  ## Configuration
>  
>  The configuration is defined in the file `/etc/sysconfig/bootchain` when
> @@ -109,6 +163,14 @@ addressing, as if they are hidden.
>    on the <OUT> of the previous step from the <IN> of the next step, which can
>    be useful, for example, when we don`t want the results of the `waitdev` step
>    to be used in the next step, `localdev`, which primarily looks at them.
> +- `noretry` - prohibits the following steps from ending with a non-zero return
> +  code, what will lead to the immediate shutdown of the daemon in case of a
> +  script failure any next step. By default, the steps are allowed to fail,
> +  the daemon will try to restart them again four times with a pause of two
> +  seconds.
> +- `retry` - allows all subsequent steps to be completed with a non-zero return
> +  code, which will lead to their starting five times, in total. This mode of
> +  operation of the daemon operates by default.
>  
>  ## External elements of the bootchain (steps-scripts)
>  
> diff --git a/features/bootchain-core/data/bin/bootchain-sh-functions b/features/bootchain-core/data/bin/bootchain-sh-functions
> index d1d0cef..8c5a2f2 100644
> --- a/features/bootchain-core/data/bin/bootchain-sh-functions
> +++ b/features/bootchain-core/data/bin/bootchain-sh-functions
> @@ -17,9 +17,11 @@ message_time=1
>  if [ "${ROOT-}" = pipeline ]; then
>  	BC_LOGFILE="${BC_LOGFILE:-/var/log/pipelined.log}"
>  	mntdir="${mntdir:-/dev/pipeline}"
> +	pipeline_mode=1
>  else
>  	BC_LOGFILE="${BC_LOGFILE:-/var/log/chaind.log}"
>  	mntdir="${mntdir:-/dev/bootchain}"
> +	pipeline_mode=
>  fi
>  
>  BC_NEXTCHAIN=/.initrd/bootchain/bootchain.next
> diff --git a/features/bootchain-core/data/sbin/chaind b/features/bootchain-core/data/sbin/chaind
> index 5623a37..4c9ebaa 100755
> --- a/features/bootchain-core/data/sbin/chaind
> +++ b/features/bootchain-core/data/sbin/chaind
> @@ -2,7 +2,11 @@
>  
>  . bootchain-sh-functions
>  
> +bcretry=1
>  pidfile="/var/run/$PROG.pid"
> +chainsteps="$BOOTCHAIN"
> +stepnum=0
> +prevdir=
>  
>  
>  exit_handler()
> @@ -39,11 +43,7 @@ run mkdir -p -- "$mntdir" "$BC_PASSED"
>  mountpoint -q -- "$mntdir" ||
>  	run mount -t tmpfs tmpfs "$mntdir" ||:
>  
> -stepnum=0
> -chainsteps="$BOOTCHAIN"
> -datadir=
> -destdir=
> -
> +rc=0
>  while [ -n "$chainsteps" ]; do
>  	name="${chainsteps%%,*}"
>  	exe="$handlerdir/$name"
> @@ -54,53 +54,96 @@ while [ -n "$chainsteps" ]; do
>  		prevdir=
>  		message "[0] Step '$name' has been passed"
>  
> +	elif [ "$name" = retry ]; then
> +		chainsteps="${chainsteps#$name}"
> +		chainsteps="${chainsteps#,}"
> +		bcretry=1
> +		message "subsequent steps will restart after failure"
> +
> +	elif [ "$name" = noretry ]; then
> +		chainsteps="${chainsteps#$name}"
> +		chainsteps="${chainsteps#,}"
> +		bcretry=0
> +		message "daemon will be stopped immediately after any step failure"
> +
>  	elif [ -x "$exe" ]; then
>  		assign "callnum" "\${callnum_$name:-0}"
>  		datadir="$mntdir/src/step$stepnum"
>  		destdir="$mntdir/dst/step$stepnum"
>  
> -		[ "$stepnum" != 0 ] ||
> -			prevdir=""
> -
>  		run mkdir -p -- "$datadir" "$destdir"
>  
> -		if ! mountpoint -q "$destdir"; then
> +		if mountpoint -q -- "$destdir" ||
> +			[ -s "$destdir/DEVNAME" ] ||
> +			[ -b "$destdir/dev" ] ||
> +			[ -c "$destdir/dev" ]
> +		then
> +			message "[$callnum] Handler: $exe skipped"
> +		else
>  			message "[$callnum] Handler: $exe"
>  
>  			export name callnum datadir destdir prevdir
>  
> +			for try in 1 2 3 4 5; do
>  				[ -z "$BC_DEBUG" ] ||
>  					run "$handlerdir/debug" ||:
>  				rc=0
>  				run "$exe" ||
>  					rc=$?
> -
> -			if [ "$rc" != 0 ]; then
> -				[ "$rc" != 2 ] ||
> +				[ "$rc" != 0 ] ||
>  					break
> -				message "[$callnum] Handler failed (rc=$rc)"
> -				sleep 1
> -				continue
> -			fi
> -		else
> -			message "[$callnum] Handler: $exe skipped"
> +				[ "$rc" != 2 ] || [ -z "$pipeline_mode" ] ||
> +					break 2
> +				message "[$callnum] Handler failed (rc=$rc, try=$try)"
> +				[ ! -f "$BC_PASSED/$PROG" ] ||
> +					break 2
> +				[ "$bcretry" != 0 ] ||
> +					break
> +				sleep 2
> +			done
> +
> +			[ -r "$BC_NEXTCHAIN" ] ||
> +				run touch "$BC_PASSED/$name"
> +			[ ! -f "$BC_PASSED/$PROG" ] ||
> +				break
> +			[ "$rc" = 0 ] ||
> +				break
>  		fi
>  
> -		prevdir="$destdir"
> +		if [ ! -r "$BC_NEXTCHAIN" ]; then
> +			callnum=$((1 + $callnum))
> +			assign "callnum_$name" "\$callnum"
> +			eval "export callnum_$name"
> +		fi
>  
> -		callnum=$(($callnum + 1))
> -		eval "callnum_$name=\"\$callnum\""
> +		stepnum=$((1 + $stepnum))
> +		prevdir="$(readlink-e "$destdir" 2>/dev/null ||:)"
>  	fi
>  
> -	chainsteps="${chainsteps#$name}"
> -	chainsteps="${chainsteps#,}"
> +	if [ ! -r "$BC_NEXTCHAIN" ]; then
> +		chainsteps="${chainsteps#$name}"
> +		chainsteps="${chainsteps#,}"
> +	else
> +		debug "chain will be reloaded by $BC_NEXTCHAIN:"
> +		fdump "$BC_NEXTCHAIN"
> +		. "$BC_NEXTCHAIN"
> +		run rm -f -- "$BC_NEXTCHAIN"

Я специально дочитал до конца патчсета, но так и не понял кто и где
будет формировать BC_NEXTCHAIN ?

И как это будет работать с waitdev так как BC_NEXTCHAIN проверяется после
каждого шага ?

Получается BC_NEXTCHAIN может сформировать только следующий после waitdev
шаг.

> +	fi
>  
> -	stepnum=$(($stepnum + 1))
> +	debug "remaining steps: $chainsteps"
>  done
>  
>  [ -z "$chainsteps" ] ||
>  	message "remaining steps after breaking loop: $chainsteps"
>  
> +if [ "$rc" = 2 ] && [ -n "$pipeline_mode" ]; then
> +	debug "finishing in pipeline mode"
> +elif [ "$rc" = 0 ] && [ -f "$BC_PASSED/$PROG" ]; then
> +	debug "finishing in bootchain mode"
> +else
> +	fatal "daemon terminated incorrectly (rc=$rc)"
> +fi
> +
>  if [ -z "$BC_DEBUG" ]; then
>  	grep -qs " $mntdir/" /proc/mounts ||
>  		run umount -- "$mntdir" &&
> -- 
> 2.24.1
> 
> _______________________________________________
> Make-initrd mailing list
> Make-initrd at lists.altlinux.org
> https://lists.altlinux.org/mailman/listinfo/make-initrd
> 

-- 
Rgrds, legion



More information about the Make-initrd mailing list