Skip to content

Commit 1ec28f6

Browse files
committed
provisioning: Hook up GUID-based partition type
Signed-off-by: Ikey Doherty <[email protected]>
1 parent d6659b1 commit 1ec28f6

File tree

6 files changed

+129
-7
lines changed

6 files changed

+129
-7
lines changed

crates/provisioning/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ phf = { workspace = true, features = ["macros"] }
1616
test-log.workspace = true
1717
thiserror.workspace = true
1818
log.workspace = true
19+
uuid.workspace = true

crates/provisioning/src/commands/create_partition.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
//
44
// SPDX-License-Identifier: MPL-2.0
55

6-
use crate::{get_kdl_property, get_property_str, Constraints, Context, FromKdlProperty, PartitionRole};
6+
use crate::{
7+
get_kdl_entry, get_kdl_property, get_property_str, Constraints, Context, FromKdlProperty, FromKdlType,
8+
PartitionRole, PartitionTypeGuid, PartitionTypeKDL,
9+
};
710

811
/// Command to create a partition
912
#[derive(Debug)]
@@ -17,6 +20,9 @@ pub struct Command {
1720
/// The role, if any, of the partition
1821
pub role: Option<PartitionRole>,
1922

23+
/// The GUID of the partition type
24+
pub partition_type: Option<PartitionTypeGuid>,
25+
2026
pub constraints: Constraints,
2127
}
2228

@@ -37,11 +43,21 @@ pub(crate) fn parse(context: Context<'_>) -> Result<super::Command, crate::Error
3743
return Err(crate::Error::MissingNode("constraints"));
3844
};
3945

46+
let partition_type = if let Some(partition_type) = context.node.iter_children().find(|n| n.name().value() == "type")
47+
{
48+
match PartitionTypeKDL::from_kdl_type(get_kdl_entry(partition_type, &0)?)? {
49+
PartitionTypeKDL::GUID => Some(PartitionTypeGuid::from_kdl_node(partition_type)?),
50+
}
51+
} else {
52+
None
53+
};
54+
4055
// TODO: Load constraints etc
4156
Ok(super::Command::CreatePartition(Box::new(Command {
4257
disk,
4358
id,
4459
role,
4560
constraints,
61+
partition_type,
4662
})))
4763
}

crates/provisioning/src/provisioner.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ impl Provisioner {
169169
}
170170
}
171171

