summaryrefslogtreecommitdiffstats
path: root/bin/sbuild-qemu-create
diff options
context:
space:
mode:
Diffstat (limited to 'bin/sbuild-qemu-create')
-rwxr-xr-xbin/sbuild-qemu-create234
1 files changed, 234 insertions, 0 deletions
diff --git a/bin/sbuild-qemu-create b/bin/sbuild-qemu-create
new file mode 100755
index 0000000..ca59404
--- /dev/null
+++ b/bin/sbuild-qemu-create
@@ -0,0 +1,234 @@
+#!/usr/bin/python3
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright © 2020-2024 Christian Kastner <ckk@debian.org>
+# 2024 Johannes Schauer Marin Rodrigues <josch@debian.org>
+#
+# 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/>.
+#
+#######################################################################
+
+
+import argparse
+import os
+import subprocess
+import sys
+import textwrap
+
+
+SUPPORTED_ARCHS = [
+ 'amd64',
+ 'arm64',
+ 'armhf',
+ 'i386',
+ 'ppc64el',
+]
+
+DEFAULT_ARCH = subprocess.check_output(
+ ['dpkg', '--print-architecture'],
+ text=True,
+).strip()
+
+
+def gen_sourceslist(mirror, dist, components, with_bpo=False):
+ """Generate a sources.list file for the VM.
+
+ If distribution ends with '-backports', then its base distribution will
+ automatically be added.
+
+ If distribution is 'experimental', then the 'unstable' distribution will
+ automatically be added.
+ """
+ sl = textwrap.dedent(
+ f"""\
+ deb {mirror} {dist} {' '.join(components)}
+ deb-src {mirror} {dist} {' '.join(components)}
+ """)
+ if dist == 'experimental':
+ sl += textwrap.dedent(
+ f"""
+ deb {mirror} unstable {' '.join(components)}
+ deb-src {mirror} unstable {' '.join(components)}
+ """)
+ elif dist.endswith('-backports'):
+ sl += textwrap.dedent(
+ f"""
+ deb {mirror} {dist[:-10]} {' '.join(components)}
+ deb-src {mirror} {dist[:-10]} {' '.join(components)}
+ """)
+ return sl
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ description="Builds images for use with qemu-sbuild and autopkgtest.",
+ epilog="Note that qemu-sbuild-create is just a simple wrapper around "
+ "autopkgtest-build-qemu(1) that automates a few additional "
+ "steps commonly performed with package-building images.",
+ )
+ parser.add_argument(
+ '--arch',
+ action='store',
+ default=DEFAULT_ARCH,
+ help="Architecture to use. Default is the host architecture. "
+ "Currently supported architectures are: "
+ f"{', '.join(SUPPORTED_ARCHS)}.",
+ )
+ parser.add_argument(
+ '--install-packages',
+ action='store',
+ help="Comma-separated list of additional packages to install in the "
+ "image using 'apt-get install' from within the image.",
+ )
+ parser.add_argument(
+ '--extra-deb',
+ action='append',
+ help="Package file (.deb) from the local filesystem to install. Can "
+ "be specified more than once.",
+ )
+ parser.add_argument(
+ '--components',
+ action='store',
+ default='main',
+ help="Comma-separated list of components to use with sources.list "
+ "entries. Default: main.",
+ )
+ # Not yet merged into autopkgtest, see #973457
+ # parser.add_argument('--variant', action='store')
+ parser.add_argument(
+ '--skel',
+ type=str,
+ action='store',
+ help="Skeleton directory to use for /root.",
+ )
+ parser.add_argument(
+ '--authorized-keys',
+ metavar='FILE',
+ action='store',
+ help="Install this file as /root/.ssh/authorized_keys within the "
+ "guest. This will automatically install the 'openssh-server' "
+ "package. This supersedes any copying of this file by the "
+ "--skel option.",
+ )
+ parser.add_argument(
+ '--size',
+ type=str,
+ action='store',
+ default='10G',
+ help="Image size to use. Note that the images are in qcow2 format, so "
+ "they won't consume that space right away. Default: 10G.",
+ )
+ parser.add_argument(
+ '-o', '--out-file',
+ action='store',
+ help="Output filename. If not supplied, then "
+ "DIST-autopkgtest-ARCH.img will be used.",
+ )
+ parser.add_argument(
+ '--noexec',
+ action='store_true',
+ help="Don't actually do anything. Just print the autopkgtest-build-"
+ "qemu(1) command string that would be executed, and then exit.",
+ )
+ parser.add_argument(
+ '--boot',
+ choices=['auto', 'bios', 'efi', 'ieee1275', 'none'],
+ default='auto',
+ help="How the image should boot. Default is BIOS on amd64 and i386, "
+ "EFI on arm64 and armhf, and IEEE1275 on ppc64el.",
+ )
+ parser.add_argument(
+ 'distribution',
+ action='store',
+ help="The distribution to debootstrap.",
+ )
+ parser.add_argument(
+ 'mirror',
+ action='store',
+ help="The mirror to use for the installation. Note that the mirror "
+ "will also be used for the sources.list file in the VM.",
+ )
+ parsed = parser.parse_args()
+
+ # Internal args
+ if parsed.arch not in SUPPORTED_ARCHS:
+ print(
+ f"Unsupported architecture: {parsed.arch}",
+ file=sys.stderr,
+ )
+ sys.exit(1)
+ if parsed.out_file:
+ out_file = parsed.out_file
+ else:
+ out_file = f"{parsed.distribution}-autopkgtest-{parsed.arch}.img"
+ components = parsed.components.split(',')
+
+ # We can only pass arguments to the other tools via the environment
+ #
+ # Args consumed by the modscript
+ if parsed.skel:
+ os.environ['SQC_SKEL'] = parsed.skel
+ print('export SQC_SKEL=' + os.environ['SQC_SKEL'])
+ if parsed.authorized_keys:
+ os.environ['SQC_AUTH_KEYS'] = parsed.authorized_keys
+ print('export SQC_AUTH_KEYS=' + os.environ['SQC_AUTH_KEYS'])
+ if parsed.extra_deb:
+ extra_debs = ' '.join(parsed.extra_deb)
+ os.environ['SQC_EXTRA_DEBS'] = extra_debs
+ print('export SQC_EXTRA_DEBS=' + extra_debs)
+ if parsed.install_packages:
+ install_packages = parsed.install_packages.replace(',', ' ')
+ os.environ['SQC_INSTALL_PACKAGES'] = install_packages
+ print('export SQC_INSTALL_PACKAGES=' + install_packages)
+ # Args consumed by autopkgtest-build-qemu
+ os.environ['AUTOPKGTEST_APT_SOURCES'] = gen_sourceslist(
+ parsed.mirror,
+ parsed.distribution,
+ components,
+ )
+ print('sources.list (via export AUTOPKGTEST_APT_SOURCES)\n------------')
+ print(os.environ['AUTOPKGTEST_APT_SOURCES'])
+
+ #if parsed.variant:
+ # args += ['--variant', parsed.variant]
+ dist = parsed.distribution
+ if dist.endswith('-backports'):
+ dist = dist[:-len('-backports')]
+ elif dist == 'experimental':
+ dist = 'unstable'
+
+ args = [
+ 'autopkgtest-build-qemu',
+ '--architecture', parsed.arch,
+ '--mirror', parsed.mirror,
+ '--size', parsed.size,
+ '--script', '/usr/share/sbuild/sbuild-qemu-create-modscript',
+ '--boot', parsed.boot,
+ dist,
+ out_file,
+ ]
+
+ if os.getuid() != 0:
+ print('Must be root to use this.', file=sys.stderr)
+ sys.exit(1)
+ os.umask(22)
+
+ print(' '.join(str(a) for a in args))
+ if not parsed.noexec:
+ os.execvp(args[0], args)
+
+
+if __name__ == '__main__':
+ main()