[pbs-devel] [PATCH proxmox-backup-restore-image 9/9] add debug initramfs as seperate package

Thomas Lamprecht t.lamprecht at proxmox.com
Thu May 6 20:07:18 CEST 2021


On 06.05.21 17:26, Stefan Reiter wrote:
> "proxmox-backup-restore-image-debug", containing only the debug
> initramfs, so depends on the base "proxmox-backup-restore-image" for the
> kernel.
> 
> Adapt the init-shim to start an agetty on ttyS1, which the host
> can use to connect to a root shell for debugging, and use
> create_dir_all, since some debug packages seem to create /sys and /proc
> as empty dirs already.
> 
> The build_initramfs.sh script is modified to include dependency
> resolution via apt-rdepends, so debug packages like agetty (util-linux),
> busybox and gdb can easily be added. This now builds both the regular
> and the debug binary at once, to avoid downloading shared packages
> twice.
> 
> Signed-off-by: Stefan Reiter <s.reiter at proxmox.com>
> ---
> 
> The updated build_initramfs script should also make further additions to the
> initrd easier, e.g. adding lvm and zfs tooling if necessary.
> 
>  Makefile                                      | 13 +++--
>  debian/control                                | 10 +++-
>  ...proxmox-backup-restore-image-debug.install |  1 +
>  ...ckup-restore-image-debug.lintian-overrides |  2 +
>  ...roxmox-backup-restore-image-debug.triggers |  1 +
>  src/Makefile                                  |  5 +-
>  src/build_initramfs.sh                        | 55 +++++++++++++------
>  src/init-shim-rs/src/main.rs                  | 46 +++++++++++++++-
>  8 files changed, 106 insertions(+), 27 deletions(-)
>  create mode 100644 debian/proxmox-backup-restore-image-debug.install
>  create mode 100644 debian/proxmox-backup-restore-image-debug.lintian-overrides
>  create mode 100644 debian/proxmox-backup-restore-image-debug.triggers
> 
> diff --git a/Makefile b/Makefile
> index d11ac3e..92aa791 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -2,11 +2,14 @@ include /usr/share/dpkg/pkg-info.mk
>  include /usr/share/dpkg/architecture.mk
>  
>  PACKAGE=proxmox-backup-restore-image
> +PACKAGE_DBG=proxmox-backup-restore-image-debug
>  
>  BUILDDIR=${PACKAGE}-${DEB_VERSION_UPSTREAM_REVISION}
>  
>  DEB=${PACKAGE}_${DEB_VERSION}_${DEB_BUILD_ARCH}.deb
>  DSC=${PACKAGE}_${DEB_VERSION}.dsc
> +DEB_DBG=${PACKAGE_DBG}_${DEB_VERSION}_${DEB_BUILD_ARCH}.deb
> +DSC_DBG=${PACKAGE_DBG}_${DEB_VERSION}.dsc
>  

multiple source control files do not really make sense. There's only one source
per d/control instance (normally per repo) for Debians POV...

