mirror of
https://git.proxmox.com/git/proxmox-backup-restore-image
synced 2025-08-07 06:25:01 +00:00
add debug initramfs as seperate package
"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@proxmox.com>
This commit is contained in:
parent
37456b06e8
commit
2a1ef81fca
13
Makefile
13
Makefile
@ -2,11 +2,14 @@ include /usr/share/dpkg/pkg-info.mk
|
|||||||
include /usr/share/dpkg/architecture.mk
|
include /usr/share/dpkg/architecture.mk
|
||||||
|
|
||||||
PACKAGE=proxmox-backup-restore-image
|
PACKAGE=proxmox-backup-restore-image
|
||||||
|
PACKAGE_DBG=proxmox-backup-restore-image-debug
|
||||||
|
|
||||||
BUILDDIR=${PACKAGE}-${DEB_VERSION_UPSTREAM_REVISION}
|
BUILDDIR=${PACKAGE}-${DEB_VERSION_UPSTREAM_REVISION}
|
||||||
|
|
||||||
DEB=${PACKAGE}_${DEB_VERSION}_${DEB_BUILD_ARCH}.deb
|
DEB=${PACKAGE}_${DEB_VERSION}_${DEB_BUILD_ARCH}.deb
|
||||||
DSC=${PACKAGE}_${DEB_VERSION}.dsc
|
DSC=${PACKAGE}_${DEB_VERSION}.dsc
|
||||||
|
DEB_DBG=${PACKAGE_DBG}_${DEB_VERSION}_${DEB_BUILD_ARCH}.deb
|
||||||
|
DSC_DBG=${PACKAGE_DBG}_${DEB_VERSION}.dsc
|
||||||
|
|
||||||
all: deb
|
all: deb
|
||||||
|
|
||||||
@ -32,21 +35,23 @@ ${BUILDDIR}: submodules.prepared
|
|||||||
deb: ${DEB}
|
deb: ${DEB}
|
||||||
${DEB}: ${BUILDDIR}
|
${DEB}: ${BUILDDIR}
|
||||||
cd ${BUILDDIR}; dpkg-buildpackage -b -us -uc
|
cd ${BUILDDIR}; dpkg-buildpackage -b -us -uc
|
||||||
lintian ${DEB}
|
lintian ${DEB} ${DEB_DBG}
|
||||||
|
${DEB_DBG}: ${DEB}
|
||||||
|
|
||||||
.PHONY: dsc
|
.PHONY: dsc
|
||||||
dsc: ${DSC}
|
dsc: ${DSC}
|
||||||
${DSC}: ${BUILDDIR}
|
${DSC}: ${BUILDDIR}
|
||||||
cd ${BUILDDIR}; dpkg-buildpackage -S -us -uc -d
|
cd ${BUILDDIR}; dpkg-buildpackage -S -us -uc -d
|
||||||
lintian ${DSC}
|
lintian ${DSC} ${DSC_DBG}
|
||||||
|
${DSC_DBG}: ${DSC}
|
||||||
|
|
||||||
.PHONY: dinstall
|
.PHONY: dinstall
|
||||||
dinstall: deb
|
dinstall: deb
|
||||||
dpkg -i ${DEB}
|
dpkg -i ${DEB} ${DEB_DBG}
|
||||||
|
|
||||||
.PHONY: upload
|
.PHONY: upload
|
||||||
upload: ${DEB}
|
upload: ${DEB}
|
||||||
tar cf - ${DEB} | ssh -X repoman@repo.proxmox.com upload --product pbs,pve --dist buster
|
tar cf - ${DEB} ${DEB_DBG} | ssh -X repoman@repo.proxmox.com upload --product pbs,pve --dist buster
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
|
10
debian/control
vendored
10
debian/control
vendored
@ -2,7 +2,8 @@ Source: proxmox-backup-restore-image
|
|||||||
Section: admin
|
Section: admin
|
||||||
Priority: optional
|
Priority: optional
|
||||||
Maintainer: Proxmox Support Team <support@proxmox.com>
|
Maintainer: Proxmox Support Team <support@proxmox.com>
|
||||||
Build-Depends: asciidoc-base,
|
Build-Depends: apt-rdepends,
|
||||||
|
asciidoc-base,
|
||||||
automake,
|
automake,
|
||||||
bc,
|
bc,
|
||||||
bison,
|
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
|
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
|
Server snapshots. Not really useful on their own, so best used together with
|
||||||
the proxmox-backup-file-restore package, which provide the actual tools.
|
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.
|
||||||
|
1
debian/proxmox-backup-restore-image-debug.install
vendored
Normal file
1
debian/proxmox-backup-restore-image-debug.install
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
build/initramfs/initramfs-debug.img /usr/lib/x86_64-linux-gnu/proxmox-backup/file-restore/
|
2
debian/proxmox-backup-restore-image-debug.lintian-overrides
vendored
Normal file
2
debian/proxmox-backup-restore-image-debug.lintian-overrides
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
missing-depends-on-sensible-utils
|
||||||
|
uses-dpkg-database-directly
|
1
debian/proxmox-backup-restore-image-debug.triggers
vendored
Normal file
1
debian/proxmox-backup-restore-image-debug.triggers
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
activate-noawait proxmox-backup-restore-image-update
|
@ -9,12 +9,13 @@ SHIM_DIR=init-shim-rs
|
|||||||
|
|
||||||
KERNEL_IMG=${BUILDDIR}/bzImage
|
KERNEL_IMG=${BUILDDIR}/bzImage
|
||||||
INITRAMFS_IMG=${INITRAMFS_BUILDDIR}/initramfs.img
|
INITRAMFS_IMG=${INITRAMFS_BUILDDIR}/initramfs.img
|
||||||
|
INITRAMFS_IMG_DBG=${INITRAMFS_BUILDDIR}/initramfs-debug.img
|
||||||
|
|
||||||
CONFIG=config-base
|
CONFIG=config-base
|
||||||
|
|
||||||
RUST_SRC=$(wildcard ${SHIM_DIR}/**/*.rs) ${SHIM_DIR}/Cargo.toml
|
RUST_SRC=$(wildcard ${SHIM_DIR}/**/*.rs) ${SHIM_DIR}/Cargo.toml
|
||||||
|
|
||||||
all: ${KERNEL_IMG} ${INITRAMFS_IMG}
|
all: ${KERNEL_IMG} ${INITRAMFS_IMG_DBG}
|
||||||
|
|
||||||
${BUILDDIR}.prepared: ${CONFIG}
|
${BUILDDIR}.prepared: ${CONFIG}
|
||||||
rm -rf ${BUILDDIR}
|
rm -rf ${BUILDDIR}
|
||||||
@ -54,6 +55,8 @@ ${INITRAMFS_IMG}: ${BUILDDIR}.prepared ${RUST_SRC} build_initramfs.sh
|
|||||||
cd ${SHIM_DIR}; cargo build --release
|
cd ${SHIM_DIR}; cargo build --release
|
||||||
sh build_initramfs.sh
|
sh build_initramfs.sh
|
||||||
|
|
||||||
|
${INITRAMFS_IMG_DBG}: ${INITRAMFS_IMG}
|
||||||
|
|
||||||
.PHONY: test-run
|
.PHONY: test-run
|
||||||
test-run: ${KERNEL_IMG} ${INITRAMFS_IMG}
|
test-run: ${KERNEL_IMG} ${INITRAMFS_IMG}
|
||||||
# note: this will always fail since /proxmox-restore-daemon is not
|
# note: this will always fail since /proxmox-restore-daemon is not
|
||||||
|
@ -6,29 +6,36 @@ ROOT="root"
|
|||||||
BUILDDIR="build/initramfs"
|
BUILDDIR="build/initramfs"
|
||||||
INIT="../../init-shim-rs/target/release/init-shim-rs"
|
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"
|
echo "Using build dir: $BUILDDIR"
|
||||||
rm -rf "$BUILDDIR"
|
rm -rf "$BUILDDIR"
|
||||||
mkdir -p "$BUILDDIR"
|
mkdir -p "$BUILDDIR"
|
||||||
cd "$BUILDDIR"
|
cd "$BUILDDIR"
|
||||||
mkdir "$ROOT"
|
mkdir "$ROOT"
|
||||||
|
|
||||||
# add necessary packages to initramfs
|
# adds necessary packages to initramfs build root folder
|
||||||
for pkg in $PKGS; do
|
add_pkgs() {
|
||||||
apt-get download "$pkg"
|
DEPS=""
|
||||||
dpkg-deb -x ./*.deb "$ROOT"
|
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
|
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"
|
cp $INIT "$ROOT/init"
|
||||||
chmod a+x "$ROOT/init" # just to be sure
|
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
|
# tell daemon it's running in the correct environment
|
||||||
touch "$ROOT/restore-vm-marker"
|
touch "$ROOT/restore-vm-marker"
|
||||||
|
|
||||||
fakeroot -- sh -c "
|
add_pkgs "
|
||||||
cd '$ROOT';
|
libstdc++6:amd64 \
|
||||||
find . -print0 | cpio --null -oV --format=newc -F ../initramfs.img
|
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"
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
use anyhow::Error;
|
use anyhow::{bail, Error};
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
const URANDOM_MAJ: u64 = 1;
|
const URANDOM_MAJ: u64 = 1;
|
||||||
const URANDOM_MIN: u64 = 9;
|
const URANDOM_MIN: u64 = 9;
|
||||||
@ -21,15 +23,54 @@ fn main() {
|
|||||||
do_mknod("/dev/urandom", URANDOM_MAJ, URANDOM_MIN)
|
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();
|
let uptime = read_uptime();
|
||||||
println!("[init-shim] reached daemon start after {:.2}s", uptime);
|
println!("[init-shim] reached daemon start after {:.2}s", uptime);
|
||||||
|
|
||||||
do_run("/proxmox-restore-daemon");
|
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> {
|
fn do_mount(target: &str, fstype: &str) -> Result<(), Error> {
|
||||||
use nix::mount::{mount, MsFlags};
|
use nix::mount::{mount, MsFlags};
|
||||||
fs::create_dir(target)?;
|
fs::create_dir_all(target)?;
|
||||||
let none_type: Option<&CStr> = None;
|
let none_type: Option<&CStr> = None;
|
||||||
mount(
|
mount(
|
||||||
none_type,
|
none_type,
|
||||||
@ -63,7 +104,6 @@ fn read_uptime() -> f32 {
|
|||||||
|
|
||||||
fn do_run(cmd: &str) -> ! {
|
fn do_run(cmd: &str) -> ! {
|
||||||
use std::io::ErrorKind;
|
use std::io::ErrorKind;
|
||||||
use std::process::Command;
|
|
||||||
|
|
||||||
let spawn_res = Command::new(cmd).env("RUST_BACKTRACE", "1").spawn();
|
let spawn_res = Command::new(cmd).env("RUST_BACKTRACE", "1").spawn();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user