Compare commits
21 commits
f2020cf3ed
...
2f768b07dc
Author | SHA1 | Date | |
---|---|---|---|
2f768b07dc | |||
4ca0556cd2 | |||
d9f9c64ac2 | |||
dd94ee3b84 | |||
99d2579e0b | |||
610058d105 | |||
2ff8f6142d | |||
417d958a14 | |||
8674e11c71 | |||
daa886264b | |||
d157ba2b9a | |||
884a04b18a | |||
014a9c30a5 | |||
90fe7941bb | |||
428ee78121 | |||
ae6dcc001d | |||
b4ba78897b | |||
69954515e7 | |||
136cbdf0f1 | |||
87edb1c2d1 | |||
0de9e19ca4 |
10 changed files with 220 additions and 105 deletions
|
@ -20,6 +20,8 @@ if [ -e ./mmdebstrap ]; then
|
|||
fi
|
||||
|
||||
perlcritic --severity 4 --verbose 8 ./mmdebstrap
|
||||
|
||||
pod2man ./mmdebstrap >/dev/null
|
||||
fi
|
||||
|
||||
for f in tarfilter coverage.py caching_proxy.py; do
|
||||
|
@ -27,7 +29,7 @@ for f in tarfilter coverage.py caching_proxy.py; do
|
|||
black --check "./$f"
|
||||
done
|
||||
|
||||
shellcheck --exclude=SC2016 coverage.sh make_mirror.sh run_null.sh run_qemu.sh gpgvnoexpkeysig hooks/*/*.sh
|
||||
shellcheck --exclude=SC2016 coverage.sh make_mirror.sh run_null.sh run_qemu.sh gpgvnoexpkeysig mmdebstrap-autopkgtest-build-qemu hooks/*/*.sh
|
||||
|
||||
mirrordir="./shared/cache/debian"
|
||||
|
||||
|
|
|
@ -449,7 +449,7 @@ if [ "$HAVE_QEMU" = "yes" ]; then
|
|||
tmpdir="$(mktemp -d)"
|
||||
trap 'kill "$PROXYPID" || :;cleanuptmpdir; cleanup_newcachedir' EXIT INT TERM
|
||||
|
||||
pkgs=perl-doc,systemd-sysv,perl,arch-test,fakechroot,fakeroot,mount,uidmap,qemu-user-static,qemu-user,dpkg-dev,mini-httpd,libdevel-cover-perl,libtemplate-perl,debootstrap,procps,apt-cudf,aspcud,python3,libcap2-bin,gpg,debootstrap,distro-info-data,iproute2,ubuntu-keyring,apt-utils,squashfs-tools-ng,genext2fs,linux-image-generic
|
||||
pkgs=perl-doc,systemd-sysv,perl,arch-test,fakechroot,fakeroot,mount,uidmap,qemu-user-static,qemu-user,dpkg-dev,mini-httpd,libdevel-cover-perl,libtemplate-perl,debootstrap,procps,apt-cudf,aspcud,python3,libcap2-bin,gpg,debootstrap,distro-info-data,iproute2,ubuntu-keyring,apt-utils,squashfs-tools-ng,genext2fs,linux-image-generic,passwd
|
||||
if [ ! -e ./mmdebstrap ]; then
|
||||
pkgs="$pkgs,mmdebstrap"
|
||||
fi
|
||||
|
@ -493,6 +493,8 @@ mount -t 9p -o trans=virtio,access=any,msize=128k mmdebstrap /mnt
|
|||
# need to restart mini-httpd because we mounted different content into www-root
|
||||
systemctl restart mini-httpd
|
||||
|
||||
ip link set enp0s1 down || :
|
||||
|
||||
handler () {
|
||||
while IFS= read -r line || [ -n "$line" ]; do
|
||||
printf "%s %s: %s\n" "$(date -u -d "0 $(date +%s.%3N) seconds - $2 seconds" +"%T.%3N")" "$1" "$line"
|
||||
|
@ -530,7 +532,8 @@ END
|
|||
fi
|
||||
# set PATH to pick up the correct mmdebstrap variant
|
||||
env PATH="$(dirname "$(realpath --canonicalize-existing "$CMD")"):$PATH" \
|
||||
debvm-create --skip=usrmerge --size="$DISK_SIZE" --release="$DEFAULT_DIST" \
|
||||
debvm-create --skip=usrmerge,systemdnetwork \
|
||||
--size="$DISK_SIZE" --release="$DEFAULT_DIST" \
|
||||
--output="$newcachedir/debian-$DEFAULT_DIST.ext4" -- \
|
||||
--architectures="$arches" --include="$pkgs" \
|
||||
--setup-hook='echo "Acquire::http::Proxy \"http://127.0.0.1:8080/\";" > "$1/etc/apt/apt.conf.d/00proxy"' \
|
||||
|
@ -541,7 +544,7 @@ END
|
|||
--customize-hook='touch "$1/mmdebstrap-testenv"' \
|
||||
--customize-hook='copy-in "'"$tmpdir"'/mmdebstrap.service" /etc/systemd/system/' \
|
||||
--customize-hook='copy-in "'"$tmpdir"'/worker.sh" /' \
|
||||
--customize-hook='printf 127.0.0.1 localhost > "$1/etc/hosts"' \
|
||||
--customize-hook='echo 127.0.0.1 localhost > "$1/etc/hosts"' \
|
||||
--customize-hook='printf "START=1\nDAEMON_OPTS=\"-h 127.0.0.1 -p 80 -u nobody -dd /mnt/cache -i /var/run/mini-httpd.pid -T UTF-8\"\n" > "$1/etc/default/mini-httpd"' \
|
||||
"$mirror"
|
||||
|
||||
|
|
197
mmdebstrap
197
mmdebstrap
|
@ -1953,7 +1953,7 @@ sub run_setup() {
|
|||
# since we do not know the dpkg version inside the chroot at this
|
||||
# point, we can only omit it in chrootless mode
|
||||
if ($options->{mode} ne 'chrootless'
|
||||
or scalar @{ $options->{dpkgopts} } > 0) {
|
||||
or length $options->{dpkgopts} > 0) {
|
||||
push @directories, '/etc/dpkg/dpkg.cfg.d/';
|
||||
}
|
||||
# if dpkg and apt operate from the outside we need some more
|
||||
|
@ -2083,26 +2083,11 @@ sub run_setup() {
|
|||
close $fh;
|
||||
}
|
||||
|
||||
if (scalar @{ $options->{aptopts} } > 0
|
||||
if (length $options->{aptopts} > 0
|
||||
and (!-e "$options->{root}/etc/apt/apt.conf.d/99mmdebstrap")) {
|
||||
open my $fh, '>', "$options->{root}/etc/apt/apt.conf.d/99mmdebstrap"
|
||||
or error "cannot open /etc/apt/apt.conf.d/99mmdebstrap: $!";
|
||||
foreach my $opt (@{ $options->{aptopts} }) {
|
||||
if (-r $opt) {
|
||||
# flush handle because copy() uses syswrite() which bypasses
|
||||
# buffered IO
|
||||
$fh->flush();
|
||||
copy $opt, $fh or error "cannot copy $opt: $!";
|
||||
} else {
|
||||
print $fh $opt;
|
||||
if ($opt !~ /;$/) {
|
||||
print $fh ';';
|
||||
}
|
||||
if ($opt !~ /\n$/) {
|
||||
print $fh "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
print $fh $options->{aptopts};
|
||||
close $fh;
|
||||
if ($verbosity_level >= 3) {
|
||||
debug "content of /etc/apt/apt.conf.d/99mmdebstrap:";
|
||||
|
@ -2110,7 +2095,7 @@ sub run_setup() {
|
|||
}
|
||||
}
|
||||
|
||||
if (scalar @{ $options->{dpkgopts} } > 0
|
||||
if (length $options->{dpkgopts} > 0
|
||||
and (!-e "$options->{root}/etc/dpkg/dpkg.cfg.d/99mmdebstrap")) {
|
||||
# FIXME: in chrootless mode, dpkg will only read the configuration
|
||||
# from the host -- see #808203
|
||||
|
@ -2120,19 +2105,7 @@ sub run_setup() {
|
|||
}
|
||||
open my $fh, '>', "$options->{root}/etc/dpkg/dpkg.cfg.d/99mmdebstrap"
|
||||
or error "cannot open /etc/dpkg/dpkg.cfg.d/99mmdebstrap: $!";
|
||||
foreach my $opt (@{ $options->{dpkgopts} }) {
|
||||
if (-r $opt) {
|
||||
# flush handle because copy() uses syswrite() which bypasses
|
||||
# buffered IO
|
||||
$fh->flush();
|
||||
copy $opt, $fh or error "cannot copy $opt: $!";
|
||||
} else {
|
||||
print $fh $opt;
|
||||
if ($opt !~ /\n$/) {
|
||||
print $fh "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
print $fh $options->{dpkgopts};
|
||||
close $fh;
|
||||
if ($verbosity_level >= 3) {
|
||||
debug "content of /etc/dpkg/dpkg.cfg.d/99mmdebstrap:";
|
||||
|
@ -2234,6 +2207,8 @@ sub run_setup() {
|
|||
chmod $mode, "$options->{root}/$file"
|
||||
or error "cannot chmod $file: $!";
|
||||
}
|
||||
} elsif (-e $file && -e "$options->{root}/$file") {
|
||||
info "rootfs alreday contains $file";
|
||||
} else {
|
||||
warning("Host system does not have a $file to copy into the"
|
||||
. " rootfs.");
|
||||
|
@ -3137,7 +3112,7 @@ sub run_cleanup() {
|
|||
} else {
|
||||
# clean up temporary configuration file
|
||||
unlink "$options->{root}/etc/apt/apt.conf.d/00mmdebstrap"
|
||||
or error "failed to unlink /etc/apt/apt.conf.d/00mmdebstrap: $!";
|
||||
or warning "failed to unlink /etc/apt/apt.conf.d/00mmdebstrap: $!";
|
||||
|
||||
if (defined $ENV{APT_CONFIG} && -e $ENV{APT_CONFIG}) {
|
||||
unlink $ENV{APT_CONFIG}
|
||||
|
@ -4518,8 +4493,8 @@ sub main() {
|
|||
architectures => [$hostarch],
|
||||
mode => 'auto',
|
||||
format => 'auto',
|
||||
dpkgopts => [],
|
||||
aptopts => [],
|
||||
dpkgopts => '',
|
||||
aptopts => '',
|
||||
apttrusted => $apttrusted,
|
||||
apttrustedparts => $apttrustedparts,
|
||||
noop => [],
|
||||
|
@ -4586,8 +4561,43 @@ sub main() {
|
|||
},
|
||||
'architectures=s@' => \$options->{architectures},
|
||||
'mode=s' => \$options->{mode},
|
||||
'dpkgopt=s@' => \$options->{dpkgopts},
|
||||
'aptopt=s@' => \$options->{aptopts},
|
||||
'dpkgopt=s' => sub {
|
||||
my ($opt_name, $opt_value) = @_;
|
||||
if (-r $opt_value) {
|
||||
open my $fh, '<', $opt_value
|
||||
or error "failed to open $opt_value: $!";
|
||||
$options->{dpkgopts} .= do { local $/; <$fh> };
|
||||
if ($options->{dpkgopts} !~ /\n$/) {
|
||||
print $fh "\n";
|
||||
}
|
||||
close $fh;
|
||||
} else {
|
||||
$options->{dpkgopts} .= $opt_value;
|
||||
if ($opt_value !~ /\n$/) {
|
||||
$options->{dpkgopts} .= "\n";
|
||||
}
|
||||
}
|
||||
},
|
||||
'aptopt=s' => sub {
|
||||
my ($opt_name, $opt_value) = @_;
|
||||
if (-r $opt_value) {
|
||||
open my $fh, '<', $opt_value
|
||||
or error "failed to open $opt_value: $!";
|
||||
$options->{aptopts} .= do { local $/; <$fh> };
|
||||
if ($options->{aptopts} !~ /\n$/) {
|
||||
print $fh "\n";
|
||||
}
|
||||
close $fh;
|
||||
} else {
|
||||
$options->{aptopts} .= $opt_value;
|
||||
if ($opt_value !~ /;$/) {
|
||||
$options->{aptopts} .= ';';
|
||||
}
|
||||
if ($opt_value !~ /\n$/) {
|
||||
$options->{aptopts} .= "\n";
|
||||
}
|
||||
}
|
||||
},
|
||||
'keyring=s' => sub {
|
||||
my ($opt_name, $opt_value) = @_;
|
||||
if ($opt_value =~ /"/) {
|
||||
|
@ -4722,7 +4732,7 @@ sub main() {
|
|||
}
|
||||
push @{ $options->{skip} }, $skip;
|
||||
}
|
||||
}) or pod2usage(-exitval => 2, -verbose => 1);
|
||||
}) or pod2usage(-exitval => 2, -verbose => 0);
|
||||
|
||||
if (defined($logfile)) {
|
||||
open(STDERR, '>', $logfile) or error "cannot open $logfile: $!";
|
||||
|
@ -4939,9 +4949,17 @@ sub main() {
|
|||
test_unshare_userns(1);
|
||||
}
|
||||
} elsif ($options->{mode} eq 'chrootless') {
|
||||
if ($EFFECTIVE_USER_ID == 0) {
|
||||
warning "running chrootless mode as root might damage the host "
|
||||
. "system";
|
||||
if (any { $_ eq 'check/chrootless' } @{ $options->{skip} }) {
|
||||
info "skipping check/chrootless as requested";
|
||||
} else {
|
||||
my $ischroot = 0 == system 'ischroot';
|
||||
if ( $EFFECTIVE_USER_ID == 0
|
||||
&& !exists $ENV{FAKEROOTKEY}
|
||||
&& !$ischroot) {
|
||||
error
|
||||
"running chrootless mode as root without fakeroot might "
|
||||
. "damage the host system if not run inside a chroot";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error "unknown mode: $options->{mode}";
|
||||
|
@ -6392,45 +6410,52 @@ B<mmdebstrap> creates a Debian chroot of I<SUITE> into I<TARGET> from one or
|
|||
more I<MIRROR>s. It is meant as an alternative to the debootstrap tool (see
|
||||
section B<DEBOOTSTRAP>). In contrast to debootstrap it uses apt to resolve
|
||||
dependencies and is thus able to use more than one mirror and resolve more
|
||||
complex dependencies. See section B<OPERATION> for an overview of how
|
||||
B<mmdebstrap> works internally.
|
||||
complex dependency relationships. See section B<OPERATION> for an overview of
|
||||
how B<mmdebstrap> works internally.
|
||||
|
||||
If no I<MIRROR> option is provided and I<SUITE> is not a stable release name,
|
||||
L<http://deb.debian.org/debian> is used. If I<SUITE> is a stable release name
|
||||
and no I<MIRROR> is specified, then mirrors for updates and security are
|
||||
automatically added. If a I<MIRROR> option starts with "deb " or "deb-src "
|
||||
then it is used as a one-line-style format entry for apt's sources.list inside
|
||||
the chroot. If a I<MIRROR> option contains a "://" then it is interpreted as a
|
||||
mirror URI and the apt line inside the chroot is assembled as "deb [arch=A] B C
|
||||
D" where A is the host's native architecture, B is the I<MIRROR>, C is the
|
||||
given I<SUITE> and D is the components given via B<--components> (defaults to
|
||||
"main"). If a I<MIRROR> option happens to be an existing file, then its
|
||||
contents are pasted into the chroot's sources.list. This can be used to supply
|
||||
a deb822 style sources.list. If I<MIRROR> is C<-> then standard input is pasted
|
||||
into the chroot's sources.list. More than one mirror can be specified and are
|
||||
appended to the chroot's sources.list in the given order. If you specify a
|
||||
https or tor I<MIRROR> and you want the chroot to be able to update itself,
|
||||
don't forget to also install the ca-certificates package, the
|
||||
apt-transport-https package for apt versions less than 1.5 and/or the
|
||||
apt-transport-tor package using the B<--include> option, as necessary.
|
||||
|
||||
The optional I<TARGET> argument can either be the path to a directory, the path
|
||||
to a tarball filename, the path to a squashfs image, the path to an ext2 image,
|
||||
a FIFO, a character special device, or C<->. Without the B<--format> option,
|
||||
I<TARGET> will be used to choose the format. See the section B<FORMATS> for
|
||||
more information. If no I<TARGET> was specified or if I<TARGET> is C<->, an
|
||||
uncompressed tarball will be sent to standard output.
|
||||
|
||||
The I<SUITE> may be a valid release code name (eg, sid, stretch, jessie) or a
|
||||
symbolic name (eg, unstable, testing, stable, oldstable). Any suite name that
|
||||
works with apt on the given mirror will work. If no I<SUITE> was specified,
|
||||
then a single I<MIRROR> C<-> is added and thus the information of the desired
|
||||
suite has to come from standard input as part of a valid apt sources.list file.
|
||||
The I<SUITE> option may either be a valid release code name (eg, sid, bookworm,
|
||||
trixie) or a symbolic name (eg, unstable, testing, stable, oldstable). Any
|
||||
suite name that works with apt on the given mirror will work. The I<SUITE>
|
||||
option is optional if no I<TARGET> and no I<MIRROR> option is provided. If
|
||||
I<SUITE> is missing, then the information of the desired suite has to come from
|
||||
standard input as part of a valid apt sources.list file or be set up via hooks.
|
||||
The value of the I<SUITE> argument will be used to determine which apt index to
|
||||
use for finding out the set of C<Essential:yes> packages and/or the set of
|
||||
packages with the right priority for the selected variant. See the section
|
||||
packages with the right priority for the selected variant. This functionality
|
||||
can be disabled by choosing the empty string for I<SUITE>. See the section
|
||||
B<VARIANTS> for more information.
|
||||
|
||||
The I<TARGET> option may either be the path to a directory, the path to a
|
||||
tarball filename, the path to a squashfs image, the path to an ext2 image, a
|
||||
FIFO, a character special device, or C<->. The I<TARGET> option is optional if
|
||||
no I<MIRROR> option is provided. If I<TARGET> is missing or if I<TARGET> is
|
||||
C<->, an uncompressed tarball will be sent to standard output. Without the
|
||||
B<--format> option, I<TARGET> will be used to choose the format. See the
|
||||
section B<FORMATS> for more information.
|
||||
|
||||
The I<MIRROR> option may either be provided as a URI, in apt one-line format,
|
||||
as a path to a file in apt's one-line or deb822-format, or C<->. If no
|
||||
I<MIRROR> option is provided, then L<http://deb.debian.org/debian> is used as
|
||||
the default. If I<SUITE> does not refer to "unstable" or "testing", then
|
||||
I<SUITE>-updates and I<SUITE>-security mirrors are automatically added. If a
|
||||
I<MIRROR> option starts with "deb " or "deb-src " then it is used as a one-line
|
||||
format entry for apt's sources.list inside the chroot. If a I<MIRROR> option
|
||||
contains a "://" then it is interpreted as a mirror URI and the apt line inside
|
||||
the chroot is assembled as "deb [arch=A] B C D" where A is the host's native
|
||||
architecture, B is the I<MIRROR>, C is the given I<SUITE> and D is the
|
||||
components given via B<--components> (defaults to "main"). If a I<MIRROR>
|
||||
option happens to be an existing file, then its contents are written into the
|
||||
chroot's sources.list (if the first I<MIRROR> is a file in one-line format) or
|
||||
into the chroot's sources.list.d directory, named with the extension .list or
|
||||
.sources, depending on whether the file is in one-line or deb822 format,
|
||||
respectively. If I<MIRROR> is C<-> then standard input is pasted into the
|
||||
chroot's sources.list. More than one mirror can be specified and are appended
|
||||
to the chroot's sources.list in the given order. If you specify a https or tor
|
||||
I<MIRROR> and you want the chroot to be able to update itself, don't forget to
|
||||
also install the ca-certificates package, the apt-transport-https package for
|
||||
apt versions less than 1.5 and/or the apt-transport-tor package using the
|
||||
B<--include> option, as necessary.
|
||||
|
||||
All status output is printed to standard error unless B<--logfile> is used to
|
||||
redirect it to a file or B<--quiet> or B<--silent> is used to suppress any
|
||||
output on standard error. Help and version information will be printed to
|
||||
|
@ -6903,6 +6928,11 @@ available and you know your subuid/subgid offset (100000 in this example):
|
|||
$ sudo systemd-nspawn --private-users=100000 \
|
||||
> --directory=./debian-rootfs /bin/bash
|
||||
|
||||
A directory created in B<unshare> mode cannot be removed the normal way.
|
||||
Instead, use something like this:
|
||||
|
||||
$ unshare --map-root-user --map-auto rm -rf ./debian-rootfs
|
||||
|
||||
If this mode is used as the root user, the user namespace is not unshared (but
|
||||
the mount namespace and other still are) and created directories will have
|
||||
correct ownership information. This is also useful in cases where the root user
|
||||
|
@ -6934,10 +6964,13 @@ dpkg-root-support usertag of debian-dpkg@lists.debian.org in the Debian bug
|
|||
tracking system. B<WARNING>: if this option is used carelessly with packages
|
||||
that do not support C<DPKG_ROOT>, this mode can result in undesired changes to
|
||||
the system running B<mmdebstrap> because maintainer-scripts will be run without
|
||||
L<chroot(1)>.
|
||||
L<chroot(1)>. Make sure to run this mode without superuser privileges and/or
|
||||
inside a throw-away chroot enviroment like so:
|
||||
|
||||
=for TODO
|
||||
=item B<qemu>
|
||||
mmdebstrap --variant=apt --include=mmdebstrap \
|
||||
--customize-hook='chroot "$1" mmdebstrap --mode=chrootless
|
||||
--variant=apt unstable chrootless.tar' \
|
||||
--customize-hook='copy-out chrootless.tar .' unstable /dev/null
|
||||
|
||||
=back
|
||||
|
||||
|
@ -6968,7 +7001,9 @@ then this variant will fail because it cannot configure the packages.
|
|||
|
||||
=item B<essential>
|
||||
|
||||
C<Essential:yes> packages.
|
||||
C<Essential:yes> packages. If I<SUITE> is a non-empty string, then only
|
||||
packages from the archive with suite or codename matching I<SUITE> will be
|
||||
considered for selection of C<Essential:yes> packages.
|
||||
|
||||
=item B<apt>
|
||||
|
||||
|
@ -6983,7 +7018,7 @@ ignored without throwing an error.
|
|||
|
||||
=item B<required>, B<minbase>
|
||||
|
||||
The B<essential> set plus all packages with Priority:required and apt.
|
||||
The B<essential> set plus all packages with Priority:required.
|
||||
It is roughly equivalent to running mmdebstrap with
|
||||
|
||||
--variant=essential --include="?priority(required)"
|
||||
|
@ -7240,6 +7275,8 @@ Upon startup, several checks are carried out, like:
|
|||
|
||||
=item * which mode to use and whether prerequisites are met
|
||||
|
||||
=item * do not allow chrootless mode as root (without fakeroot) unless inside a chroot. This check can be disabled using B<--skip=check/chrootless>
|
||||
|
||||
=item * whether the requested architecture can be executed (requires arch-test) using qemu binfmt_misc support. This requires arch-test and can be disabled using B<--skip=check/qemu>
|
||||
|
||||
=item * how the apt sources can be assembled from I<SUITE>, I<MIRROR> and B<--components> and/or from standard input as deb822 or one-line format and whether the required GPG keys exist.
|
||||
|
|
|
@ -30,7 +30,9 @@ B<mmdebstrap-autopkgtest-build-qemu> is a mostly compatible drop-in replacement
|
|||
for L<autopkgtest-build-qemu(1)> with two main differences: Firstly, it uses
|
||||
L<mmdebstrap(1)> instead of L<vmdb2(1)> and thus is able to create QEMU disk
|
||||
images without requiring superuser privileges. Secondly, it uses
|
||||
L<systemd-boot(7)> and thus only supports booting via EFI.
|
||||
L<systemd-boot(7)> and thus only supports booting via EFI. For architectures
|
||||
for which L<autopkgtest-virt-qemu(1)> does not default to EFI booting you must
|
||||
pass B<--boot=efi> when invoking the autopkgtest virt backend.
|
||||
|
||||
=head1 POSITIONAL PARAMETERS
|
||||
|
||||
|
@ -96,9 +98,17 @@ Passes an additional B<--keyring> parameter to B<mmdebstrap>.
|
|||
|
||||
=head1 EXAMPLES
|
||||
|
||||
$ mmdebstrap-autopkgtest-build-qemu --boot=efi stable /path/to/debian-stable-i386.img i386
|
||||
Make sure, that F</path/to/debian-unstable.img> is a path that the unshared
|
||||
user has access to. This can be done by ensuring world-execute permissions on
|
||||
all path components or by creating the image in a world-readable directory like
|
||||
/tmp before copying it into its final location.
|
||||
|
||||
$ mmdebstrap-autopkgtest-build-qemu --boot=efi unstable /path/to/debian-unstable.img
|
||||
$ mmdebstrap-autopkgtest-build-qemu --boot=efi --arch=amd64 unstable /path/to/debian-unstable.img
|
||||
[...]
|
||||
$ autopkgtest mypackage -- qemu --boot=efi --dpkg-architecture=amd64 /path/to/debian-unstable.img
|
||||
|
||||
Make sure to add B<--boot=efi> to both the B<mmdebstrap-autopkgtest-build-qemu>
|
||||
as well as the B<autopkgtest-virt-qemu> invocation.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
|
@ -223,21 +233,31 @@ test "$BOOT" = efi ||
|
|||
case "$ARCHITECTURE" in
|
||||
amd64)
|
||||
EFIIMG=bootx64.efi
|
||||
QEMUARCH=x86_64
|
||||
VMFPKG=ovmf
|
||||
;;
|
||||
arm64)
|
||||
EFIIMG=bootaa64.efi
|
||||
QEMUARCH=aarch64
|
||||
VMFPKG=qemu-efi-aarch64
|
||||
;;
|
||||
armhf)
|
||||
EFIIMG=bootarm.efi
|
||||
QEMUARCH=arm
|
||||
VMFPKG=qemu-efi-arm
|
||||
;;
|
||||
i386)
|
||||
EFIIMG=bootia32.efi
|
||||
QEMUARCH=i386
|
||||
VMFPKG=ovmf-ia32
|
||||
;;
|
||||
riscv64)
|
||||
EFIIMG=bootriscv64.efi
|
||||
QEMUARCH=riscv64
|
||||
VMFPKG=
|
||||
;;
|
||||
*)
|
||||
die "unsupported architecture"
|
||||
die "unsupported architecture: $ARCHITECTURE"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
@ -250,9 +270,17 @@ else
|
|||
test "$(dpkg-query -f '${db:Status-Status}' -W "binutils$GNU_SUFFIX")" = installed ||
|
||||
die "please install binutils$GNU_SUFFIX or binutils-multiarch"
|
||||
fi
|
||||
|
||||
arches=" $(dpkg --print-architecture) $(dpkg --print-foreign-architectures | tr '\n' ' ') "
|
||||
case $arches in
|
||||
*" $ARCHITECTURE "*) : ;; # nothing to do
|
||||
*) die "enable $ARCHITECTURE by running: sudo dpkg --add-architecture $ARCHITECTURE && sudo apt update" ;;
|
||||
esac
|
||||
|
||||
for pkg in autopkgtest dosfstools e2fsprogs fdisk mount mtools passwd "systemd-boot-efi:$ARCHITECTURE" uidmap; do
|
||||
test "$(dpkg-query -f '${db:Status-Status}' -W "$pkg")" = installed ||
|
||||
if [ "$(dpkg-query -f '${db:Status-Status}' -W "$pkg")" != installed ]; then
|
||||
die "please install $pkg"
|
||||
fi
|
||||
done
|
||||
|
||||
BOOTSTUB="/usr/lib/systemd/boot/efi/linux${EFIIMG#boot}.stub"
|
||||
|
@ -278,6 +306,14 @@ rm -f "$IMAGE"
|
|||
unshare -U -r --map-groups=auto chown 0:1 "$IMAGE"
|
||||
chmod 0660 "$IMAGE"
|
||||
|
||||
# Make sure that the unshared user is able to access the file.
|
||||
# Alternatively to using /sbin/mkfs.ext4 could use --format=ext2 which would
|
||||
# add an extra copy operation and come with the limitations of ext2.
|
||||
# Another solution: https://github.com/tytso/e2fsprogs/pull/118
|
||||
if ! mmdebstrap --unshare-helper touch "$IMAGE"; then
|
||||
die "$IMAGE cannot be accessed by the unshared user -- either make all path components up to the image itself world-executable or place the image into a world-readable path like /tmp"
|
||||
fi
|
||||
|
||||
set -- \
|
||||
--mode=unshare \
|
||||
--variant=important \
|
||||
|
@ -387,3 +423,12 @@ start=$((FAT_OFFSET_SECTORS + FAT_SIZE_SECTORS)), type=0FC63DAF-8483-4772-8E79-3
|
|||
EOF
|
||||
|
||||
dd if="$WORKDIR/fat" of="$IMAGE" conv=notrunc,sparse bs=512 "seek=$FAT_OFFSET_SECTORS" status=none
|
||||
|
||||
if test "$(dpkg --print-architecture)" != "$ARCHITECTURE" && test "$(dpkg-query -f '${db:Status-Status}' -W "qemu-system-$QEMUARCH")" != installed; then
|
||||
echo "I: you might need to install a package providing qemu-system-$QEMUARCH to use this image with autopkgtest-virt-qemu" >&2
|
||||
fi
|
||||
if test -n "$VMFPKG" && test "$(dpkg-query -f '${db:Status-Status}' -W "$VMFPKG")" != installed; then
|
||||
echo "I: you might need to install $VMFPKG to use this image with autopkgtest-virt-qemu" >&2
|
||||
fi
|
||||
|
||||
echo "I: don't forget to pass --boot=efi when running autopkgtest-virt-qemu with this image" >&2
|
||||
|
|
|
@ -10,9 +10,6 @@ cleanup() {
|
|||
rv=$?
|
||||
rm -f "$tmpdir/log"
|
||||
[ -e "$tmpdir" ] && rmdir "$tmpdir"
|
||||
if [ -n "${TAIL_PID:-}" ]; then
|
||||
kill "$TAIL_PID"
|
||||
fi
|
||||
if [ -e shared/output.txt ]; then
|
||||
res="$(cat shared/exitstatus.txt)"
|
||||
if [ "$res" != "0" ]; then
|
||||
|
@ -30,8 +27,7 @@ if [ -e shared/output.txt ]; then
|
|||
rm shared/output.txt
|
||||
fi
|
||||
touch shared/output.txt
|
||||
tail -f shared/output.txt &
|
||||
TAIL_PID=$!
|
||||
setpriv --pdeathsig TERM tail -f shared/output.txt &
|
||||
|
||||
# to connect to serial use:
|
||||
# minicom -D 'unix#/tmp/ttyS0'
|
||||
|
@ -40,6 +36,7 @@ TAIL_PID=$!
|
|||
# socat stdin,raw,echo=0,escape=0x11 unix-connect:/tmp/ttyS0
|
||||
ret=0
|
||||
timeout --foreground 40m debvm-run --image="$(realpath "$cachedir")/debian-$DEFAULT_DIST.ext4" -- \
|
||||
-nic none \
|
||||
-m 4G -snapshot \
|
||||
-monitor unix:/tmp/monitor,server,nowait \
|
||||
-serial unix:/tmp/ttyS0,server,nowait \
|
||||
|
|
|
@ -13,6 +13,7 @@ echo "SOURCE_DATE_EPOCH=$SOURCE_DATE_EPOCH"
|
|||
{{ CMD }} --variant={{ VARIANT }} --mode={{ MODE }} \
|
||||
--essential-hook='[ {{ DIST }} = oldstable ] && [ {{ VARIANT }} = - ] && echo _apt:*:100:65534::/nonexistent:/usr/sbin/nologin >> "$1"/etc/passwd || :' \
|
||||
"$(if [ {{ DIST }} = oldstable ]; then echo --merged-usr; else echo --hook-dir=./hooks/merged-usr; fi)" \
|
||||
"$(case {{ DIST }} in oldstable) echo --include=e2fsprogs,mount,tzdata,gcc-9-base;; stable) echo --include=e2fsprogs,mount,tzdata;; *) echo --include=base-files ;; esac )" \
|
||||
{{ DIST }} /tmp/debian-{{ DIST }}-mm.tar {{ MIRROR }}
|
||||
|
||||
mkdir /tmp/debian-{{ DIST }}-mm
|
||||
|
@ -176,11 +177,30 @@ fi
|
|||
|
||||
# since debootstrap 1.0.133 there is no tzdata in the buildd variant and thus
|
||||
# debootstrap creates its own /etc/localtime
|
||||
if [ "{{ VARIANT }}" = "buildd" ]; then
|
||||
if [ "{{ VARIANT }}" = "buildd" ] && [ "{{ DIST }}" != "stable" ] && [ "{{ DIST }}" != "oldstable" ]; then
|
||||
[ "$(readlink /tmp/debian-{{ DIST }}-debootstrap/etc/localtime)" = /usr/share/zoneinfo/UTC ]
|
||||
rm /tmp/debian-{{ DIST }}-debootstrap/etc/localtime
|
||||
fi
|
||||
|
||||
# starting with systemd 255 upstream dropped splitusr support and depending on
|
||||
# the installation order, symlink targets are prefixed with /usr or not
|
||||
# See #1060000 and #1054137
|
||||
case {{ DIST }} in testing|unstable)
|
||||
for f in multi-user.target.wants/e2scrub_reap.service timers.target.wants/apt-daily-upgrade.timer timers.target.wants/apt-daily.timer timers.target.wants/e2scrub_all.timer; do
|
||||
for d in mm debootstrap; do
|
||||
[ -L "/tmp/debian-{{ DIST }}-$d/etc/systemd/system/$f" ] || continue
|
||||
oldlink="$(readlink "/tmp/debian-{{ DIST }}-$d/etc/systemd/system/$f")"
|
||||
case $oldlink in
|
||||
/usr/*) : ;;
|
||||
/*) oldlink="/usr$oldlink" ;;
|
||||
*) echo unexpected >&2; exit 1 ;;
|
||||
esac
|
||||
ln -sf "$oldlink" "/tmp/debian-{{ DIST }}-$d/etc/systemd/system/$f"
|
||||
done
|
||||
done
|
||||
;;
|
||||
esac
|
||||
|
||||
# check if the file content differs
|
||||
diff --unified --no-dereference --recursive /tmp/debian-{{ DIST }}-debootstrap /tmp/debian-{{ DIST }}-mm >&2
|
||||
|
||||
|
@ -189,8 +209,9 @@ diff --unified --no-dereference --recursive /tmp/debian-{{ DIST }}-debootstrap /
|
|||
find /tmp/debian-{{ DIST }}-debootstrap /tmp/debian-{{ DIST }}-mm -type d -print0 | xargs -0 touch --date="@{{ SOURCE_DATE_EPOCH }}"
|
||||
# debootstrap never ran apt -- fixing permissions
|
||||
for d in ./var/lib/apt/lists/partial ./var/cache/apt/archives/partial; do
|
||||
chroot /tmp/debian-{{ DIST }}-debootstrap chmod 0700 $d
|
||||
chroot /tmp/debian-{{ DIST }}-debootstrap chown "$(id -u _apt):root" $d
|
||||
unmergedPATH="$PATH$(if [ "{{ DIST }}" = oldstable ]; then echo :/bin:/sbin; fi)"
|
||||
PATH="$unmergedPATH" chroot /tmp/debian-{{ DIST }}-debootstrap chmod 0700 $d
|
||||
PATH="$unmergedPATH" chroot /tmp/debian-{{ DIST }}-debootstrap chown "$(id -u _apt):root" $d
|
||||
done
|
||||
tar -C /tmp/debian-{{ DIST }}-debootstrap --numeric-owner --sort=name --clamp-mtime --mtime="$(date --utc --date=@{{ SOURCE_DATE_EPOCH }} --iso-8601=seconds)" -cf /tmp/root1.tar .
|
||||
tar -C /tmp/debian-{{ DIST }}-mm --numeric-owner --sort=name --clamp-mtime --mtime="$(date --utc --date=@{{ SOURCE_DATE_EPOCH }} --iso-8601=seconds)" -cf /tmp/root2.tar .
|
||||
|
|
|
@ -8,7 +8,7 @@ trap "rm -f /tmp/chrootless.tar /tmp/root.tar" EXIT INT TERM
|
|||
for INCLUDE in '' 'apt' 'apt,build-essential' 'systemd-sysv'; do
|
||||
for MODE in root chrootless; do
|
||||
{{ CMD }} --mode=$MODE --variant={{ VARIANT }} --hook-dir=./hooks/merged-usr \
|
||||
${INCLUDE:+--include="$INCLUDE"} \
|
||||
${INCLUDE:+--include="$INCLUDE"} --skip=check/chrootless \
|
||||
{{ DIST }} "/tmp/$MODE.tar" {{ MIRROR }}
|
||||
done
|
||||
cmp /tmp/root.tar /tmp/chrootless.tar || diffoscope /tmp/root.tar /tmp/chrootless.tar
|
||||
|
|
|
@ -18,18 +18,23 @@ if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto
|
|||
prefix="runuser -u ${SUDO_USER:-user} --"
|
||||
fi
|
||||
|
||||
MMTARFILTER=
|
||||
[ -x /usr/bin/mmtarfilter ] && MMTARFILTER=/usr/bin/mmtarfilter
|
||||
[ -x ./tarfilter ] && MMTARFILTER=./tarfilter
|
||||
|
||||
# we need --hook-dir=./hooks/merged-usr because usrmerge does not understand
|
||||
# DPKG_ROOT
|
||||
# permissions drwxr-sr-x and extended attributes of ./var/log/journal/ cannot
|
||||
# be preserved under fakeroot
|
||||
# this applies to 'z' lines in files in /usr/lib/tmpfiles.d/
|
||||
for INCLUDE in '' 'apt' 'apt,build-essential' 'systemd-sysv'; do
|
||||
{{ CMD }} --variant={{ VARIANT }} --hook-dir=./hooks/merged-usr \
|
||||
--customize-hook='if [ -d "$1"/var/log/journal ]; then rmdir "$1"/var/log/journal; mkdir --mode=2755 "$1"/var/log/journal; chroot "$1" chown root:systemd-journal /var/log/journal; fi' \
|
||||
--customize-hook="if [ \"$INCLUDE\" = systemd-sysv ]; then for f in var/log/journal etc/credstore etc/credstore.encrypted; do chmod 00755 \"\$1/\$f\"; done; fi" \
|
||||
${INCLUDE:+--include="$INCLUDE"} \
|
||||
{{ DIST }} /tmp/root.tar {{ MIRROR }}
|
||||
{{ DIST }} - {{ MIRROR }} | "$MMTARFILTER" --pax-exclude='*' >/tmp/root.tar
|
||||
$prefix fakeroot {{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} --hook-dir=./hooks/merged-usr \
|
||||
${INCLUDE:+--include="$INCLUDE"} \
|
||||
{{ DIST }} /tmp/chrootless.tar {{ MIRROR }}
|
||||
{{ DIST }} - {{ MIRROR }} | "$MMTARFILTER" > /tmp/chrootless.tar
|
||||
cmp /tmp/root.tar /tmp/chrootless.tar || diffoscope /tmp/root.tar /tmp/chrootless.tar
|
||||
rm /tmp/chrootless.tar /tmp/root.tar
|
||||
done
|
||||
|
|
|
@ -45,7 +45,7 @@ for INCLUDE in '' 'apt' 'systemd-sysv'; do
|
|||
arch-test "$arch" && exit 1
|
||||
{{ CMD }} --mode=chrootless --architecture="$arch" --variant={{ VARIANT }} \
|
||||
--hook-dir=./hooks/merged-usr ${INCLUDE:+--include="$INCLUDE"} \
|
||||
{{ DIST }} "/tmp/chrootless.tar" {{ MIRROR }}
|
||||
--skip=check/chrootless {{ DIST }} "/tmp/chrootless.tar" {{ MIRROR }}
|
||||
# when creating a foreign architecture chroot, the tarballs are not
|
||||
# bit-by-bit identical but contain a few remaining differences:
|
||||
#
|
||||
|
|
|
@ -22,12 +22,17 @@ chroot /tmp/debian-chroot dpkg-query -f '${binary:Package}\n' -W \
|
|||
rm /tmp/expected
|
||||
for cmd in echo cat sed grep; do
|
||||
test -L /tmp/debian-chroot/bin/$cmd
|
||||
test "$(readlink /tmp/debian-chroot/bin/$cmd)" = "/bin/busybox"
|
||||
test "$(readlink /tmp/debian-chroot/bin/$cmd)" = "/usr/bin/busybox"
|
||||
done
|
||||
for cmd in sort tee; do
|
||||
test -L /tmp/debian-chroot/usr/bin/$cmd
|
||||
test "$(readlink /tmp/debian-chroot/usr/bin/$cmd)" = "/bin/busybox"
|
||||
test "$(readlink /tmp/debian-chroot/usr/bin/$cmd)" = "/usr/bin/busybox"
|
||||
done
|
||||
|
||||
# if /bin or /sbin are not symlinks, add /bin and /sbin to PATH
|
||||
if [ ! -L /tmp/debian-chroot/bin ] || [ ! -L /tmp/debian-chroot/sbin ]; then
|
||||
export PATH="$PATH:/sbin:/bin"
|
||||
fi
|
||||
chroot /tmp/debian-chroot echo foobar \
|
||||
| chroot /tmp/debian-chroot cat \
|
||||
| chroot /tmp/debian-chroot sort \
|
||||
|
|
Loading…
Reference in a new issue