>  all: deb
>  
> @@ -32,21 +35,23 @@ ${BUILDDIR}: submodules.prepared
>  deb: ${DEB}
>  ${DEB}: ${BUILDDIR}
>  	cd ${BUILDDIR}; dpkg-buildpackage -b -us -uc
> -	lintian ${DEB}
> +	lintian ${DEB} ${DEB_DBG}
> +${DEB_DBG}: ${DEB}
>  
>  .PHONY: dsc
>  dsc: ${DSC}
>  ${DSC}: ${BUILDDIR}
>  	cd ${BUILDDIR}; dpkg-buildpackage -S -us -uc -d
> -	lintian ${DSC}
> +	lintian ${DSC} ${DSC_DBG}
> +${DSC_DBG}: ${DSC}
>  
>  .PHONY: dinstall
>  dinstall: deb
> -	dpkg -i ${DEB}
> +	dpkg -i ${DEB} ${DEB_DBG}
>  
>  .PHONY: upload
>  upload: ${DEB}
> -	tar cf - ${DEB} | ssh -X repoman at repo.proxmox.com upload --product pbs,pve --dist buster
> +	tar cf - ${DEB} ${DEB_DBG} | ssh -X repoman at repo.proxmox.com upload --product pbs,pve --dist buster
>  
>  .PHONY: clean
>  clean:
> diff --git a/debian/control b/debian/control
> index 5b50392..b87c903 100644
> --- a/debian/control
> +++ b/debian/control
> @@ -2,7 +2,8 @@ Source: proxmox-backup-restore-image
>  Section: admin
>  Priority: optional
>  Maintainer: Proxmox Support Team <support at proxmox.com>
> -Build-Depends: asciidoc-base,
> +Build-Depends: apt-rdepends,
> +               asciidoc-base,
>                 automake,
>                 bc,
>                 bison,
> @@ -34,3 +35,10 @@ Description: Kernel/initramfs images for Proxmox Backup single-file restore.
>   Preconfigured images used as base for single file restore of Proxmox Backup
>   Server snapshots. Not really useful on their own, so best used together with
>   the proxmox-backup-file-restore package, which provide the actual tools.
> +
> +Package: proxmox-backup-restore-image-debug
> +Architecture: amd64
> +Depends: proxmox-backup-restore-image
> +Description: Debug initramfs image for Proxmox Backup single-file restore.
> + Not required for production use, only useful for manual inspection of file
> + restore VMs. Includes busybox and gdb.
> diff --git a/debian/proxmox-backup-restore-image-debug.install b/debian/proxmox-backup-restore-image-debug.install
> new file mode 100644
> index 0000000..02ffb49
> --- /dev/null
> +++ b/debian/proxmox-backup-restore-image-debug.install
> @@ -0,0 +1 @@
> +build/initramfs/initramfs-debug.img /usr/lib/x86_64-linux-gnu/proxmox-backup/file-restore/
> diff --git a/debian/proxmox-backup-restore-image-debug.lintian-overrides b/debian/proxmox-backup-restore-image-debug.lintian-overrides
> new file mode 100644
> index 0000000..ad59aad
> --- /dev/null
> +++ b/debian/proxmox-backup-restore-image-debug.lintian-overrides
> @@ -0,0 +1,2 @@
> +missing-depends-on-sensible-utils
> +uses-dpkg-database-directly
> diff --git a/debian/proxmox-backup-restore-image-debug.triggers b/debian/proxmox-backup-restore-image-debug.triggers
> new file mode 100644
> index 0000000..948d898
> --- /dev/null
> +++ b/debian/proxmox-backup-restore-image-debug.triggers
> @@ -0,0 +1 @@
> +activate-noawait proxmox-backup-restore-image-update
> diff --git a/src/Makefile b/src/Makefile
> index 37f385f..a398ea1 100644
> --- a/src/Makefile
> +++ b/src/Makefile
> @@ -9,12 +9,13 @@ SHIM_DIR=init-shim-rs
>  
>  KERNEL_IMG=${BUILDDIR}/bzImage
>  INITRAMFS_IMG=${INITRAMFS_BUILDDIR}/initramfs.img
> +INITRAMFS_IMG_DBG=${INITRAMFS_BUILDDIR}/initramfs-debug.img
>  
>  CONFIG=config-base
>  
>  RUST_SRC=$(wildcard ${SHIM_DIR}/**/*.rs) ${SHIM_DIR}/Cargo.toml
>  
> -all: ${KERNEL_IMG} ${INITRAMFS_IMG}
> +all: ${KERNEL_IMG} ${INITRAMFS_IMG_DBG}
>  
>  ${BUILDDIR}.prepared: ${CONFIG}
>  	rm -rf ${BUILDDIR}
> @@ -54,6 +55,8 @@ ${INITRAMFS_IMG}: ${BUILDDIR}.prepared ${RUST_SRC} build_initramfs.sh
>  	cd ${SHIM_DIR}; cargo build --release
>  	sh build_initramfs.sh
>  
> +${INITRAMFS_IMG_DBG}: ${INITRAMFS_IMG}
> +
>  .PHONY: test-run
>  test-run: ${KERNEL_IMG} ${INITRAMFS_IMG}
>  	# note: this will always fail since /proxmox-restore-daemon is not
> diff --git a/src/build_initramfs.sh b/src/build_initramfs.sh
> index 4efa29b..c4ee95c 100755
> --- a/src/build_initramfs.sh
> +++ b/src/build_initramfs.sh
> @@ -6,29 +6,36 @@ ROOT="root"
>  BUILDDIR="build/initramfs"
>  INIT="../../init-shim-rs/target/release/init-shim-rs"
>  
> -PKGS=" \
> -    libc6:amd64 \
> -    libgcc1:amd64 \
> -    libstdc++6:amd64 \
> -    libssl1.1:amd64 \
> -    libattr1:amd64 \
> -    libacl1:amd64
> -"
> -
>  echo "Using build dir: $BUILDDIR"
>  rm -rf "$BUILDDIR"
>  mkdir -p "$BUILDDIR"
>  cd "$BUILDDIR"
>  mkdir "$ROOT"
>  
> -# add necessary packages to initramfs
> -for pkg in $PKGS; do
> -    apt-get download "$pkg"
> -    dpkg-deb -x ./*.deb "$ROOT"
> +# adds necessary packages to initramfs build root folder
> +add_pkgs() {
> +    DEPS=""
> +    for pkg in $1; do
> +        LOCAL_DEPS=$(apt-rdepends -f Depends -s Depends "$pkg" | grep -v '^ ')
> +        DEPS="$DEPS $LOCAL_DEPS"
> +    done
> +    # debconf and gcc are unnecessary
> +    DEPS=$(echo "$DEPS" |\
> +        sed -E 's/debconf(-2\.0)?//' |\
> +        sed -E 's/gcc-.{1,2}-base//')
> +    apt-get download $DEPS
> +    for deb in ./*.deb; do
> +        dpkg-deb -x "$deb" "$ROOT"
> +    done
>      rm ./*.deb
> -done
> +}
>  
> -rm -rf ${ROOT:?}/usr/share # contains only docs and debian stuff
> +make_cpio() {
> +    fakeroot -- sh -c "
> +        cd '$ROOT';
> +        find . -print0 | cpio --null -oV --format=newc -F ../$1
> +    "
> +}
>  
>  cp $INIT "$ROOT/init"
>  chmod a+x "$ROOT/init" # just to be sure
> @@ -36,7 +43,19 @@ chmod a+x "$ROOT/init" # just to be sure
>  # tell daemon it's running in the correct environment
>  touch "$ROOT/restore-vm-marker"
>  
> -fakeroot -- sh -c "
> -    cd '$ROOT';
> -    find . -print0 | cpio --null -oV --format=newc -F ../initramfs.img
> +add_pkgs "
> +    libstdc++6:amd64 \
> +    libssl1.1:amd64 \
> +    libacl1:amd64 \
>  "
> +rm -rf ${ROOT:?}/usr/share # contains only docs and debian stuff
> +make_cpio "initramfs.img"
> +
> +# add debug helpers for debug initramfs, packages from above are included too
> +add_pkgs "
> +    util-linux:amd64 \
> +    busybox-static:amd64 \
> +    gdb:amd64 \
> +"
> +# leave /usr/share here, it contains necessary stuff for gdb
> +make_cpio "initramfs-debug.img"
> diff --git a/src/init-shim-rs/src/main.rs b/src/init-shim-rs/src/main.rs
> index 89aff7b..641218f 100644
> --- a/src/init-shim-rs/src/main.rs
> +++ b/src/init-shim-rs/src/main.rs
> @@ -1,6 +1,8 @@
> -use anyhow::Error;
> +use anyhow::{bail, Error};
>  use std::ffi::CStr;
>  use std::fs;
> +use std::path::PathBuf;
> +use std::process::Command;
>  
>  const URANDOM_MAJ: u64 = 1;
>  const URANDOM_MIN: u64 = 9;
> @@ -21,15 +23,54 @@ fn main() {
>          do_mknod("/dev/urandom", URANDOM_MAJ, URANDOM_MIN)
>      });
>  
> +    if let Err(err) = run_agetty() {
> +        // not fatal
> +        println!("[init-shim] debug: agetty start failed: {}", err);
> +    }
> +
>      let uptime = read_uptime();
>      println!("[init-shim] reached daemon start after {:.2}s", uptime);
>  
>      do_run("/proxmox-restore-daemon");
>  }
>  
> +fn run_agetty() -> Result<(), Error> {
> +    use nix::unistd::{fork, ForkResult};
> +
> +    if !PathBuf::from("/sbin/agetty").exists() {
> +        bail!("/sbin/agetty not found, probably not running debug mode and safe to ignore");
> +    }
> +
> +    if !PathBuf::from("/sys/class/tty/ttyS1/device/driver/serial8250").exists() {
> +        bail!("ttyS1 device does not exist or is not a 8250");
> +    }
> +
> +    let dev = fs::read_to_string("/sys/class/tty/ttyS1/dev")?;
> +    let (tty_maj, tty_min) = dev.trim().split_at(dev.find(':').unwrap_or(1));
> +    do_mknod("/dev/ttyS1", tty_maj.parse()?, tty_min[1..].parse()?)?;
> +
> +    match unsafe { fork() } {
> +        Ok(ForkResult::Parent { .. }) => {}
> +        Ok(ForkResult::Child) => loop {
> +            // continue to restart agetty if it exits, this runs in a forked process
> +            println!("[init-shim] Spawning new agetty");
> +            let res = Command::new("/sbin/agetty")
> +                .args(&["-a", "root", "-l", "/bin/busybox", "-o", "sh", "115200", "ttyS1"])
> +                .spawn()
> +                .unwrap()
> +                .wait()
> +                .unwrap();
> +            println!("[init-shim] agetty exited: {}", res.code().unwrap_or(-1));
> +        },
> +        Err(err) => println!("fork failed: {}", err),
> +    }
> +
> +    Ok(())
> +}
> +
>  fn do_mount(target: &str, fstype: &str) -> Result<(), Error> {
>      use nix::mount::{mount, MsFlags};
> -    fs::create_dir(target)?;
> +    fs::create_dir_all(target)?;
>      let none_type: Option<&CStr> = None;
>      mount(
>          none_type,
> @@ -63,7 +104,6 @@ fn read_uptime() -> f32 {
>  
>  fn do_run(cmd: &str) -> ! {
>      use std::io::ErrorKind;
> -    use std::process::Command;
>  
>      let spawn_res = Command::new(cmd).env("RUST_BACKTRACE", "1").spawn();
>  
> 






More information about the pbs-devel mailing list