Merge pull request #19 from blitz/specialisation

Lanzatool: enable specialisation
This commit is contained in:
nikstur 2022-11-27 18:19:59 +01:00 committed by GitHub
commit e6aa11f76c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 69 additions and 10 deletions

View File

@ -103,11 +103,11 @@
}, },
"nixpkgs-test": { "nixpkgs-test": {
"locked": { "locked": {
"lastModified": 1669288333, "lastModified": 1669495095,
"narHash": "sha256-PMP3JiUBIYu40gmWAIw+DG2UVsx7m5exGaGxdSQE3ew=", "narHash": "sha256-wasu8T7ac+LVm4aXuAYkH76Rr98VW0Cp9oZvNPuKiiU=",
"owner": "RaitoBezarius", "owner": "RaitoBezarius",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "308e09c57da1df2abeccc236431a2675a2b38555", "rev": "8bbe1bb1f7352dd9c2e448e8d68846a66d0c2aca",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@ -211,6 +211,30 @@
dst = "convert_to_esp(bootspec.get('kernel'))"; 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")
'';
};
};
}; };
} }

View File

@ -14,6 +14,7 @@
], ],
"label": "LanzaOS", "label": "LanzaOS",
"toplevel": "/run/current-system", "toplevel": "/run/current-system",
"specialisation": {},
"extension": { "extension": {
"osRelease": "/etc/os-release" "osRelease": "/etc/os-release"
} }

View File

@ -1,8 +1,9 @@
use std::collections::HashMap;
use std::path::PathBuf; use std::path::PathBuf;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct Bootspec { pub struct Bootspec {
/// Label for the system closure /// Label for the system closure
@ -19,10 +20,12 @@ pub struct Bootspec {
pub initrd_secrets: Option<PathBuf>, pub initrd_secrets: Option<PathBuf>,
/// config.system.build.toplevel path /// config.system.build.toplevel path
pub toplevel: PathBuf, pub toplevel: PathBuf,
/// Mapping of specialisation names to their boot.json
pub specialisation: HashMap<String, Bootspec>,
pub extension: Extension, pub extension: Extension,
} }
#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct Extension { pub struct Extension {
pub os_release: PathBuf, pub os_release: PathBuf,

View File

@ -67,5 +67,12 @@ fn nixos_path(path: impl AsRef<Path>, name: &str) -> Result<PathBuf> {
} }
fn generation_path(generation: &Generation) -> PathBuf { 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))
}
} }

View File

@ -9,6 +9,7 @@ use crate::bootspec::Bootspec;
#[derive(Debug)] #[derive(Debug)]
pub struct Generation { pub struct Generation {
version: u64, version: u64,
specialisation_name: Option<String>,
pub bootspec: Bootspec, pub bootspec: Bootspec,
} }
@ -22,9 +23,22 @@ impl Generation {
Ok(Self { Ok(Self {
version: parse_version(toplevel)?, version: parse_version(toplevel)?,
specialisation_name: None,
bootspec, 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<String> {
self.specialisation_name.clone()
}
} }
impl fmt::Display for Generation { impl fmt::Display for Generation {

View File

@ -51,18 +51,28 @@ impl Installer {
println!("Installing generation {generation}"); 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(()) Ok(())
} }
pub fn install_generation(&self, generation: Generation) -> Result<()> { fn install_generation(&self, generation: &Generation) -> Result<()> {
println!("Reading bootspec..."); println!("Reading bootspec...");
let bootspec = &generation.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..."); println!("Assembling lanzaboote image...");