Add grubby-bls package

Add a grubby wrapper script that allows to manage BootLoaderSpec files by
using the same command line options supported by the grubby tool. This is
provided for backward compatibility for grubby users that swtich to BLS.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
This commit is contained in:
Javier Martinez Canillas 2018-06-18 11:14:35 +02:00
parent 83d4145e20
commit 504ff4446b
No known key found for this signature in database
GPG Key ID: C751E590D63F3D69
2 changed files with 636 additions and 8 deletions

616
grubby-bls Executable file
View File

@ -0,0 +1,616 @@
#!/bin/bash
#
# grubby wrapper to manage BootLoaderSpec files
#
#
# Copyright 2018 Red Hat, Inc. All rights reserved.
#
# 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, see <http://www.gnu.org/licenses/>.
readonly SCRIPTNAME="${0##*/}"
CMDLINE_LINUX_DEBUG=" systemd.log_level=debug systemd.log_target=kmsg"
LINUX_DEBUG_VERSION_POSTFIX="_with_debugging"
LINUX_DEBUG_TITLE_POSTFIX=" with debugging"
declare -a bls_file
declare -a bls_title
declare -a bls_version
declare -a bls_linux
declare -a bls_initrd
declare -a bls_options
declare -a bls_id
[[ -f /etc/sysconfig/kernel ]] && . /etc/sysconfig/kernel
[[ -f /etc/os-release ]] && . /etc/os-release
read MACHINE_ID < /etc/machine-id
arch=$(uname -m)
if [[ $arch = 's390' || $arch = 's390x' ]]; then
bootloader="zipl"
else
bootloader="grub2"
fi
print_error() {
echo "$1" >&2
exit 1
}
if [[ ${#} = 0 ]]; then
print_error "no action specified"
fi
get_bls_value() {
local bls="$1" && shift
local key="$1" && shift
echo "$(grep "^${key}[ \t]" "${bls}" | sed -e "s,^${key}[ \t]*,,")"
}
set_bls_value() {
local bls="$1" && shift
local key="$1" && shift
local value="$1" && shift
sed -i -e "s,^${key}.*,${key} ${value}," "${bls}"
}
append_bls_value() {
local bls="$1" && shift
local key="$1" && shift
local value="$1" && shift
old_value="$(get_bls_value ${bls} ${key})"
set_bls_value "${bls}" "${key}" "${old_value}${value}"
}
get_bls_values() {
count=0
for bls in $(ls -vr ${blsdir}/*.conf 2> /dev/null); do
bls_file[$count]="${bls}"
bls_title[$count]="$(get_bls_value ${bls} title)"
bls_version[$count]="$(get_bls_value ${bls} version)"
bls_linux[$count]="$(get_bls_value ${bls} linux)"
bls_initrd[$count]="$(get_bls_value ${bls} initrd)"
bls_options[$count]="$(get_bls_value ${bls} options)"
bls_id[$count]="$(get_bls_value ${bls} id)"
count=$((count+1))
done
}
get_default_index() {
local default=""
local index="-1"
local title=""
local version=""
if [[ $bootloader = "grub2" ]]; then
default="$(grep '^saved_entry=' ${env} | sed -e 's/^saved_entry=//')"
else
default="$(grep '^default=' ${zipl_config} | sed -e 's/^default=//')"
fi
if [[ -z $default ]]; then
index=0
elif [[ $default =~ ^[0-9]+$ ]]; then
index="$default"
fi
# GRUB2 and zipl use different fields to set the default entry
if [[ $bootloader = "grub2" ]]; then
title="$default"
else
version="$default"
fi
for i in ${!bls_file[@]}; do
if [[ $title = ${bls_title[$i]} || $version = ${bls_version[$i]} ||
$i -eq $index ]]; then
echo $i
return
fi
done
}
display_default_value() {
case "$display_default" in
kernel)
echo "${bls_linux[$default_index]}"
exit 0
;;
index)
echo "$default_index"
exit 0
;;
title)
echo "${bls_title[$default_index]}"
exit 0
;;
esac
}
param_to_indexes() {
local param="$1"
local indexes=""
if [[ $param = "ALL" ]]; then
for i in ${!bls_file[@]}; do
indexes="$indexes $i"
done
echo -n $indexes
return
fi
if [[ $param = "DEFAULT" ]]; then
echo -n $default_index
return
fi
for i in ${!bls_file[@]}; do
if [[ $param = "${bls_linux[$i]}" ]]; then
indexes="$indexes $i"
fi
if [[ $param = "TITLE=${bls_title[$i]}" ]]; then
indexes="$indexes $i"
fi
if [[ $param = $i ]]; then
indexes="$indexes $i"
fi
done
if [[ -n $indexes ]]; then
echo -n $indexes
return
fi
echo -n "-1"
}
display_info_values() {
local indexes=($(param_to_indexes "$1"))
for i in ${indexes[*]}; do
echo "index=$i"
echo "kernel=${bls_linux[$i]}"
echo "args=\"${bls_options[$i]}\""
echo "initrd=${bls_initrd[$i]}"
echo "title=${bls_title[$i]}"
done
exit 0
}
mkbls() {
local kernel=$1 && shift
local kernelver=$1 && shift
local datetime=$1 && shift
local debugname=""
local flavor=""
if [[ $kernelver == *\+* ]] ; then
local flavor=-"${kernelver##*+}"
if [[ $flavor == "-debug" ]]; then
local debugname="with debugging"
local debugid="-debug"
fi
fi
cat <<EOF
title ${NAME} (${kernelver}) ${VERSION}${debugname}
version ${kernelver}${debugid}
linux ${kernel}
initrd /initramfs-${kernelver}.img
options \$kernelopts
id ${ID}-${datetime}-${kernelver}${debugid}
grub_users \$grub_users
grub_arg --unrestricted
grub_class kernel${flavor}
EOF
}
remove_bls_fragment() {
local indexes=($(param_to_indexes "$1"))
if [[ $indexes = "-1" ]]; then
print_error "The param $1 is incorrect"
fi
for i in ${indexes[*]}; do
rm -f "${bls_file[$i]}"
done
get_bls_values
}
add_bls_fragment() {
local kernel="$1" && shift
local title="$1" && shift
local options="$1" && shift
local initrd="$1" && shift
local extra_initrd="$1" && shift
if [[ $kernel = *"vmlinuz-"* ]]; then
kernelver="${kernel##*/vmlinuz-}"
else
kernelver="${kernel##*/}"
fi
if [[ ! -d "/lib/modules/${kernelver}" || ! -f "/boot/vmlinuz-${kernelver}" ]] &&
[[ $bad_image != "true" ]]; then
print_error "The ${kernelver} kernel isn't installed in the machine"
fi
if [[ -z $title ]]; then
print_error "The kernel title must be specified"
fi
if [[ ! -d $blsdir ]]; then
install -m 700 -d "${blsdir}"
fi
bls_target="${blsdir}/${MACHINE_ID}-${kernelver}.conf"
kernel_dir="/lib/modules/${kernelver}"
if [[ -f "${kernel_dir}/bls.conf" ]]; then
cp -aT "${kernel_dir}/bls.conf" "${bls_target}" || exit $?
else
if [[ -d $kernel_dir ]]; then
datetime="$(date -u +%Y%m%d%H%M%S -d "$(stat -c '%y' "${kernel_dir}")")"
else
datetime=0
fi
mkbls "${kernel}" "${kernelver}" "${datetime}" > "${bls_target}"
fi
if [[ -n $title ]]; then
set_bls_value "${bls_target}" "title" "${title}"
fi
if [[ -n $options ]]; then
set_bls_value "${bls_target}" "options" "${options}"
fi
if [[ -n $initrd ]]; then
set_bls_value "${bls_target}" "initrd" "${initrd}"
fi
if [[ -n $extra_initrd ]]; then
append_bls_value "${bls_target}" "initrd" "${extra_initrd}"
fi
if [[ $MAKEDEBUG = "yes" ]]; then
arch="$(uname -m)"
bls_debug="$(echo ${bls_target} | sed -e "s/\.${arch}/-debug.${arch}/")"
cp -aT "${bls_target}" "${bls_debug}"
append_bls_value "${bls_debug}" "title" "${LINUX_DEBUG_TITLE_POSTFIX}"
append_bls_value "${bls_debug}" "version" "${LINUX_DEBUG_VERSION_POSTFIX}"
append_bls_value "${bls_debug}" "options" "${CMDLINE_LINUX_DEBUG}"
blsid="$(get_bls_value ${bls_debug} "id" | sed -e "s/\.${arch}/-debug.${arch}/")"
set_bls_value "${bls_debug}" "id" "${blsid}"
fi
get_bls_values
if [[ $make_default = "true" ]]; then
set_default_bls "TITLE=${title}"
fi
exit 0
}
update_args() {
local args=$1 && shift
local remove_args=($1) && shift
local add_args=($1) && shift
for arg in ${remove_args[*]}; do
args="$(echo $args | sed -e "s,$arg[^ ]*,,")"
done
for arg in ${add_args[*]}; do
if [[ $arg = *"="* ]]; then
value=${arg##*=}
key=${arg%%=$value}
exist=$(echo $args | grep "${key}=")
if [[ -n $exist ]]; then
args="$(echo $args | sed -e "s,$key=[^ ]*,$key=$value,")"
else
args="$args $key=$value"
fi
else
exist=$(echo $args | grep $arg)
if ! [[ -n $exist ]]; then
args="$args $arg"
fi
fi
done
echo ${args}
}
update_bls_fragment() {
local indexes=($(param_to_indexes "$1")) && shift
local remove_args=$1 && shift
local add_args=$1 && shift
local initrd=$1 && shift
for i in ${indexes[*]}; do
if [[ -n $remove_args || -n $add_args ]]; then
local new_args="$(update_args "${bls_options[$i]}" "${remove_args}" "${add_args}")"
set_bls_value "${bls_file[$i]}" "options" "${new_args}"
fi
if [[ -n $initrd ]]; then
set_bls_value "${bls_file[$i]}" "initrd" "${initrd}"
fi
done
}
set_default_bls() {
local index=($(param_to_indexes "$1"))
if [[ $bootloader = grub2 ]]; then
grub2-editenv "${env}" set saved_entry="${bls_title[$index]}"
else
local default="${bls_version[$index]}"
local current="$(grep '^default=' ${zipl_config} | sed -e 's/^default=//')"
if [[ -n $current ]]; then
sed -i -e "s,^default=.*,default=${default}," "${zipl_config}"
else
echo "default=${default}" >> "${zipl_config}"
fi
fi
}
remove_var_prefix() {
if [[ -n $remove_kernel && $remove_kernel =~ ^/ ]]; then
remove_kernel="/${remove_kernel##*/}"
fi
if [[ -n $initrd ]]; then
initrd="/${initrd##*/}"
fi
if [[ -n $extra_initrd ]]; then
extra_initrd=" /${extra_initrd##*/}"
fi
if [[ -n $kernel ]]; then
kernel="/${kernel##*/}"
fi
if [[ -n $update_kernel && $update_kernel =~ ^/ ]]; then
update_kernel="/${update_kernel##*/}"
fi
}
print_usage()
{
cat <<EOF
Usage: grubby [OPTION...]
--add-kernel=kernel-path add an entry for the specified kernel
--args=args default arguments for the new kernel or new arguments for kernel being updated)
--bad-image-okay don't sanity check images in boot entries (for testing only)
-c, --config-file=path path to grub config file to update ("-" for stdin)
--copy-default use the default boot entry as a template for the new entry being added; if the default is not a linux image, or if the kernel referenced by the default image does not exist, the
first linux entry whose kernel does exist is used as the template
--default-kernel display the path of the default kernel
--default-index display the index of the default kernel
--default-title display the title of the default kernel
--env=path path for environment data
--grub2 configure grub2 bootloader
--info=kernel-path display boot information for specified kernel
--initrd=initrd-path initrd image for the new kernel
-i, --extra-initrd=initrd-path auxiliary initrd image for things other than the new kernel
--make-default make the newly added entry the default boot entry
-o, --output-file=path path to output updated config file ("-" for stdout)
--remove-args=STRING remove kernel arguments
--remove-kernel=kernel-path remove all entries for the specified kernel
--set-default=kernel-path make the first entry referencing the specified kernel the default
--set-default-index=entry-index make the given entry index the default entry
--title=entry-title title to use for the new kernel entry
--update-kernel=kernel-path updated information for the specified kernel
--zipl configure zipl bootloader
-b, --bls-directory path to directory containing the BootLoaderSpec fragment files
Help options:
-?, --help Show this help message
EOF
}
OPTS="$(getopt -o c:i:o:b:? --long help,add-kernel:,args:,bad-image-okay,\
config-file:,copy-default,default-kernel,default-index,default-title,env:,\
grub2,info:,initrd:,extra-initrd:,make-default,output-file:,remove-args:,\
remove-kernel:,set-default:,set-default-index:,title:,update-kernel:,zipl,\
bls-directory:,add-kernel:,add-multiboot:,mbargs:,mounts:,boot-filesystem:,\
bootloader-probe,debug,devtree,devtreedir:,elilo,efi,extlinux,grub,lilo,\
output-file:,remove-mbargs:,remove-multiboot:,silo,yaboot -n ${SCRIPTNAME} -- "$@")"
[[ $? = 0 ]] || exit 1
eval set -- "$OPTS"
while [ ${#} -gt 0 ]; do
case "$1" in
--help|-h)
print_usage
exit 0
;;
--add-kernel)
kernel="${2}"
shift
;;
--args)
args="${2}"
shift
;;
--bad-image-okay)
bad_image=true
;;
--config-file|-c)
zipl_config="${2}"
shift
;;
--copy-default)
copy_default=true
;;
--default-kernel)
display_default="kernel"
;;
--default-index)
display_default="index"
;;
--default-title)
display_default="title"
;;
--env)
env="${2}"
shift
;;
--grub2)
bootloader="grub2"
;;
--info)
display_info="${2}"
shift
;;
--initrd)
initrd="${2}"
shift
;;
--extra-initrd|-i)
extra_initrd=" /${2}"
shift
;;
--make-default)
make_default=true
;;
--output-file|-o)
output_file="${2}"
shift
;;
--remove-args)
remove_args="${2}"
shift
;;
--remove-kernel)
remove_kernel="${2}"
shift
;;
--set-default)
set_default="${2}"
shift
;;
--set-default-index)
set_default="${2}"
shift
;;
--title)
title="${2}"
shift
;;
--update-kernel)
update_kernel="${2}"
shift
;;
--zipl)
bootloader="zipl"
;;
--bls-directory|-b)
blsdir="${2}"
shift
;;
--add-kernel|--add-multiboot|--mbargs|--mounts|--boot-filesystem|\
--bootloader-probe|--debug|--devtree|--devtreedir|--elilo|--efi|\
--extlinux|--grub|--lilo|--output-file|--remove-mbargs|--silo|\
--remove-multiboot|--slilo|--yaboot)
echo
echo "${SCRIPTNAME}: the option \"${1}\" was deprecated" >&2
echo "Try '${SCRIPTNAME} --help' to list supported options" >&2
echo
exit 1
;;
--)
shift
break
;;
*)
echo
echo "${SCRIPTNAME}: invalid option \"${1}\"" >&2
echo "Try '${SCRIPTNAME} --help' for more information" >&2
echo
exit 1
;;
esac
shift
done
if [[ -z $blsdir ]]; then
blsdir="/boot/loader/entries"
fi
if [[ -z $env ]]; then
env="/boot/grub2/grubenv"
fi
if [[ -z $zipl_config ]]; then
zipl_config="/etc/zipl.conf"
fi
get_bls_values
default_index="$(get_default_index)"
if [[ -n $display_default ]]; then
display_default_value
fi
if [[ -n $display_info ]]; then
display_info_values "${display_info}"
fi
if [[ $bootloader = grub2 ]]; then
remove_var_prefix
fi
if [[ -n $kernel ]]; then
if [[ $copy_default = "true" ]]; then
opts="${bls_options[$default_index]}"
if [[ -n $args ]]; then
opts="${opts} ${args}"
fi
else
opts="${args}"
fi
add_bls_fragment "${kernel}" "${title}" "${opts}" "${initrd}" \
"${extra_initrd}"
fi
if [[ -n $remove_kernel ]]; then
remove_bls_fragment "${remove_kernel}"
fi
if [[ -n $update_kernel ]]; then
update_bls_fragment "${update_kernel}" "${remove_args}" "${args}" "${initrd}"
fi
if [[ -n $set_default ]]; then
set_default_bls "${set_default}"
fi
exit 0

