def __call__(self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any) -> None: """Execute command.""" target = args[0] systemd_directory = "/usr/lib/systemd/system/" target_path = systemd_directory + args[0] if not isfile(system_context, target_path): raise GenerateError( 'Target "{}" does not exist or is no file. ' "Can not use as default target.".format(target)) default = "default.target" default_path = systemd_directory + "default.target" self._execute(location, system_context, "remove", default_path, force=True) self._execute( location.next_line(), system_context, "symlink", target, default, work_directory=systemd_directory, ) system_context.set_substitution("DEFAULT_BOOT_TARGET", target)
def _setup_hooks( self, location: Location, system_context: SystemContext, locales: typing.Sequence[str], ) -> None: if not system_context.substitution("CLRM_LOCALES", ""): location.set_description("run locale-gen") self._add_hook( location, system_context, "export", "run", "/usr/bin/locale-gen", inside=True, ) location.set_description("Remove locale related data.") self._add_hook( location, system_context, "export", "remove", "/usr/share/locale/*", "/etc/locale.gen", "/usr/bin/locale-gen", "/usr/bin/localedef", force=True, recursive=True, ) system_context.set_substitution("CLRM_LOCALES", ",".join(locales))
def __call__(self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any) -> None: """Execute command.""" verity_file = args[0] base_image = kwargs.get("base_image", "") assert base_image result = run(self._binary(Binaries.VERITYSETUP), "format", base_image, verity_file) size_extend(verity_file) root_hash: typing.Optional[str] = None uuid: typing.Optional[str] = None for line in result.stdout.split("\n"): if line.startswith("Root hash:"): root_hash = line[10:].strip() if line.startswith("UUID:"): uuid = line[10:].strip() assert root_hash is not None assert uuid is not None system_context.set_substitution("LAST_DMVERITY_UUID", uuid) system_context.set_substitution("LAST_DMVERITY_ROOTHASH", root_hash)
def __call__( self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any, ) -> None: """Execute command.""" static_hostname = args[0] pretty_hostname = kwargs.get("pretty", static_hostname) if system_context.substitution("HOSTNAME", ""): raise GenerateError("Hostname was already set.", location=location) system_context.set_substitution("HOSTNAME", static_hostname) system_context.set_substitution("PRETTY_HOSTNAME", pretty_hostname) self._execute(location, system_context, "create", "/etc/hostname", static_hostname) self._execute( location.next_line(), system_context, "sed", f'/^PRETTY_HOSTNAME=/ cPRETTY_HOSTNAME="{pretty_hostname}"', "/etc/machine.info", )
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 __call__(self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any) -> None: """Execute command.""" # Enable KMS: self._execute(location, system_context, 'pkg_intel_kms') self._execute(location, system_context, 'pkg_xorg') # Set some kernel parameters: cmdline = system_context.substitution('KERNEL_CMDLINE', '') if cmdline: cmdline += ' ' cmdline += 'intel_iommu=igfx_off i915.fastboot=1' system_context.set_substitution('KERNEL_CMDLINE', cmdline) self._execute(location, system_context, 'pacman', 'libva-intel-driver', 'mesa', 'vulkan-intel', 'xf86-video-intel', 'intel-media-driver') self._execute(location.next_line(), system_context, 'create', '/etc/modprobe.d/i915-guc.conf', 'options i915 enable_guc=3') self._execute(location.next_line(), system_context, 'remove', '/usr/lib/firmware/amdgpu/*', '/usr/lib/firmware/nvidia/*', '/usr/lib/firmware/radeon/*', force=True, recursive=True)
def __call__( self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any, ) -> None: """Execute command.""" old_machine_id = system_context.substitution("MACHINE_ID", "") if old_machine_id: raise GenerateError( f'Machine-id was already set to "{old_machine_id}".', location=location, ) machine_id = args[0] system_context.set_substitution("MACHINE_ID", machine_id) machine_id += "\n" self._execute( location.next_line(), system_context, "create", "/etc/machine-id", machine_id, )
def _setup_hooks(self, location: Location, system_context: SystemContext) -> None: i_gpg_dir = "/usr/lib/pacman/gpg" i_packages = "/var/cache/pacman/pkg/*" location.set_description("cleanup pacman-key files (internal)") self._add_hook( location, system_context, "_teardown", "remove", i_gpg_dir + "/S.*", i_gpg_dir + "/pubring.gpg~", i_gpg_dir + "/secring.gpg*", "/var/log/pacman.log", i_packages, recursive=True, force=True, ) location.set_description("Cleanup pacman-key files (external)") o_gpg_dir = os.path.join(system_context.meta_directory, "pacman/gpg") self._add_hook( location, system_context, "_teardown", "remove", o_gpg_dir + "/S.*", o_gpg_dir + "/pubring.gpg~", o_gpg_dir + "/secring.gpg*", recursive=True, force=True, outside=True, ) location.set_description("Move systemd files into /usr") self._add_hook(location, system_context, "_teardown", "systemd_cleanup") location.set_description("Moving /opt into /usr") self._add_hook(location.next_line(), system_context, "export", "move", "/opt", "/usr") self._add_hook( location, system_context, "export", "symlink", "usr/opt", "opt", work_directory="/", ) location.set_description("Writing package information to FS.") self._add_hook(location.next_line(), system_context, "export", "_pacman_write_package_data") system_context.set_substitution("DISTRO_ID_LIKE", "archlinux")
def __call__( self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any ) -> None: """Execute command.""" system_context.set_substitution(args[0], args[1])
def __call__( self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any, ) -> None: """Execute command.""" variant = kwargs.get("variant", "native") kernel = f"kernel-{variant}" self._execute( location, system_context, "swupd", kernel, "boot-encrypted", ) kernel_version = move_kernel(system_context, variant) update_cmdline(system_context, kernel_version, variant) system_context.set_substitution("KERNEL_VERSION", f"{kernel_version}.{variant}") move_initrds(system_context, kernel_version=kernel_version, variant=variant) # fix up permissions of some files that were just installed: os.chmod( system_context.file_name( "/usr/lib/systemd/system/blk-availability.service"), 0o644, ) os.chmod( system_context.file_name( "/usr/lib/systemd/system/dm-event.service"), 0o644) os.chmod( system_context.file_name( "/usr/lib/systemd/system/dm-event.socket"), 0o644) os.chmod( system_context.file_name( "/usr/lib/systemd/system/lvm2-lvmetad.service"), 0o644, ) os.chmod( system_context.file_name( "/usr/lib/systemd/system/lvm2-lvmetad.socket"), 0o644, ) os.chmod( system_context.file_name( "/usr/lib/systemd/system/[email protected]"), 0o644, )
def __call__(self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any) -> None: """Execute command.""" if system_context.has_substitution('MACHINE_ID'): raise GenerateError('Machine-id was already set.', location=location) machine_id = args[0] system_context.set_substitution('MACHINE_ID', machine_id) machine_id += '\n' self._execute(location.next_line(), system_context, 'create', '/etc/machine-id', machine_id)
def _setup_hooks(self, location: Location, system_context: SystemContext, locales: typing.Sequence[str]) -> None: if not system_context.has_substitution('CLRM_LOCALES'): location.set_description('run locale-gen') self._add_hook(location, system_context, 'export', 'run', '/usr/bin/locale-gen', inside=True) location.set_description('Remove locale related data.') self._add_hook(location, system_context, 'export', 'remove', '/usr/share/locale/*', '/etc/locale.gen', '/usr/bin/locale-gen', '/usr/bin/localedef', force=True, recursive=True) system_context.set_substitution('CLRM_LOCALES', ','.join(locales))
def __call__(self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any) -> None: """Execute command.""" uuid = args[0] cmdline = system_context.substitution('KERNEL_CMDLINE', '') if 'rd.luks.name=' in cmdline: raise GenerateError('rd.luks.name already set.', location=location) if cmdline: cmdline += ' ' cmdline += 'rd.luks.name={}={} rd.luks.options=discard'.format( uuid, args[1]) system_context.set_substitution('KERNEL_CMDLINE', cmdline)
def __call__( self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any, ) -> None: """Execute command.""" kernel = "linux" variant = kwargs.get("variant", "") if variant: kernel = f"{kernel}-{variant}" self._execute( location, system_context, "pacman", "--assume-installed", "initramfs", kernel, ) vmlinuz = os.path.join(system_context.boot_directory, "vmlinuz") lib_modules = system_context.file_name("/usr/lib/modules") module_dirs = [ d for d in os.listdir(lib_modules) if os.path.isdir(os.path.join(lib_modules, d)) and "-arch" in d ] assert len(module_dirs) == 1 kernel_version = module_dirs[0] system_context.set_substitution("KERNEL_VERSION", kernel_version) # New style linux packages that put vmlinuz into /usr/lib/modules: self._execute( location.next_line(), system_context, "move", f"/usr/lib/modules/{kernel_version}/vmlinuz", vmlinuz, to_outside=True, ignore_missing_sources=True, ) assert os.path.isfile(vmlinuz)
def __call__(self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any) -> None: """Execute command.""" if system_context.has_substitution("MACHINE_ID"): raise GenerateError("Machine-id was already set.", location=location) machine_id = args[0] system_context.set_substitution("MACHINE_ID", machine_id) machine_id += "\n" self._execute( location.next_line(), system_context, "create", "/etc/machine-id", machine_id, )
def __call__(self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any) -> None: """Execute command.""" static_hostname = args[0] pretty_hostname = kwargs.get('pretty', static_hostname) if system_context.has_substitution('HOSTNAME'): raise GenerateError('Hostname was already set.', location=location) system_context.set_substitution('HOSTNAME', static_hostname) system_context.set_substitution('PRETTY_HOSTNAME', pretty_hostname) self._execute(location, system_context, 'create', '/etc/hostname', static_hostname) self._execute( location.next_line(), system_context, 'sed', '/^PRETTY_HOSTNAME=/ cPRETTY_HOSTNAME=\"{}\"'.format( pretty_hostname), '/etc/machine.info')
def update_cmdline(system_context: SystemContext, version: str, variant: str): with open( system_context.file_name( f"/usr/lib/kernel/cmdline-{version}.{variant}"), "r") as cmd: clr_cmdline = [ a.strip() for a in cmd.read().split("\n") if a and a != "quiet" ] in_cmdline = [ a for a in system_context.substitution("KERNEL_CMDLINE", "").split(" ") if a ] cmdline = [ *in_cmdline, *clr_cmdline, ] cmdline_str = " ".join([a for a in cmdline if a]) system_context.set_substitution("KERNEL_CMDLINE", cmdline_str)
def __call__(self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any) -> None: """Execute command.""" device = args[0] root_device_key = 'ROOT_DEVICE' dev = system_context.substitution(root_device_key) if dev is not None: raise GenerateError('"{}" root device is already set to "{}".' .format(self.name, dev), location=location) system_context.set_substitution(root_device_key, device) self._write_file(system_context, 'root_device', root_device_key) if ' ' in device: device = '"{}"'.format(device) cmdline = system_context.substitution('KERNEL_CMDLINE', '') cmdline = ' '.join((cmdline, 'root={}'.format(device), 'rootflags=ro')) system_context.set_substitution('KERNEL_CMDLINE', cmdline)
def __call__( self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any, ) -> None: """Execute command.""" ## validate package type: if system_context.substitution("CLRM_PACKAGE_TYPE", ""): raise GenerateError( "Trying to run swupd_init on a system that already has a CLRM_PACKAGE_TYPE defined." ) system_context.set_substitution("CLRM_PACKAGE_TYPE", "swupd") run( self._binary(Binaries.SWUPD), "autoupdate", f"--path={system_context.fs_directory}", "--disable", "--no-progress", returncode=28, ) # Setup update-helper so that swupd os-install will actually work: os.makedirs(system_context.file_name("/usr/bin")) with open(system_context.file_name("/usr/bin/update-helper"), "wb") as fd: fd.write( dedent( """\ #!/usr/bin/sh exit 0 """ ).encode("utf-8") ) os.chmod(system_context.file_name("/usr/bin/update-helper"), 0o755) run( self._binary(Binaries.SWUPD), "os-install", f"--path={system_context.fs_directory}", "--skip-optional", "--no-progress", ) location.set_description("Move systemd files into /usr") self._add_hook(location, system_context, "_teardown", "systemd_cleanup") with open(system_context.file_name("/usr/lib/os-release"), "r") as osr: for l in osr: l = l.strip() if l.startswith("BUILD_ID="): build_id = l[9:] verbose(f"Installed {build_id}.") system_context.set_substitution("DISTRO_VERSION_ID", build_id) system_context.set_substitution("DISTRO_VERSION", build_id) self._execute(location.next_line(), system_context, "create_os_release")
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", "")
def __call__( self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any, ) -> None: """Execute command.""" ## validate package type: if system_context.substitution("CLRM_PACKAGE_TYPE", ""): raise GenerateError( "Trying to run swupd_init on a system that already has a CLRM_PACKAGE_TYPE defined." ) system_context.set_substitution("CLRM_PACKAGE_TYPE", "swupd") system_context.set_substitution("DISTRO_PRETTY_NAME", "Cleanroom - CLR") run( self._binary(Binaries.SWUPD), "autoupdate", f"--path={system_context.fs_directory}", "--disable", "--no-progress", returncode=28, ) # Setup update-helper so that swupd os-install will actually work: os.makedirs(system_context.file_name("/usr/bin")) with open(system_context.file_name("/usr/bin/update-helper"), "wb") as fd: fd.write( dedent("""\ #!/usr/bin/sh exit 0 """).encode("utf-8")) os.chmod(system_context.file_name("/usr/bin/update-helper"), 0o755) run( self._binary(Binaries.SWUPD), "os-install", f"--path={system_context.fs_directory}", "--skip-optional", "--no-progress", ) system_context.set_substitution("INITRD_GENERATOR", "clr") location.set_description("Move systemd files into /usr") self._add_hook(location, system_context, "_teardown", "systemd_cleanup") location.set_description("Setup Clearlinux triggers as hooks") self._add_hook( location, system_context, "export", "run", "/usr/bin/systemd-tmpfiles", "--create", inside=True, ) self._add_hook( location, system_context, "export", "_clr_catalog_trigger", ) self._add_hook( location, system_context, "export", "_clr_fontconfig_trigger", ) self._add_hook( location, system_context, "export", "_clr_glib_schemas_trigger", ) self._add_hook( location, system_context, "export", "_clr_graphviz_dot_trigger", ) self._add_hook( location, system_context, "export", "_clr_hwdb_update_trigger", ) self._add_hook( location, system_context, "export", "_clr_icon_cache_update_trigger", ) self._add_hook( location, system_context, "export", "_clr_ldconfig_trigger", ) self._add_hook( location, system_context, "export", "_clr_locale_archive_trigger", ) self._add_hook( location, system_context, "export", "_clr_mandb_trigger", ) self._add_hook( location, system_context, "export", "_clr_sysusers_trigger", ) self._add_hook( location, system_context, "export", "_clr_dynamic_trust_store_trigger", ) self._add_hook( location, system_context, "export", "_clr_mime_update_trigger", ) with open(system_context.file_name("/usr/lib/os-release"), "r") as osr: for l in osr: l = l.strip() if l.startswith("BUILD_ID="): build_id = l[9:] verbose(f"Installed {build_id}.") system_context.set_substitution("DISTRO_VERSION_ID", build_id) system_context.set_substitution("DISTRO_VERSION", build_id) system_context.set_substitution("DISTRO_ID_LIKE", "clearlinux") system_context.set_substitution( "ROOTFS_PARTLABEL", "root_${TIMESTAMP}-${DISTRO_VERSION_ID}") system_context.set_substitution( "VRTYFS_PARTLABEL", "vrty_${TIMESTAMP}-${DISTRO_VERSION_ID}") system_context.set_substitution( "KERNEL_FILENAME", "${PRETTY_SYSTEM_NAME}_${TIMESTAMP}-${DISTRO_VERSION_ID}.efi", ) system_context.set_substitution( "CLRM_IMAGE_FILENAME", "${PRETTY_SYSTEM_NAME}_${TIMESTAMP}-${DISTRO_VERSION_ID}", ) self._execute(location.next_line(), system_context, "create_os_release")
def __call__( self, location: Location, system_context: SystemContext, *args: typing.Any, **kwargs: typing.Any, ) -> None: """Execute command.""" name = args[0] if not name.endswith(".conf"): name += ".conf" device_id = kwargs.get("device", "disk0") assert not " " in device_id contents = "[Partition]\n" type = kwargs.get("type", "") contents += f"Type={type}\n" label = kwargs.get("label", "") if label: contents += f"Label={label}\n" uuid = kwargs.get("uuid", "") if uuid: contents += f"UUID={uuid}\n" priority = kwargs.get("priority", 0) if priority != 0: contents += f"Priority={priority}\n" weight = kwargs.get("weight", 1000) if weight != 1000: contents += f"Weight={weight}\n" padding_weight = kwargs.get("paddingWeight", 0) if padding_weight != 0: contents += f"PaddingWeight={padding_weight}\n" minSize = kwargs.get("minSize", "") if minSize: contents += f"SizeMinBytes={minSize}\n" maxSize = kwargs.get("maxSize", "") if maxSize: contents += f"SizeMaxBytes={maxSize}\n" minPadding = kwargs.get("minPadding", "") if minPadding: contents += f"PaddingMinBytes={minPadding}\n" maxPadding = kwargs.get("maxPadding", "") if maxPadding: contents += f"PaddingMaxBytes={maxPadding}\n" rel_path = os.path.join( system_context.substitution("DISTRO_ID"), "repart.d", device_id, ) path = os.path.join(system_context.boot_directory, "extra", rel_path,) filename = os.path.join(path, name) trace(f"Creating repart.d file {filename} (relative: {rel_path}).") os.makedirs(path, mode=0o750, exist_ok=True) with open(filename, "wb") as f: f.write(contents.encode("utf-8")) os.chown(filename, 0, 0, follow_symlinks=False) os.chmod(filename, 0o644) # set up substitutions: device_ids = system_context.substitution_expanded( "DEPLOY_DEVICE_IDS", "" ).split() if not device_id in device_ids: device_ids.append(device_id) system_context.set_substitution("DEPLOY_DEVICE_IDS", " ".join(device_ids)) key = f"DEPLOY_{device_id}_REPART_D" repart_path = system_context.substitution_expanded(key, "") if not repart_path: trace(f"Setting {key} to {rel_path}.") system_context.set_substitution(key, rel_path) else: assert rel_path == repart_path if type == "esp" and uuid: system_context.set_substitution("EFI_PARTITION_PARTUUID", uuid)