172-
// OK lets now apply amy mutations to the device assignments
172+
// OK lets now apply any mutations to the device assignments
173173
for (disk_name, device_plan) in device_assignments.iter_mut() {
174174
debug!("Applying device plan for disk {}", disk_name);
175175
if let Err(e) = device_plan.strategy.apply(&mut device_plan.planner) {

crates/provisioning/src/types.rs

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ mod units;
1818
pub use units::*;
1919
pub mod constraints;
2020
pub use constraints::*;
21+
mod partition_type;
22+
pub use partition_type::*;
2123

2224
/// The type of a KDL value
2325
#[derive(Debug)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// SPDX-FileCopyrightText: Copyright © 2025 Serpent OS Developers
2+
// SPDX-FileCopyrightText: Copyright © 2025 AerynOS Developers
3+
//
4+
// SPDX-License-Identifier: MPL-2.0
5+
6+
use std::{fmt, str::FromStr};
7+
8+
pub use gpt::partition_types::Type as GptPartitionType;
9+
use partitioning::gpt;
10+
pub use uuid::Uuid;
11+
12+
use crate::{get_kdl_entry, kdl_value_to_string, UnsupportedValue};
13+
14+
use super::FromKdlType;
15+
16+
pub enum PartitionTypeKDL {
17+
GUID,
18+
}
19+
20+
impl FromStr for PartitionTypeKDL {
21+
type Err = crate::Error;
22+
23+
fn from_str(value: &str) -> Result<Self, Self::Err> {
24+
match value {
25+
"guid" => Ok(Self::GUID),
26+
_ => Err(crate::Error::UnknownVariant),
27+
}
28+
}
29+
}
30+
31+
impl fmt::Display for PartitionTypeKDL {
32+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33+
match self {
34+
Self::GUID => f.write_str("guid"),
35+
}
36+
}
37+
}
38+
39+
impl<'a> FromKdlType<'a> for PartitionTypeKDL {
40+
fn from_kdl_type(id: &'a kdl::KdlEntry) -> Result<Self, crate::Error> {
41+
let ty_id = if let Some(ty) = id.ty() {
42+
ty.value().to_lowercase()
43+
} else {
44+
"".into()
45+
};
46+
47+
let v = ty_id.parse().map_err(|_| UnsupportedValue {
48+
at: id.span(),
49+
advice: Some("only '(GUID)' type is supported".into()),
50+
})?;
51+
Ok(v)
52+
}
53+
}
54+
55+
/// Represents GPT partition type GUIDs
56+
#[derive(Debug, PartialEq)]
57+
pub enum PartitionTypeGuid {
58+
EfiSystemPartition,
59+
ExtendedBootLoader,
60+
LinuxSwap,
61+
}
62+
63+
impl fmt::Display for PartitionTypeGuid {
64+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65+
match self {
66+
Self::EfiSystemPartition => f.write_str("efi-system-partition"),
67+
Self::ExtendedBootLoader => f.write_str("linux-extended-boot"),
68+
Self::LinuxSwap => f.write_str("linux-swap"),
69+
}
70+
}
71+
}
72+
73+
impl FromStr for PartitionTypeGuid {
74+
type Err = crate::Error;
75+
76+
fn from_str(value: &str) -> Result<Self, Self::Err> {
77+
match value {
78+
"efi-system-partition" => Ok(Self::EfiSystemPartition),
79+
"linux-extended-boot" => Ok(Self::ExtendedBootLoader),
80+
"linux-swap" => Ok(Self::LinuxSwap),
81+
_ => Err(crate::Error::UnknownVariant),
82+
}
83+
}
84+
}
85+
86+
impl PartitionTypeGuid {
87+
/// Returns the GUID value for this partition type
88+
pub fn as_guid(&self) -> GptPartitionType {
89+
match self {
90+
Self::EfiSystemPartition => gpt::partition_types::EFI,
91+
Self::ExtendedBootLoader => gpt::partition_types::FREEDESK_BOOT,
92+
Self::LinuxSwap => gpt::partition_types::LINUX_SWAP,
93+
}
94+
}
95+
96+
pub fn from_kdl_node(node: &kdl::KdlNode) -> Result<Self, crate::Error> {
97+
let value = kdl_value_to_string(get_kdl_entry(node, &0)?)?;
98+
let v = value.parse().map_err(|_| crate::UnsupportedValue {
99+
at: node.span(),
100+
advice: Some("'efi-system-partition', 'linux-swap', and 'linux-extended-boot' are supported".into()),
101+
})?;
102+
Ok(v)
103+
}
104+
}

crates/provisioning/tests/use_whole_disk.kdl

+4-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ strategy name="whole_disk" summary="Wipe and use an entire disk" {
44
// The result is stored in "root_disk" (disk=..)
55
find-disk "root_disk" {
66
constraints {
7-
min (GB)30
7+
min (GB)60
88
}
99
}
1010

@@ -17,7 +17,7 @@ strategy name="whole_disk" summary="Wipe and use an entire disk" {
1717
min (GIB)1
1818
max (GIB)2
1919
}
20-
type (GUID)"ESP"
20+
type (GUID)"efi-system-partition"
2121
}
2222

2323
// Create xbootldr
@@ -26,7 +26,7 @@ strategy name="whole_disk" summary="Wipe and use an entire disk" {
2626
min (GIB)2
2727
max (GIB)4
2828
}
29-
type (GUID)"LinuxExtendedBoot"
29+
type (GUID) "linux-extended-boot"
3030
}
3131

3232
// Create a partition for rootfs
@@ -35,7 +35,6 @@ strategy name="whole_disk" summary="Wipe and use an entire disk" {
3535
min (GIB)30
3636
max (GIB)120
3737
}
38-
type (GUID)"LinuxRoot"
3938
}
4039

4140
// find a partition (bound to root_disk here)
@@ -51,6 +50,6 @@ strategy name="whole_disk_with_swap" inherits="whole_disk" \
5150
min (GIB)4
5251
max (GIB)8
5352
}
54-
type (GUID)"LinuxSwap"
53+
type (GUID)"linux-swap"
5554
}
5655
}

0 commit comments

Comments
 (0)