View File

@ -1,6 +1,6 @@
Name: grubby
Version: 8.40
Release: 12%{?dist}
Release: 13%{?dist}
Summary: Command line tool for updating bootloader configs
License: GPLv2+
URL: https://github.com/rhinstaller/grubby
@ -9,6 +9,7 @@ URL: https://github.com/rhinstaller/grubby
# git archive --format=tar --prefix=grubby-%%{version}/ HEAD |bzip2 > grubby-%%{version}.tar.bz2
# Source0: %%{name}-%%{version}.tar.bz2
Source0: https://github.com/rhboot/grubby/archive/%{version}-1.tar.gz
Source1: grubby-bls
Patch1: drop-uboot-uImage-creation.patch
Patch2: 0001-Change-return-type-in-getRootSpecifier.patch
Patch3: 0002-Add-btrfs-subvolume-support-for-grub2.patch
@ -34,6 +35,8 @@ and zipl (s390) boot loaders. It is primarily designed to be used from scripts
which install new kernels and need to find information about the current boot
environment.
%global debug_package %{nil}
%prep
%setup -q -n grubby-%{version}-1
@ -57,20 +60,29 @@ make test
%install
make install DESTDIR=$RPM_BUILD_ROOT mandir=%{_mandir}
%postun
if [ "$1" = 0 ] ; then
grub2-switch-to-blscfg --backup-suffix=.rpmsave &>/dev/null || :
fi
rm %{buildroot}/sbin/installkernel
rm %{buildroot}/sbin/new-kernel-pkg
cp %{SOURCE1} %{buildroot}/sbin/grubby
%files
%package bls
Summary: Command line tool for updating BootLoaderSpec files
Obsoletes: %{name} < 8.40-13
BuildArch: noarch
%description bls
This package provides a grubby wrapper that manages BootLoaderSpec files and is
meant to only be used for legacy compatibility users with existing grubby users.
%files bls
%{!?_licensedir:%global license %%doc}
%license COPYING
/sbin/installkernel
/sbin/new-kernel-pkg
/sbin/grubby
%{_mandir}/man8/*.8*
%changelog
* Fri Jul 13 2018 Javier Martinez Canillas <javierm@redhat.com> - 8.40-13
- Add a grubby-bls package that contains grubby-bls script and obsoletes grubby
* Tue Apr 10 2018 Javier Martinez Canillas <javierm@redhat.com> - 8.40-12
- Use .rpmsave as backup suffix when switching to BLS configuration