Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ no_color = "0.2.0"
poly_l10n = "0.0.6"
derivative = "2.2.0"
parking_lot = "0.12.3"
file-guard = "0.2.0"

# [dependencies.os-detect]
# git = "https://github.com/FyraLabs/distinst"
Expand Down
1 change: 1 addition & 0 deletions po/en-US/readymade.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,5 @@ stage-grub1 = Generating stage 1 grub.cfg in ESP...
stage-grub2 = Generating stage 2 grub.cfg in /boot/grub2/grub.cfg...
stage-biosgrub = Installing BIOS Grub2
stage-kernel = Reinstalling kernels
stage-recovery = Setting up recovery environment
stage-selinux = Setting SELinux labels
8 changes: 7 additions & 1 deletion po/es/readymade.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,10 @@ page-installation = Instalación
page-installation-progress = Instalando sistema base...
page-installationtype = Tipo de Instalación
page-installationtype-chromebook = Chromebook

unknown-os = SO Desconocido
page-installationtype-tpm = Habilitar TPM
parttype-esp = Partición de sistema EFI ({ $path })
parttype-home = Información de usuario
parttype-other = Punto de montaje personalizado
page-welcome = Bienvenido a { $distro }
page-installationtype-encrypt = Habilitar encriptación de disco
10 changes: 5 additions & 5 deletions po/fr/readymade.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
next = Suivant
unknown-os = OS inconnu
parttype-root = Racine du système de fichiers ({ $path })
parttype-esp = Partition EFI système ({ $path })
parttype-esp = Partition système EFI ({ $path })
parttype-home = Données utilisateur ({ $path })
parttype-var = Données variables ({ $path })
page-welcome = Bienvenue dans { $distro }
Expand Down Expand Up @@ -45,15 +45,15 @@ page-installationtype-chromebook = Chromebook
page-installationtype-custom = Personnalisée
dialog-installtype-encrypt = Chiffrement du disque
dialog-installtype-password = Mot de passe
dialog-installtype-repeat = Saisissez le mot de passe à nouveau
dialog-installtype-repeat = Saisissez à nouveau le mot de passe
dialog-installtype-cancel = Annuler
dialog-installtype-confirm = Confirmer
installtype-edit-mp = Modifier le point de montage
installtype-rm-mp = Supprimer le point de montage
dialog-mp-part = Partition
dialog-mp-at = Monter sur
dialog-mp-opts = Options de montage
installtype-parttool = Sélectionnez votre outil de partitionnement
installtype-parttool = Sélectionner votre outil de partitionnement
stage-extracting = Extraction des fichiers
stage-copying = Copie des fichiers
stage-initramfs = Régénération de l'initramfs
Expand All @@ -73,9 +73,9 @@ page-installationtype-dual = Double démarrage
stage-grub2 = Génération du fichier grub.cfg d'étape 2 dans /boot/grub2/grub.cfg...
dialog-installtype-encrypt-desc =
Veuillez définir le mot de passe de chiffrement du disque.
Si vous perdez ce mot de passe, vos données ne seront pas récupérables.
Si vous perdez ce mot de passe, vos données ne pourront pas être récupérées.
stage-grub = Génération des valeurs système par défaut pour GRUB
stage-selinux = Définition des étiquettes SELinux
stage-selinux = Ajout des étiquettes SELinux
page-confirmation-problem-device-mounted = { $dev } est monté sur { $mountpoint }. Démontez-le pour continuer.
page-confirmation-problem-devblkopen =
Le périphérique de blocs <tt>{ $dev }</tt> est utilisé par les processus suivants :
Expand Down
15 changes: 10 additions & 5 deletions po/ru/readymade.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ parttype-home = Домашняя директория пользователя (
parttype-var = Переменные данные ({ $path })
parttype-other = Пользовательская точка монтирования раздела
page-welcome = Добро пожаловать в { $distro }
page-welcome-desc = Либо попробуйте { $distro } из этой программы установки, либо начните установку сейчас. Вы всегда можете вернуться к этому экрану, выбрав в меню приложение «Installer».
page-welcome-desc = Вы можете попробовать { $distro }, или начать установку уже сейчас.
page-welcome-try = Попробовать
page-welcome-install = Установить
page-failure = Сбой установки
Expand All @@ -35,11 +35,11 @@ page-installation-help = Нужна помощь?
page-installation-help-desc = Задайте вопрос в одном из наших чатов!
page-installation-contrib = Внести вклад в { $distro }
page-installation-contrib-desc = Узнайте, как пожертвовать своим временем, деньгами или оборудованием.
page-installation-progress = Установка базовой системы...
page-installation-progress = Установка базовых системных пакетов...
page-installcustom = Пользовательская установка
page-installcustom-title = Разделы и точки монтирования
page-installcustom-desc = { $num } правил(а)
page-installcustom-tool = Открыть дисковую утилиту
page-installcustom-tool = Открыть утилиту разметки
page-installcustom-add = Добавить новое правило
page-installationtype = Тип установки
page-installationtype-entire = Весь диск
Expand All @@ -61,7 +61,7 @@ installtype-rm-mp = Удалить точку монтирования
dialog-mp-part = Раздел
dialog-mp-at = Монтировать на
dialog-mp-opts = Настройки монтирования
installtype-parttool = Выберите вашу дисковую утилиту
installtype-parttool = Выберите свою утилиту разметки
stage-extracting = Распаковка файлов
stage-copying = Копирование файлов
stage-mkpart = Создание разделов и копирование файлов
Expand All @@ -70,5 +70,10 @@ stage-grub = Генерация системных настроек grub по у
stage-grub1 = Генерация stage 1 grub.cfg на ESP...
stage-grub2 = Генерация stage 2 grub.cfg в /boot/grub2/grub.cfg...
stage-biosgrub = Установка BIOS Grub2
stage-kernel = Повторная установка ядер
stage-kernel = Переустановка ядер
stage-selinux = Установка политик SELinux
page-confirmation-problem-devblkopen =
Накопитель <tt>{ $dev }</tt> уже используется следующими процессами:
<tt>{ $pids }</tt>
Данные процессы должны быть остановлены для дальнейшей работы установщика.
page-confirmation-problem-device-mounted = { $dev } уже смонтирован в { $mountpoint }. Размонтируйте чтобы продолжить.
36 changes: 25 additions & 11 deletions src/backend/install.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use file_guard::Lock;
use ipc_channel::ipc::{IpcError, IpcOneShotServer, IpcSender};
use parking_lot::Mutex;
use serde::{Deserialize, Serialize};
use std::{
io::Write,
os::unix::process::CommandExt,
path::{Path, PathBuf},
process::{Command, Stdio},
sync::OnceLock,
Expand Down Expand Up @@ -818,17 +820,29 @@ impl FinalInstallationState {
["--key-file", keyfile_path]
});

let repart_cmd = Command::new("systemd-repart")
.args(["--dry-run", if dry_run { "yes" } else { "no" }])
.args(["--definitions", cfgdir.to_str().unwrap()])
.args(["--empty", "force", "--offline", "false", "--json", "pretty"])
.args(["--copy-source", &copy_source].iter().filter(|_| !is_bootc))
.args(arg_keyfile.iter().flatten())
.arg(blockdev)
.stdout(Stdio::piped())
.stderr(Stdio::inherit())
.output()
.context("can't run systemd-repart")?;
// Scope to ensure device and lock live long enough for the command
let repart_cmd = {
// lock device
let mut device = std::fs::OpenOptions::new()
.read(true)
.write(true)
.open(blockdev)
.context("Failed to open block device")?;
// We are locking the device so that repart doesn't fail due to device busy
// The lock is held in this scope
let mut _lock = file_guard::lock(&mut device, Lock::Exclusive, 0, 1)?;
Command::new("systemd-repart")
.args(["--dry-run", if dry_run { "yes" } else { "no" }])
.args(["--definitions", cfgdir.to_str().unwrap()])
.args(["--empty", "force", "--offline", "false", "--json", "pretty"])
.args(["--copy-source", &copy_source].iter().filter(|_| !is_bootc))
.args(arg_keyfile.iter().flatten())
.arg(blockdev)
.stdout(Stdio::piped())
.stderr(Stdio::inherit())
.output()
.context("can't run systemd-repart")?
};

if !repart_cmd.status.success() {
bail!(
Expand Down
47 changes: 44 additions & 3 deletions src/backend/postinstall/reinstall_kernel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,29 @@ pub struct ReinstallKernel;
impl PostInstallModule for ReinstallKernel {
fn run(&self, _context: &Context) -> Result<()> {
let kernel_vers = std::fs::read_dir("/lib/modules")?
.map(|entry| entry.unwrap().file_name())
.filter_map(|entry| entry.ok().map(|e| e.file_name()))
.collect_vec();

tracing::info!(?kernel_vers, "Kernel versions found");

// We're gonna just install the first kernel we find, so let's do that
let kver = kernel_vers.first().unwrap().to_str().unwrap();
let kver = kernel_vers
.first()
.ok_or_else(|| color_eyre::eyre::eyre!("No kernel versions found in /lib/modules"))?
.to_str()
.ok_or_else(|| color_eyre::eyre::eyre!("Kernel version filename is not valid UTF-8"))?;

// install kernel
let vmlinuz_path = format!("/lib/modules/{kver}/vmlinuz");
if !std::path::Path::new(&vmlinuz_path).exists() {
bail!("Kernel version {kver} does not have a vmlinuz file at {vmlinuz_path}");
}

stage!(kernel {
let kernel_install_cmd_status = Command::new("kernel-install")
.arg("add")
.arg(kver)
.arg(format!("/lib/modules/{kver}/vmlinuz"))
.arg(&vmlinuz_path)
.arg("--verbose")
.status()?;

Expand All @@ -37,6 +45,39 @@ impl PostInstallModule for ReinstallKernel {
}
});

stage!(recovery {
// copy to /boot/vmlinuz-recovery
let recovery_vmlinuz_path = "/boot/vmlinuz-recovery".to_owned();
if std::path::Path::new(&recovery_vmlinuz_path).exists() {
tracing::warn!("Recovery kernel already exists at {recovery_vmlinuz_path}, skipping copy");
} else {
std::fs::copy(&vmlinuz_path, &recovery_vmlinuz_path)
.map_err(|e| color_eyre::eyre::eyre!(e))?;
}

// create a recovery initramfs
let recovery_initramfs_path = "/boot/initramfs-recovery.img".to_owned();

let recovery_dracut = Command::new("dracut")
.arg("--force")
.arg("--add")
.arg("dmsquash-live overlayfs rescue")
.arg("--no-hostonly")
.arg("--no-uefi")
.arg("--kver")
.arg(kver)
.arg(&recovery_initramfs_path)
.status()?;
if !recovery_dracut.success() {
bail!(
"dracut failed with exit code {:?}",
recovery_dracut.code()
);
}
tracing::info!("Recovery initramfs created at {recovery_initramfs_path}");
});
// todo: grub.d template for boot entry in OS

Ok(())
}
}
7 changes: 7 additions & 0 deletions src/backend/repart_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,13 @@ impl RepartOutput {
.map(|part| part.node.clone())
}

pub fn get_recovery_partition(&self) -> std::option::Option<String> {
self.partitions
.iter()
.find(|part| part.label == "os_recovery")
.map(|part| part.node.clone())
}

/// Create [`tiffin::Container`] from the repartitioning output with the mountpoints
/// from the DDI partition types
pub fn to_container(
Expand Down
1 change: 1 addition & 0 deletions templates/wholedisk/20-efi.conf
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ SizeMaxBytes=512M
MountPoint=/boot/efi:umask=0077,shortname=winnt
# This path is actually relative; see man repart.d at --copy-source option
CopyFiles=/boot/efi/:/
FactoryReset=true
3 changes: 2 additions & 1 deletion templates/wholedisk/45-boot.conf
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
[Partition]
Format=ext4
SizeMinBytes=1G
Weight=100
Weight=200
SizeMaxBytes=2G
MountPoint=/boot/:defaults
# This path is actually relative; see man repart.d at --copy-source option
CopyFiles=/boot:/
ExcludeFiles=/boot/efi
Type=xbootldr
FactoryReset=true
16 changes: 16 additions & 0 deletions templates/wholedisk/47-recovery.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# This partition is an EROFS mirror of rootfs, used for special recovery purposes
[Partition]
# Let's reserve this
Type=8DA63339-0007-60C0-C436-083AC8230908
Format=erofs
SizeMinBytes=4G
CopyFiles=/:/
Label=os_recovery
# Priority of 5000 ensures that it wouldn't be created if
# We don't have enough space
Priority=5000
Weight=100
# This partition will be 4-8GB in size, for future-proofing and
# recovery image updates.
SizeMaxBytes=8G
FactoryReset=false
3 changes: 3 additions & 0 deletions templates/wholedisk/50-root.conf
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ DefaultSubvolume=/
Type=root
Compression=zstd
ExcludeFiles=/boot/
Priority=-10000
Weight=5000
Format=btrfs
CopyFiles=/:/
Subvolumes=/ /home
CompressionLevel=1
FactoryReset=true