From 0a638970e7f9817bc1c057a204254a2d15317361 Mon Sep 17 00:00:00 2001 From: nikstur Date: Sun, 27 Nov 2022 11:19:02 +0100 Subject: [PATCH] lanzatool: enable specialisation --- flake.lock | 6 +++--- flake.nix | 26 +++++++++++++++++++++++++- rust/lanzatool/bootspec.json | 1 + rust/lanzatool/src/bootspec.rs | 7 +++++-- rust/lanzatool/src/esp.rs | 9 ++++++++- rust/lanzatool/src/generation.rs | 14 ++++++++++++++ rust/lanzatool/src/install.rs | 16 +++++++++++++--- 7 files changed, 69 insertions(+), 10 deletions(-) diff --git a/flake.lock b/flake.lock index c1763fb..48448a1 100644 --- a/flake.lock +++ b/flake.lock @@ -103,11 +103,11 @@ }, "nixpkgs-test": { "locked": { - "lastModified": 1669288333, - "narHash": "sha256-PMP3JiUBIYu40gmWAIw+DG2UVsx7m5exGaGxdSQE3ew=", + "lastModified": 1669495095, + "narHash": "sha256-wasu8T7ac+LVm4aXuAYkH76Rr98VW0Cp9oZvNPuKiiU=", "owner": "RaitoBezarius", "repo": "nixpkgs", - "rev": "308e09c57da1df2abeccc236431a2675a2b38555", + "rev": "8bbe1bb1f7352dd9c2e448e8d68846a66d0c2aca", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 3c48027..bdb5e22 100644 --- a/flake.nix +++ b/flake.nix @@ -211,6 +211,30 @@ dst = "convert_to_esp(bootspec.get('kernel'))"; }; }; - }; + specialisation-works = mkSecureBootTest { + name = "specialisation-still-boot-under-secureboot"; + machine = { pkgs, ... }: { + specialisation.variant.configuration = { + environment.systemPackages = [ + pkgs.efibootmgr + ]; + }; + }; + testScript = '' + machine.start() + print(machine.succeed("ls -lah /boot/EFI/Linux")) + print(machine.succeed("cat /run/current-system/bootspec/boot.v1.json")) + # TODO: make it more reliable to find this filename, i.e. read it from somewhere? + machine.succeed("bootctl set-default nixos-generation-1-specialisation-variant.efi") + machine.succeed("sync") + machine.fail("efibootmgr") + machine.crash() + machine.start() + print(machine.succeed("bootctl")) + # We have efibootmgr in this specialisation. + machine.succeed("efibootmgr") + ''; + }; + }; }; } diff --git a/rust/lanzatool/bootspec.json b/rust/lanzatool/bootspec.json index 5c89e13..5376acb 100644 --- a/rust/lanzatool/bootspec.json +++ b/rust/lanzatool/bootspec.json @@ -14,6 +14,7 @@ ], "label": "LanzaOS", "toplevel": "/run/current-system", + "specialisation": {}, "extension": { "osRelease": "/etc/os-release" } diff --git a/rust/lanzatool/src/bootspec.rs b/rust/lanzatool/src/bootspec.rs index 4afe98d..f3e8c7a 100644 --- a/rust/lanzatool/src/bootspec.rs +++ b/rust/lanzatool/src/bootspec.rs @@ -1,8 +1,9 @@ +use std::collections::HashMap; use std::path::PathBuf; use serde::{Deserialize, Serialize}; -#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Bootspec { /// Label for the system closure @@ -19,10 +20,12 @@ pub struct Bootspec { pub initrd_secrets: Option, /// config.system.build.toplevel path pub toplevel: PathBuf, + /// Mapping of specialisation names to their boot.json + pub specialisation: HashMap, pub extension: Extension, } -#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Extension { pub os_release: PathBuf, diff --git a/rust/lanzatool/src/esp.rs b/rust/lanzatool/src/esp.rs index 650562b..5b10171 100644 --- a/rust/lanzatool/src/esp.rs +++ b/rust/lanzatool/src/esp.rs @@ -67,5 +67,12 @@ fn nixos_path(path: impl AsRef, name: &str) -> Result { } fn generation_path(generation: &Generation) -> PathBuf { - PathBuf::from(format!("nixos-generation-{}.efi", generation)) + if let Some(specialisation_name) = generation.is_specialized() { + PathBuf::from(format!( + "nixos-generation-{}-specialisation-{}.efi", + generation, specialisation_name + )) + } else { + PathBuf::from(format!("nixos-generation-{}.efi", generation)) + } } diff --git a/rust/lanzatool/src/generation.rs b/rust/lanzatool/src/generation.rs index a452b2a..9ff7a5f 100644 --- a/rust/lanzatool/src/generation.rs +++ b/rust/lanzatool/src/generation.rs @@ -9,6 +9,7 @@ use crate::bootspec::Bootspec; #[derive(Debug)] pub struct Generation { version: u64, + specialisation_name: Option, pub bootspec: Bootspec, } @@ -22,9 +23,22 @@ impl Generation { Ok(Self { version: parse_version(toplevel)?, + specialisation_name: None, bootspec, }) } + + pub fn specialise(&self, name: &str, bootspec: &Bootspec) -> Self { + Self { + version: self.version, + specialisation_name: Some(String::from(name)), + bootspec: bootspec.clone(), + } + } + + pub fn is_specialized(&self) -> Option { + self.specialisation_name.clone() + } } impl fmt::Display for Generation { diff --git a/rust/lanzatool/src/install.rs b/rust/lanzatool/src/install.rs index 373a9b4..64bba50 100644 --- a/rust/lanzatool/src/install.rs +++ b/rust/lanzatool/src/install.rs @@ -51,18 +51,28 @@ impl Installer { println!("Installing generation {generation}"); - self.install_generation(generation)? + self.install_generation(&generation) + .context("Failed to install generation")?; + + for (name, bootspec) in &generation.bootspec.specialisation { + let specialised_generation = generation.specialise(name, bootspec); + + println!("Installing specialisation: {name} of generation: {generation}"); + + self.install_generation(&specialised_generation) + .context("Failed to install specialisation")?; + } } Ok(()) } - pub fn install_generation(&self, generation: Generation) -> Result<()> { + fn install_generation(&self, generation: &Generation) -> Result<()> { println!("Reading bootspec..."); let bootspec = &generation.bootspec; - let esp_paths = EspPaths::new(&self.esp, &generation)?; + let esp_paths = EspPaths::new(&self.esp, generation)?; println!("Assembling lanzaboote image...");