File: sbuild-qemu-create

package info (click to toggle)
sbuild 0.81.2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, sid
  • size: 1,756 kB
  • sloc: perl: 15,954; sh: 1,413; sql: 797; python: 401; makefile: 306; lisp: 304
file content (218 lines) | stat: -rwxr-xr-x 7,031 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
#!/usr/bin/python3
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Copyright © 2020      Christian Kastner <ckk@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 platform
import sys
import textwrap


SUPPORTED_ARCHS = {
    'x86_64': 'amd64',
    'i386': 'i386'
}


MACHINE = platform.machine()
try:
    ARCH = SUPPORTED_ARCHS[MACHINE]
except KeyError as e:
    print(f"Unsupported machine type {MACHINE}", file=sys.stderr)
    sys.exit(1)
OUT_FILE = '<dist>-autopkgtest-<arch>.img'
MOD_SCRIPT = '/usr/share/sbuild/sbuild-qemu-create-modscript'


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=ARCH,
        help="Architecture to use. Default is the host architecture. "
             "Currently supported architectures are: "
            f"{', '.join(SUPPORTED_ARCHS.values())}.",
    )
    parser.add_argument(
        '--install-packages',
        action='store',
        help="Comma-separated list of additional packages to install in the "
             "image using 'apt-get install'.",
    )
    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(
        '--size',
        type=str,
        action='store',
        default='10G',
        help="VM 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',
        default=OUT_FILE,
        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(
        '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. See "
             "MIRROR below.",
    )
    parsed = parser.parse_args()

    # Internal args
    if parsed.arch not in SUPPORTED_ARCHS.values():
        print(
            f"Unsupported architecture: {parsed.arch}",
            file=sys.stderr,
        )
        sys.exit(1)
    if parsed.out_file == OUT_FILE:
        # Default unchanged - peplace template with instantiated name
        out_file = f"{parsed.distribution}-autopkgtest-{parsed.arch}.img"
    else:
        out_file = parsed.out_file
    components = parsed.components.split(',')

    # Args that *may* be consumed by modscript (if supplied)
    if parsed.skel:
        os.environ['QSC_SKEL'] = parsed.skel
        print('export QSC_SKEL=' + os.environ['QSC_SKEL'])
    if parsed.extra_deb:
        extra_debs = ' '.join(parsed.extra_deb)
        os.environ['QSC_EXTRA_DEBS'] = extra_debs
        print('export QSC_EXTRA_DEBS=' + extra_debs)
    if parsed.install_packages:
        install_packages = parsed.install_packages.replace(',', ' ')
        os.environ['QSC_INSTALL_PACKAGES'] = install_packages
        print('export QSC_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'])

    args = [
        'autopkgtest-build-qemu',
	'--architecture',           parsed.arch,
        '--mirror',                 parsed.mirror,
        '--size',                   parsed.size,
        '--script',                 MOD_SCRIPT,
    ]
    #if parsed.variant:
    #    args += ['--variant', parsed.variant]
    dist = parsed.distribution
    if dist.endswith('-backports'):
        dist = dist[:-10]
    elif dist == 'experimental':
        dist = 'unstable'
    args += [
        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()