def _create_complete_kernel( self, location: Location, system_context: SystemContext, base_cmdline: str, squashfs_device: str, verity_device: str, root_hash: str, target_directory: str, ) -> str: full_cmdline = _setup_kernel_commandline( base_cmdline, squashfs_device, verity_device, root_hash ) kernel_name = _kernel_name(system_context) self._create_efi_kernel(location, system_context, kernel_name, full_cmdline) if self._key and self._cert: debug("Signing EFI kernel.") self._sign_efi_kernel( location, system_context, kernel_name, self._key, self._cert ) kernel_filename = os.path.join(target_directory, os.path.basename(kernel_name)) shutil.copyfile(kernel_name, kernel_filename) return kernel_filename
def _create_complete_kernel( self, location: Location, system_context: SystemContext, cmdline: str, *, kernel_file: str, efi_key: str, efi_cert: str, ): self._create_efi_kernel( location, system_context, cmdline, kernel_file=kernel_file, ) if efi_key and efi_cert: debug("Signing EFI kernel.") location.set_description("Sign EFI kernel") self._execute( location.next_line(), system_context, "sign_efi_binary", kernel_file, key=efi_key, cert=efi_cert, outside=True, keep_unsigned=False, ) trace(f"Validating existence of {kernel_file}.") assert os.path.isfile(kernel_file)
def run( *args: str, work_directory: str = "", check: bool = True, env: typing.Any = os.environ, ## What is a better type for this? ) -> subprocess.CompletedProcess: env["LC_ALL"] = "en_US.UTF-8" cwd = work_directory or None trace('Running: "{}"...'.format('" "'.join(args))) result = subprocess.run( args, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=False, cwd=cwd, ) if result.returncode != 0: debug( f'Command returned with exit code {result.returncode}:\nSTDOUT:\n{result.stdout.decode("utf-8")}\nSTDERR:\n{result.stderr.decode("utf-8")}.' ) if result.returncode == 2 and check: raise subprocess.CalledProcessError( returncode=result.returncode, cmd=args, output=result.stdout, stderr=result.stderr, ) return result
def _copy_efi(src: str, dest: str) -> int: try: efi_path = os.path.join(dest, "EFI") os.makedirs(efi_path, exist_ok=True) trace("Copying bootloader.") efi_src_path = os.path.join(src, "EFI") dirs = [ d for d in os.listdir(efi_src_path) if os.path.isdir(os.path.join(efi_src_path, d)) ] for d in dirs: dest = os.path.join(efi_path, d) trace(f"Copying {os.path.join(efi_src_path, d)} to {dest}") copytree( os.path.join(efi_src_path, d), dest, dirs_exist_ok=True, ) copytree( os.path.join(src, "loader"), os.path.join(dest, "loader"), dirs_exist_ok=True, ) except Exception as e: debug(f"Failed to install EFI: {e}.") return 1 else: debug("Successfully installed EFI") return 0
def run(*args, work_directory: str = "", check: bool = True, env: typing.Dict[str, str] = os.environ) -> subprocess.CompletedProcess: env["LC_ALL"] = "en_US.UTF-8" cwd = work_directory or None trace('Running borg: "{}"...'.format('" "'.join(args))) result = subprocess.run(args, env=env, capture_output=True, check=False, cwd=cwd) if result.returncode != 0: debug("Borg returned with exit code {}:\nSTDOUT:\n{}\nSTDERR:\n{}.". format(result.returncode, result.stdout, result.stderr)) if result.returncode == 2 and check: raise subprocess.CalledProcessError( returncode=result.returncode, cmd=args, output=result.stdout, stderr=result.stderr, ) return result
def __call__(self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any) -> None: """Execute command.""" self._setup(*args, **kwargs) h2('Exporting system "{}".'.format(system_context.system_name)) debug('Running Hooks.') self._run_all_exportcommand_hooks(system_context) verbose('Preparing system for export.') self.prepare_for_export(location, system_context) info('Validating installation for export.') if not self._skip_validation: _validate_installation(location.next_line(), system_context) export_directory \ = self.create_export_directory(system_context) assert export_directory system_context.set_substitution('EXPORT_DIRECTORY', export_directory) verbose('Exporting all data in {}.'.format(export_directory)) self._execute(location.next_line(), system_context, '_export_directory', export_directory, compression=self._repository_compression, compression_level=self._repository_compression_level, repository=self._repository) info('Cleaning up export location.') self.delete_export_directory(export_directory)
def _copy_file(src: str, dest: str, overwrite: bool): file = os.path.basename(src) if not os.path.exists(os.path.join(dest, file)) or overwrite: marker = " [FORCE]" if overwrite else "" debug(f"Copying {src} into {dest}{marker}.") copy2(src, dest) else: debug(f"Skipped copy of {src} into {dest}.")
def __call__( self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any, ) -> None: """Execute command.""" if not os.path.exists( os.path.join(system_context.boot_directory, "vmlinuz")): info("Skipping initrd generation: No vmlinuz in boot directory.") return root_hash = kwargs.get("root_hash", "") vg = system_context.substitution_expanded("DEFAULT_VG", None) image_fs = system_context.substitution_expanded("IMAGE_FS", None) image_device = _device_ify( system_context.substitution_expanded("IMAGE_DEVICE", None)) image_options = system_context.substitution_expanded( "IMAGE_OPTIONS", "") image_name = system_context.substitution_expanded( "CLRM_IMAGE_FILENAME", "") initrd = args[0] staging_area = os.path.join(system_context.cache_directory, "clrm_extra") os.makedirs(staging_area) modules = [ *system_context.substitution_expanded("INITRD_EXTRA_MODULES", "").split(","), "squashfs", *_install_image_file_support(staging_area, image_fs, image_device, image_options, image_name), *_install_lvm_support(staging_area, vg, image_name), *_install_sysroot_setup_support(staging_area), *_install_verity_support(staging_area, system_context, root_hash), *_install_volatile_support(staging_area, system_context), *_install_var_mount_support(staging_area, system_context), *_install_etc_shadow(staging_area, system_context), ] modules = [m for m in modules if m] # Trim empty modules (e.g. added by the substitution) system_context.set_or_append_substitution("INITRD_EXTRA_MODULES", ",".join(modules)) debug( f'INITRD_EXTRA_MODULES is now {system_context.substitution("INITRD_EXTRA_MODULES", "")}.' ) # Create Initrd: run( "/bin/sh", "-c", f'cd "{staging_area}" ; "{self._binary(Binaries.FIND)}" . | "{self._binary(Binaries.CPIO)}" -o -H newc > "{initrd}"', ) assert os.path.exists(initrd)
def __call__(self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any) -> None: """Execute command.""" if system_context.substitution("ROOT_DEVICE") is None: GenerateError("ROOT_DEVICE must be set when creating EFI kernel.", location=location) output = args[0] kernel = kwargs.get("kernel", "") initrd_directory = kwargs.get( "initrd", os.path.join(system_context.boot_directory, "initrd-parts")) initrd_files = _get_initrd_parts(location, initrd_directory) cmdline_input = kwargs.get("commandline", "") osrelease_file = system_context.file_name("/usr/lib/os-release") efistub = system_context.file_name("/usr/lib/systemd/boot/efi/" "linuxx64.efi.stub") debug("{}: Kernel : {}.".format(self.name, kernel)) debug("{}: Initrd : {}.".format(self.name, ", ".join(initrd_files))) debug("{}: cmdline : {}.".format(self.name, cmdline_input)) debug("{}: osrelease: {}.".format(self.name, osrelease_file)) debug("{}: efistub : {}.".format(self.name, efistub)) self._validate_files(kernel, *initrd_files, osrelease_file, efistub) with tempfile.TemporaryDirectory() as tmp: initrd = _create_initrd(tmp, *initrd_files) cmdline = _create_cmdline_file(tmp, cmdline_input) run( self._binary(Binaries.OBJCOPY), "--add-section", ".osrel={}".format(osrelease_file), "--change-section-vma", ".osrel=0x20000", "--add-section", ".cmdline={}".format(cmdline), "--change-section-vma", ".cmdline=0x30000", "--add-section", ".linux={}".format(kernel), "--change-section-vma", ".linux=0x40000", "--add-section", ".initrd={}".format(initrd), "--change-section-vma", ".initrd=0x3000000", efistub, output, ) os.remove(initrd) os.remove(cmdline)
def __call__( self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any, ) -> None: """Execute command.""" output = args[0] kernel = kwargs.get("kernel", "") initrd_directory = kwargs.get( "initrd", os.path.join(system_context.boot_directory, "initrd-parts") ) initrd_files = _get_initrd_parts(location, initrd_directory) cmdline_input = kwargs.get("commandline", "") osrelease_file = system_context.file_name("/usr/lib/os-release") efistub = system_context.file_name( "/usr/lib/systemd/boot/efi/" "linuxx64.efi.stub" ) debug(f"{self.name}: Kernel : {kernel}.") debug(f"{self.name}: Initrd : {initrd_files}.") debug(f"{self.name}: cmdline : {cmdline_input}.") debug(f"{self.name}: osrelease: {osrelease_file}.") debug(f"{self.name}: efistub : {efistub}.") self._validate_files(location, kernel, *initrd_files, osrelease_file, efistub) initrd = _create_initrd(system_context.boot_directory, *initrd_files) cmdline = _create_cmdline_file(system_context.boot_directory, cmdline_input) run( self._binary(Binaries.OBJCOPY), "--add-section", f".osrel={osrelease_file}", "--change-section-vma", ".osrel=0x20000", "--add-section", f".cmdline={cmdline}", "--change-section-vma", ".cmdline=0x30000", "--add-section", f".linux={kernel}", "--change-section-vma", ".linux=0x40000", "--add-section", f".initrd={initrd}", "--change-section-vma", ".initrd=0x3000000", efistub, output, )
def __call__(self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any) -> None: """Execute command.""" user_name = args[0] key_file = args[1] user = UserHelper.user_data(user_name, root_directory=system_context.fs_directory) if user is None: raise GenerateError( '"{}" could not find user "{}".'.format(self.name, user_name), location=location, ) debug('Installing "{}" to user "{}" ({}).'.format( key_file, user_name, user.home)) self._check_or_create_directory( location, system_context, user.home, mode=0o750, user=user.uid, group=user.gid, ) ssh_directory = os.path.join(user.home, ".ssh") self._check_or_create_directory( location, system_context, ssh_directory, mode=0o600, user=user.uid, group=user.gid, ) installed_key_file = os.path.join(ssh_directory, os.path.basename(key_file)) self._execute( location.next_line(), system_context, "copy", key_file, installed_key_file, from_outside=True, ) trace("Copied key.") chown(system_context, user.uid, user.gid, installed_key_file) trace("Ownership adjusted.") chmod(system_context, 0o600, installed_key_file) trace("Mode adjusted.")
def _create_initrd(directory: str, *files: str) -> str: target = os.path.join(directory, "initrd") with open(target, "wb") as target_file: for f in files: with open(f, "rb") as source_file: target_file.write(source_file.read()) # compress the entire initrd: debug("Compressing initrd with gzip") run("gzip", "-9", target) # os.remove(target) ## Gzip kills the uncompressed file! os.rename(f"{target}.gz", target) return target
def __call__(self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any) -> None: """Execute command.""" self._run_hooks(system_context, '_teardown') self._run_hooks(system_context, 'testing') system_context.pickle() self._execute(location, system_context, '_store') debug('Cleaning up everything in "{}".'.format( system_context.scratch_directory)) self._service('btrfs_helper').delete_subvolume_recursive( system_context.scratch_directory)
def _copy_modules( system_context: SystemContext, modules: typing.List[str], modules_dir: str, etc_dir: str, *, kernel_version: str, ): src_top = os.path.join(system_context.file_name("/usr/lib/modules"), kernel_version) target_top = os.path.join(modules_dir, kernel_version) known_modules = _kernel_module_map(src_top) to_load: typing.List[str] = [] to_install: typing.Set[str] = set() debug(f'Installing modules from "{src_top}" into "{target_top}"') for module in modules: m = module.replace("_", "-") if m not in known_modules: info(f"Module {m} not found. Was it built into the kernel?") continue p = known_modules[m] if p not in to_install: to_install.add(p) to_load.append(m) _write_modules_load_file(etc_dir, to_load) if not to_install: return # Install dependencies: dependencies = _parse_module_dependencies(src_top) to_test = to_install for t in to_test: to_install = to_install.union(_module_dependencies(t, dependencies)) for i in to_install: os.makedirs(os.path.dirname(os.path.join(target_top, i)), exist_ok=True) trace(f"Copying module {i}.") trace( f' "{os.path.join(src_top, i)}" => "{os.path.join(target_top, i)}".' ) shutil.copy2(os.path.join(src_top, i), os.path.join(target_top, i))
def _fix_dracut_modules( self, location: Location, system_context: SystemContext, extra: str = "", ): extra = extra.replace(",", " ") extra = extra.replace(" ", " ") extra = extra.strip() if extra: debug(f'Changing MODULES to "{extra}"') self._execute( location.next_line(), system_context, "sed", f"/^MODULES=/ cMODULES=({extra})", "/etc/mkinitcpio.conf", )
def _find_tests(system_context: SystemContext) -> typing.Generator[str, None, None]: """Find tests to run.""" tests_directory = system_context.system_tests_directory debug('Searching for tests in "{}".'.format(tests_directory)) for f in sorted(os.listdir(tests_directory)): test = os.path.join(tests_directory, f) if not os.path.isfile(test): trace('"{}": Not a file, skipping.'.format(test)) continue if not os.access(test, os.X_OK): trace('"{}": Not executable, skipping.'.format(test)) continue info('Found test: "{}"'.format(test)) yield test
def create_qemu_image( image_path: str, *, image_size: int, image_format: str = "qcow2", system_image_file: str, tmp_dir: str, ) -> str: trace(f"Creating image file {image_path}.") with disk.NbdDevice.new_image_file(image_path, image_size, disk_format=image_format) as device: _create_hdd_image(device) debug("mounting data partition for further setup.") with mount.Mount( device.device(3), os.path.join(tmp_dir, "data"), fs_type="btrfs", options="subvolid=0", fallback_cwd=os.getcwd(), ) as data_dir: _setup_btrfs(data_dir) trace("Copying image file") copyfile( system_image_file, os.path.join(data_dir, ".images", os.path.basename(system_image_file)), ) with mount.Mount( device.device(1), os.path.join(tmp_dir, "efi_dest"), options="defaults", fs_type="vfat", ) as efi_dest_mnt: tool.execute_with_system_mounted( lambda e, _: _copy_efi( e, efi_dest_mnt, ), image_file=system_image_file, tmp_dir=tmp_dir, ) return image_path
def create_qemu_image(image_path: str, *, image_size: str, image_format: str = "qcow2", system_name: str, system_version: str = "", repository: str, tempdir: str) -> str: trace("Creating image file {}.".format(image_path)) with disk.NbdDevice.new_image_file(image_path, image_size, disk_format=image_format) as device: _create_hdd_image(device) debug("mounting data partition for further setup.") with mount.Mount( device.device(3), os.path.join(tempdir, "data"), fs_type="btrfs", options="subvolid=0", fallback_cwd=os.getcwd(), ) as data_dir: _setup_btrfs(data_dir) extract_location = os.path.join(data_dir, ".images") verbose("Extracting system image to {}.".format(extract_location)) extracted_version = tool.write_image( system_name, extract_location, repository=repository, version=system_version, ) extracted_image = os.path.join(data_dir, ".images", "clrm_{}".format(extracted_version)) assert os.path.isfile(extracted_image) tool.copy_efi_partition( image_file=extracted_image, efi_device=device.device(1), tempdir=tempdir, kernel_only=False, ) return image_path
def __call__(self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any) -> None: """Execute command.""" h2('Running tests for system "{}"' .format(system_context.system_name), verbosity=2) env = _environment(system_context) for test in _find_tests(system_context): debug('Running test {}...'.format(test)) test_result = run(test, system_context.system_name, env=env, returncode=None, work_directory=system_context.fs_directory) if test_result.returncode == 0: success('Test "{}"'.format(test), verbosity=3) else: report_completed_process(msg, test_result) fail('Test "{}"'.format(test))
def _parse_commandline( *args: str, install_targets: typing.List[InstallTarget]) -> typing.Any: """Parse the command line options.""" parser = ArgumentParser(description="Cleanroom OS image fire starter", prog=args[0]) parser.add_argument("--verbose", action="count", default=0, help="Be verbose") parser.add_argument( "--repository", dest="repository", type=str, action="store", required=True, help="The repository of systems to work with.", ) parser.add_argument(dest="system_name", metavar="<system>", type=str, help="system to install") parser.add_argument( "--system-version", dest="system_version", default="", type=str, help="version of system to install.", ) subparsers = parser.add_subparsers( help="Installation target specifics", dest="subcommand", required=True, ) for it in install_targets: debug( f'Setting up subparser for "{it.name}" with help "{it.help_string}".' ) it.setup_subparser(subparsers.add_parser(it.name, help=it.help_string)) return parser.parse_args(args[1:])
def __call__( self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any, ) -> None: """Execute command.""" self._run_hooks(system_context, "_teardown") self._run_hooks(system_context, "testing") system_context.pickle() self._execute(location, system_context, "_store") debug(f'Cleaning up everything in "{system_context.scratch_directory}".') self._service("btrfs_helper").delete_subvolume_recursive( system_context.scratch_directory )
def __call__(self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any) -> None: """Execute command.""" location.set_description("Strip documentation files") to_remove = [ "/usr/share/doc/*", "/usr/share/gtk-doc/html", "/usr/share/help/*" ] if not os.path.exists(system_context.file_name("/usr/bin/man")): debug("No /usr/bin/man: Removing man pages.") to_remove += ["/usr/share/man/*"] if not os.path.exists(system_context.file_name("/usr/bin/info")): debug("No /usr/bin/info: Removing info pages.") to_remove += ["/usr/share/info/*"] self._execute(location, system_context, "remove", *to_remove, recursive=True, force=True)
def __call__(self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any) -> None: """Execute command.""" location.set_description('Strip documentation files') to_remove = [ '/usr/share/doc/*', '/usr/share/gtk-doc/html', '/usr/share/help/*' ] if not os.path.exists(system_context.file_name('/usr/bin/man')): debug('No /usr/bin/man: Removing man pages.') to_remove += ['/usr/share/man/*'] if not os.path.exists(system_context.file_name('/usr/bin/info')): debug('No /usr/bin/info: Removing info pages.') to_remove += ['/usr/share/info/*'] self._execute(location, system_context, 'remove', *to_remove, recursive=True, force=True)
def __call__(self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any) -> None: """Execute command.""" if system_context.substitution('ROOT_DEVICE') is None: GenerateError('ROOT_DEVICE must be set when creating EFI kernel.', location=location) output = args[0] kernel = kwargs.get('kernel', '') initrd_directory \ = kwargs.get('initrd', os.path.join(system_context.boot_directory, 'initrd-parts')) initrd_files = _get_initrd_parts(location, initrd_directory) cmdline_input = kwargs.get('commandline', '') osrelease_file = system_context.file_name('/usr/lib/os-release') efistub = system_context.file_name('/usr/lib/systemd/boot/efi/' 'linuxx64.efi.stub') debug('{}: Kernel : {}.'.format(self.name, kernel)) debug('{}: Initrd : {}.'.format(self.name, ', '.join(initrd_files))) debug('{}: cmdline : {}.'.format(self.name, cmdline_input)) debug('{}: osrelease: {}.'.format(self.name, osrelease_file)) debug('{}: efistub : {}.'.format(self.name, efistub)) self._validate_files(kernel, *initrd_files, osrelease_file, efistub) with tempfile.TemporaryDirectory() as tmp: initrd = _create_initrd(tmp, *initrd_files) cmdline = _create_cmdline_file(tmp, cmdline_input) run(self._binary(Binaries.OBJCOPY), '--add-section', '.osrel={}'.format(osrelease_file), '--change-section-vma', '.osrel=0x20000', '--add-section', '.cmdline={}'.format(cmdline), '--change-section-vma', '.cmdline=0x30000', '--add-section', '.linux={}'.format(kernel), '--change-section-vma', '.linux=0x40000', '--add-section', '.initrd={}'.format(initrd), '--change-section-vma', '.initrd=0x3000000', efistub, output) os.remove(initrd) os.remove(cmdline)
def create_qemu_image(image_path: str, *, image_size: str, image_format: str = 'qcow2', system_name: str, system_version: str = '', repository: str, tempdir: str) -> str: trace('Creating image file {}.'.format(image_path)) with disk.NbdDevice.new_image_file(image_path, image_size, disk_format=image_format) as device: _create_hdd_image(device) debug('mounting data partition for further setup.') with mount.Mount(device.device(3), os.path.join(tempdir, 'data'), fs_type='btrfs', options='subvolid=0', fallback_cwd=os.getcwd()) as data_dir: _setup_btrfs(data_dir) extract_location = os.path.join(data_dir, '.images') verbose('Extracting system image to {}.' .format(extract_location)) extracted_version \ = tool.write_image(system_name, extract_location, repository=repository, version=system_version) extracted_image \ = os.path.join(data_dir, '.images', 'clrm_{}'.format(extracted_version)) assert os.path.isfile(extracted_image) tool.copy_efi_partition(image_file=extracted_image, efi_device=device.device(1), tempdir=tempdir, kernel_only=False) return image_path
def main(*command_args: str) -> int: known_install_targets: typing.List[InstallTarget] = [ ContainerFilesystemInstallTarget(), CopyInstallTarget(), ImagePartitionInstallTarget(), MountInstallTarget(), PartitionInstallTarget(), QemuImageInstallTarget(), QemuInstallTarget(), TarballInstallTarget(), ] parse_result = _parse_commandline(*command_args, install_targets=known_install_targets) # Set up printing: pr = Printer.instance() pr.set_verbosity(parse_result.verbose) pr.show_verbosity_level() trace(f"Arguments parsed from command line: {parse_result}.") install_target = next(x for x in known_install_targets if x.name == parse_result.subcommand) assert install_target debug(f"Install target {install_target.name} found.") with TemporaryDirectory(prefix=f"fs_{install_target.name}") as tmp_dir: trace(f"Using temporary directory: {tmp_dir}.") image_dir = os.path.join(tmp_dir, "borg") os.makedirs(image_dir) with BorgMount( image_dir, system_name=parse_result.system_name, repository=parse_result.repository, version=parse_result.system_version, ) as image_file: trace(f"Mounted borg directory with image file: {image_file}.") debug( f"Running install target with parse_args={parse_result}, tmp_dir={tmp_dir} and image_file={image_file}." ) result = install_target( parse_result=parse_result, tmp_dir=tmp_dir, image_file=image_file, ) debug(f"Install target done: return code: {result}.") trace("Starting cleanup.") trace(f"Done, leaving with return code {result}.") return result
def _copy_efi(src: str, dest: str, *, include_bootloader: bool = False, overwrite: bool = False) -> int: try: efi_path = os.path.join(dest, "EFI") os.makedirs(efi_path, exist_ok=True) linux_src_path = os.path.join(src, "EFI/Linux") kernels = [ f for f in os.listdir(linux_src_path) if os.path.isfile(os.path.join(linux_src_path, f)) ] kernels_str = '", "'.join(kernels) debug(f'Found kernel(s): "{kernels_str}".') assert len(kernels) == 1 kernel = kernels[0] _copy_file( os.path.join(linux_src_path, kernel), os.path.join(dest, "EFI/Linux"), overwrite=overwrite, ) if include_bootloader: trace("Copying bootloader.") efi_src_path = os.path.join(src, "EFI") dirs = [ d for d in os.listdir(efi_src_path) if d != "Linux" and os.path.isdir(os.path.join(efi_src_path, d)) ] for d in dirs: trace(f"Copying {os.path.join(efi_src_path, d)} to {efi_path}") copytree(os.path.join(efi_src_path, d), efi_path, dirs_exist_ok=True) copytree( os.path.join(src, "loader"), os.path.join(dest, "loader"), dirs_exist_ok=True, ) except Exception as e: debug(f"Failed to install EFI: {e}.") return 1 else: debug("Successfully installed EFI") return 0
def _create_hdd_image(device): verbose('hdd.img created.') partitioner = disk.Partitioner(device) partitioner.repartition([ disk.Partitioner.efi_partition(size='512M'), disk.Partitioner.swap_partition(size='1G', name='swap'), disk.Partitioner.data_partition(name='data')]) verbose('hdd.img repartitioned.') debug('Format EFI partitition.') run('/usr/bin/mkfs.vfat', device.device(1)) debug('Set up swap partitition.') run('/usr/bin/mkswap', device.device(2)) debug('Format data partitition.') run('/usr/bin/mkfs.btrfs', '-L', 'fs_btrfs', device.device(3))
def _create_hdd_image(device): verbose("hdd.img created.") partitioner = disk.Partitioner(device) partitioner.repartition([ disk.Partitioner.efi_partition(size="512M"), disk.Partitioner.swap_partition(size="1G", name="swap"), disk.Partitioner.data_partition(name="data"), ]) verbose("hdd.img repartitioned.") debug("Format EFI partitition.") run("/usr/bin/mkfs.vfat", device.device(1)) debug("Set up swap partitition.") run("/usr/bin/mkswap", device.device(2)) debug("Format data partitition.") run("/usr/bin/mkfs.btrfs", "-L", "fs_btrfs", device.device(3))
def __call__( self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any, ) -> None: """Execute command.""" cert = kwargs.get("efi_cert", "") efi_emulator = kwargs.get("efi_emulator", "") key = kwargs.get("efi_key", "") skip_validation = kwargs.get("skip_validation", False) repository = args[0] repository_compression = kwargs.get("repository_compression", "zstd") repository_compression_level = kwargs.get( "repository_compression_level", 5) usr_only = kwargs.get("usr_only", True) debug_initrd = kwargs.get("debug_initrd", False) h2(f'Exporting system "{system_context.system_name}".') debug("Running Hooks.") self._run_all_exportcommand_hooks(system_context) verbose("Preparing system for export.") self._execute(location.next_line(), system_context, "_write_deploy_info") # Create some extra data: self._create_root_tarball(location, system_context) root_partition = self._create_root_fsimage(location, system_context, usr_only=usr_only) assert root_partition (verity_partition, root_hash) = self._create_rootverity_fsimage( location, system_context, rootfs=root_partition, ) assert root_hash has_kernel = os.path.exists( os.path.join(system_context.boot_directory, "vmlinuz")) if has_kernel: self._create_initrd(location, system_context) self._create_clrm_config_initrd(location, system_context, root_hash, debug=debug_initrd) cmdline = system_context.set_or_append_substitution( "KERNEL_CMDLINE", "systemd.volatile=true rootfstype=squashfs") cmdline = _setup_kernel_commandline(cmdline, root_hash) kernel_file = "" if has_kernel: trace( f'KERNEL_FILENAME: {system_context.substitution("KERNEL_FILENAME", "")}' ) kernel_file = os.path.join( system_context.boot_directory, system_context.substitution_expanded("KERNEL_FILENAME", ""), ) assert kernel_file self._create_complete_kernel( location, system_context, cmdline, kernel_file=kernel_file, efi_key=key, efi_cert=cert, ) efi_partition = os.path.join(system_context.cache_directory, "efi_partition.img") self._create_efi_partition( location, system_context, efi_partition=efi_partition, kernel_file=kernel_file, efi_emulator=efi_emulator, root_hash=root_hash, ) info("Validating installation for export.") if not skip_validation: _validate_installation(location.next_line(), system_context) export_directory = self.create_export_directory(system_context) assert export_directory self.create_image( location, system_context, export_directory, efi_partition=efi_partition, root_partition=root_partition, verity_partition=verity_partition, root_hash=root_hash, ) system_context.set_substitution("EXPORT_DIRECTORY", export_directory) verbose(f"Exporting all data in {export_directory}.") self._execute( location.next_line(), system_context, "_export_directory", export_directory, compression=repository_compression, compression_level=repository_compression_level, repository=repository, ) info("Cleaning up export location.") self.delete_export_directory(export_directory) system_context.set_substitution("EXPORT_DIRECTORY", "")