|
| 1 | +# Copyright (c) 2024 SUSE LLC. All rights reserved. |
| 2 | +# |
| 3 | +# This file is part of kiwi-boxed-build. |
| 4 | +# |
| 5 | +# kiwi-boxed-build is free software: you can redistribute it and/or modify |
| 6 | +# it under the terms of the GNU General Public License as published by |
| 7 | +# the Free Software Foundation, either version 3 of the License, or |
| 8 | +# (at your option) any later version. |
| 9 | +# |
| 10 | +# kiwi-boxed-build is distributed in the hope that it will be useful, |
| 11 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | +# GNU General Public License for more details. |
| 14 | +# |
| 15 | +# You should have received a copy of the GNU General Public License |
| 16 | +# along with kiwi-boxed-build. If not, see <http://www.gnu.org/licenses/> |
| 17 | +# |
| 18 | +import typer |
| 19 | +import itertools |
| 20 | +from pathlib import Path |
| 21 | +from typing import ( |
| 22 | + Annotated, Optional, List, Union, no_type_check |
| 23 | +) |
| 24 | + |
| 25 | +typers = { |
| 26 | + 'boxbuild': typer.Typer( |
| 27 | + add_completion=False, invoke_without_command=True |
| 28 | + ) |
| 29 | +} |
| 30 | + |
| 31 | +system = typers['boxbuild'] |
| 32 | + |
| 33 | + |
| 34 | +@no_type_check |
| 35 | +@system.command( |
| 36 | + context_settings={ |
| 37 | + 'allow_extra_args': True, |
| 38 | + 'ignore_unknown_options': True |
| 39 | + } |
| 40 | +) |
| 41 | +def kiwi( |
| 42 | + ctx: typer.Context |
| 43 | +): |
| 44 | + """ |
| 45 | + List of command parameters as supported by the kiwi-ng |
| 46 | + build command. The information given here is passed |
| 47 | + along to the kiwi-ng system build command running in |
| 48 | + the virtual machine or container. |
| 49 | + """ |
| 50 | + Cli = ctx.obj |
| 51 | + args = ctx.args |
| 52 | + for option in list(set(args)): |
| 53 | + if type(option) is not str or not option.startswith('-'): |
| 54 | + continue |
| 55 | + k: List[Union[str, List]] = [option] |
| 56 | + v = [] |
| 57 | + indexes = [n for n, x in enumerate(args) if x == option] |
| 58 | + if len(indexes) > 1: |
| 59 | + for index in indexes: |
| 60 | + v.append(args[index + 1]) |
| 61 | + for index in sorted(indexes, reverse=True): |
| 62 | + del args[index + 1] |
| 63 | + del args[index] |
| 64 | + k.append(v) |
| 65 | + args += k |
| 66 | + Cli.subcommand_args['boxbuild']['system_build'] = \ |
| 67 | + dict(itertools.zip_longest(*[iter(args)] * 2)) |
| 68 | + Cli.global_args['command'] = 'boxbuild' |
| 69 | + Cli.global_args['system'] = True |
| 70 | + Cli.cli_ok = True |
| 71 | + |
| 72 | + |
| 73 | +@system.callback( |
| 74 | + help='build a system image in a self contained VM or container', |
| 75 | + subcommand_metavar='kiwi [OPTIONS]' |
| 76 | +) |
| 77 | +def boxbuild( |
| 78 | + ctx: typer.Context, |
| 79 | + box: Annotated[ |
| 80 | + Optional[str], typer.Option( |
| 81 | + help='<name> Name of the box to use for the build process.' |
| 82 | + ) |
| 83 | + ] = None, |
| 84 | + list_boxes: Annotated[ |
| 85 | + Optional[bool], typer.Option( |
| 86 | + '--list-boxes', |
| 87 | + help='show available build boxes.' |
| 88 | + ) |
| 89 | + ] = False, |
| 90 | + box_memory: Annotated[ |
| 91 | + Optional[str], typer.Option( |
| 92 | + help='<vmgb> Number of GBs to reserve as main memory ' |
| 93 | + 'for the virtual machine. By default 8GB will be used.' |
| 94 | + ) |
| 95 | + ] = None, |
| 96 | + box_console: Annotated[ |
| 97 | + Optional[str], typer.Option( |
| 98 | + help='<ttyname> Name of console in the kernel settings ' |
| 99 | + 'for the virtual machine. By default set to hvc0.' |
| 100 | + ) |
| 101 | + ] = None, |
| 102 | + box_smp_cpus: Annotated[ |
| 103 | + Optional[int], typer.Option( |
| 104 | + help='<number> Number of CPUs to use in the SMP setup. ' |
| 105 | + 'By default 4 CPUs will be used.' |
| 106 | + ) |
| 107 | + ] = 4, |
| 108 | + box_debug: Annotated[ |
| 109 | + Optional[bool], typer.Option( |
| 110 | + '--box-debug', |
| 111 | + help='In debug mode the started virtual machine will be kept open.' |
| 112 | + ) |
| 113 | + ] = False, |
| 114 | + container: Annotated[ |
| 115 | + Optional[bool], typer.Option( |
| 116 | + '--container', |
| 117 | + help='Build in container instead of a VM. Options related to ' |
| 118 | + 'building in a VM will have no effect.' |
| 119 | + ) |
| 120 | + ] = False, |
| 121 | + kiwi_version: Annotated[ |
| 122 | + Optional[str], typer.Option( |
| 123 | + help='<version> Specify a KIWI version to use for ' |
| 124 | + 'the build. The referenced KIWI will be fetched from ' |
| 125 | + 'pip and replaces the box installed KIWI version. ' |
| 126 | + 'Note: If --no-snapshot is used in combination ' |
| 127 | + 'with this option, the change of the KIWI version will ' |
| 128 | + 'be permanently stored in the used box.' |
| 129 | + ) |
| 130 | + ] = None, |
| 131 | + shared_path: Annotated[ |
| 132 | + Optional[Path], typer.Option( |
| 133 | + help='<path> Optional host path to share with the box. ' |
| 134 | + 'The same path as it is present on the host will also ' |
| 135 | + 'be available inside of the box during build time.' |
| 136 | + ) |
| 137 | + ] = None, |
| 138 | + no_update_check: Annotated[ |
| 139 | + Optional[bool], typer.Option( |
| 140 | + '--no-update-check', |
| 141 | + help='Skip check for available box update. The option ' |
| 142 | + 'has no effect if the selected box does not yet exist ' |
| 143 | + 'on the host.' |
| 144 | + ) |
| 145 | + ] = False, |
| 146 | + no_snapshot: Annotated[ |
| 147 | + Optional[bool], typer.Option( |
| 148 | + '--no-snapshot', |
| 149 | + help='Run box with snapshot mode switched off. This ' |
| 150 | + 'causes the box disk file to be modified by the build ' |
| 151 | + 'process and allows to keep a persistent package cache ' |
| 152 | + 'as part of the box. The option can be used to increase ' |
| 153 | + 'the build performance due to data stored in the box ' |
| 154 | + 'which does not have to be reloaded from the network. ' |
| 155 | + 'On the contrary this option invalidates the immutable ' |
| 156 | + 'box attribute and should be used with care. On update ' |
| 157 | + 'of the box all data stored will be wiped. To prevent ' |
| 158 | + 'this combine the option with the --no-update-check option.' |
| 159 | + ) |
| 160 | + ] = False, |
| 161 | + no_accel: Annotated[ |
| 162 | + Optional[bool], typer.Option( |
| 163 | + '--no-accel', |
| 164 | + help='Run box without hardware acceleration. By default ' |
| 165 | + 'KVM acceleration is activated' |
| 166 | + ) |
| 167 | + ] = False, |
| 168 | + qemu_9p_sharing: Annotated[ |
| 169 | + Optional[bool], typer.Option( |
| 170 | + '--9p-sharing', |
| 171 | + help='Select 9p backend to use for sharing data ' |
| 172 | + 'between the host and the box.' |
| 173 | + ) |
| 174 | + ] = False, |
| 175 | + virtiofs_sharing: Annotated[ |
| 176 | + Optional[bool], typer.Option( |
| 177 | + '--virtiofs-sharing', |
| 178 | + help='Select virtiofsd backend to use for sharing data ' |
| 179 | + 'between the host and the box.' |
| 180 | + ) |
| 181 | + ] = False, |
| 182 | + sshfs_sharing: Annotated[ |
| 183 | + Optional[bool], typer.Option( |
| 184 | + '--sshfs-sharing', |
| 185 | + help='Select sshfs backend to use for sharing data ' |
| 186 | + 'between the host and the box.' |
| 187 | + ) |
| 188 | + ] = False, |
| 189 | + ssh_key: Annotated[ |
| 190 | + Optional[str], typer.Option( |
| 191 | + help='<name> Name of ssh key to authorize for ' |
| 192 | + 'connection. By default id_rsa is used.' |
| 193 | + ) |
| 194 | + ] = 'id_rsa', |
| 195 | + ssh_port: Annotated[ |
| 196 | + Optional[int], typer.Option( |
| 197 | + help='<port> Port number to use to forward the ' |
| 198 | + 'guest SSH port to the host By default 10022 is used.' |
| 199 | + ) |
| 200 | + ] = 10022, |
| 201 | + x86_64: Annotated[ |
| 202 | + Optional[bool], typer.Option( |
| 203 | + '--x86_64', |
| 204 | + help='Select box for the x86_64 architecture. If no ' |
| 205 | + 'architecture is selected the host architecture is ' |
| 206 | + 'used for selecting the box. The selected box ' |
| 207 | + 'architecture also specifies the target architecture ' |
| 208 | + 'for the image build with that box.' |
| 209 | + ) |
| 210 | + ] = False, |
| 211 | + aarch64: Annotated[ |
| 212 | + Optional[bool], typer.Option( |
| 213 | + '--aarch64', |
| 214 | + help='Select box for the aarch64 architecture. If no ' |
| 215 | + 'architecture is selected the host architecture is ' |
| 216 | + 'used for selecting the box. The selected box ' |
| 217 | + 'architecture also specifies the target architecture ' |
| 218 | + 'for the image build with that box.' |
| 219 | + ) |
| 220 | + ] = False, |
| 221 | + machine: Annotated[ |
| 222 | + Optional[str], typer.Option( |
| 223 | + help='<qemu_machine> Machine name used ' |
| 224 | + 'by QEMU. By default no specific value is used here ' |
| 225 | + 'and qemu selects its default machine type. For cross ' |
| 226 | + 'arch builds or for system architectures for which ' |
| 227 | + 'QEMU defines no default like for Arm, it is required ' |
| 228 | + 'to specify a machine name. If you do not care about ' |
| 229 | + 'reproducing the idiosyncrasies of a particular bit ' |
| 230 | + 'of hardware, the best option is to use the virt ' |
| 231 | + 'machine type.' |
| 232 | + ) |
| 233 | + ] = None, |
| 234 | + cpu: Annotated[ |
| 235 | + Optional[str], typer.Option( |
| 236 | + help='<qemu_cpu> CPU type used by QEMU. By default ' |
| 237 | + 'the host CPU type is used which is only a good ' |
| 238 | + 'selection if the host and the selected box are from ' |
| 239 | + 'the same architecture. On cross arch builds it is ' |
| 240 | + 'required to specify the CPU emulation the box should use' |
| 241 | + ) |
| 242 | + ] = None |
| 243 | +): |
| 244 | + Cli = ctx.obj |
| 245 | + Cli.subcommand_args['boxbuild'] = { |
| 246 | + '--box': box, |
| 247 | + '--list-boxes': list_boxes, |
| 248 | + '--box-memory': box_memory, |
| 249 | + '--box-console': box_console, |
| 250 | + '--box-smp-cpus': f'{box_smp_cpus}', |
| 251 | + '--box-debug': box_debug, |
| 252 | + '--container': container, |
| 253 | + '--kiwi-version': kiwi_version, |
| 254 | + '--shared-path': shared_path, |
| 255 | + '--no-update-check': no_update_check, |
| 256 | + '--no-snapshot': no_snapshot, |
| 257 | + '--no-accel': no_accel, |
| 258 | + '--9p-sharing': qemu_9p_sharing, |
| 259 | + '--virtiofs-sharing': virtiofs_sharing, |
| 260 | + '--sshfs-sharing': sshfs_sharing, |
| 261 | + '--ssh-key': ssh_key, |
| 262 | + '--ssh-port': f'{ssh_port}', |
| 263 | + '--x86_64': x86_64, |
| 264 | + '--aarch64': aarch64, |
| 265 | + '--machine': machine, |
| 266 | + '--cpu': cpu, |
| 267 | + 'help': False |
| 268 | + } |
| 269 | + Cli.global_args['command'] = 'boxbuild' |
| 270 | + Cli.global_args['system'] = True |
| 271 | + Cli.cli_ok = True |
0 commit comments