-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
👷 gucc: generate kernel params out of partitions scheme
- Loading branch information
1 parent
335d519
commit 531b19b
Showing
7 changed files
with
274 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#ifndef KERNEL_PARAMS_HPP | ||
#define KERNEL_PARAMS_HPP | ||
|
||
#include "gucc/partition.hpp" | ||
|
||
#include <optional> // for optional | ||
#include <string> // for string | ||
#include <string_view> // for string_view | ||
#include <vector> // for vector | ||
|
||
namespace gucc::fs { | ||
|
||
/// @brief Get kernel params from partitions information. | ||
/// @param partitions The partitions information. | ||
/// @param kernel_params The kernel params separated by space. | ||
/// @param zfs_root_dataset The root dataset of ZFS. | ||
/// @return A vector of strings representing the kernel parameters. | ||
auto get_kernel_params(const std::vector<Partition>& partitions, std::string_view kernel_params, std::optional<std::string> zfs_root_dataset = std::nullopt) noexcept -> std::optional<std::vector<std::string>>; | ||
|
||
} // namespace gucc::fs | ||
|
||
#endif // KERNEL_PARAMS_HPP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
#include "gucc/kernel_params.hpp" | ||
#include "gucc/file_utils.hpp" | ||
#include "gucc/io_utils.hpp" | ||
#include "gucc/string_utils.hpp" | ||
|
||
#include <filesystem> // for fs::path | ||
#include <optional> // for optional | ||
#include <utility> // for make_optional | ||
|
||
#include <fmt/compile.h> | ||
#include <fmt/format.h> | ||
|
||
#include <spdlog/spdlog.h> | ||
|
||
using namespace std::string_literals; | ||
using namespace std::string_view_literals; | ||
|
||
namespace { | ||
|
||
auto is_root_on_btrfs(const gucc::fs::Partition& partition) noexcept -> bool { | ||
return partition.mountpoint == "/"sv && partition.fstype == "btrfs"sv; | ||
} | ||
auto is_root_on_zfs(const gucc::fs::Partition& partition) noexcept -> bool { | ||
return partition.mountpoint == "/"sv && partition.fstype == "zfs"sv; | ||
} | ||
|
||
} // namespace | ||
|
||
namespace gucc::fs { | ||
|
||
// base actions taken from calamares | ||
// see https://github.com/calamares/calamares/blob/calamares/src/modules/bootloader/main.py#L133 | ||
auto get_kernel_params(const std::vector<Partition>& partitions, std::string_view kernel_params, std::optional<std::string> zfs_root_dataset) noexcept -> std::optional<std::vector<std::string>> { | ||
auto kernel_params_list = gucc::utils::make_multiline(kernel_params, false, ' '); | ||
kernel_params_list.emplace_back("rw"s); | ||
|
||
std::vector<std::string> cryptdevice_params{}; | ||
std::optional<std::string_view> root_uuid{}; | ||
// swap settings | ||
std::optional<std::string_view> swap_uuid{}; | ||
std::optional<std::string_view> swap_mappername{}; | ||
|
||
for (auto&& partition : partitions) { | ||
const bool has_luks = partition.luks_mapper_name.has_value(); | ||
if (partition.fstype == "linuxswap"sv && !has_luks) { | ||
swap_uuid = std::make_optional<std::string_view>(partition.uuid_str); | ||
} else if (partition.fstype == "linuxswap"sv && has_luks) { | ||
swap_mappername = partition.luks_mapper_name; | ||
} | ||
|
||
if (partition.mountpoint == "/"sv && has_luks) { | ||
cryptdevice_params = {fmt::format(FMT_COMPILE("cryptdevice=UUID={}:{}"), *partition.luks_uuid, *partition.luks_mapper_name)}; | ||
cryptdevice_params.push_back(fmt::format(FMT_COMPILE("root=/dev/mapper/{}"), *partition.luks_mapper_name)); | ||
} | ||
|
||
if (partition.mountpoint == "/"sv) { | ||
root_uuid = std::make_optional<std::string_view>(partition.uuid_str); | ||
} | ||
|
||
// specific logic for btrfs and zfs | ||
|
||
// If a btrfs root subvolume was not set, it implies that the root | ||
// is directly on the partition and this option is not required. | ||
if (is_root_on_btrfs(partition) && partition.subvolume) { | ||
kernel_params_list.push_back(fmt::format(FMT_COMPILE("rootflags=subvol={}"), *partition.subvolume)); | ||
} | ||
// The root dataset's location must be specified for ZFS. | ||
else if (is_root_on_zfs(partition)) { | ||
if (!zfs_root_dataset) { | ||
spdlog::error("kernel_params: root zfs dataset cannot be nullopt"); | ||
return std::nullopt; | ||
} | ||
kernel_params_list.push_back(fmt::format(FMT_COMPILE("root=ZFS={}"), *zfs_root_dataset)); | ||
} | ||
} | ||
|
||
if (!root_uuid.has_value() || root_uuid->empty()) { | ||
spdlog::error("kernel_params: not found ROOT partition UUID"); | ||
return std::nullopt; | ||
} | ||
|
||
if (!cryptdevice_params.empty()) { | ||
kernel_params_list.insert(kernel_params_list.end(), cryptdevice_params.begin(), cryptdevice_params.end()); | ||
} else { | ||
kernel_params_list.push_back(fmt::format(FMT_COMPILE("root=UUID={}"), *root_uuid)); | ||
} | ||
|
||
if (swap_uuid.has_value() && !swap_uuid->empty()) { | ||
kernel_params_list.push_back(fmt::format(FMT_COMPILE("resume=UUID={}"), *swap_uuid)); | ||
} | ||
|
||
if (swap_mappername.has_value() && !swap_mappername->empty()) { | ||
kernel_params_list.push_back(fmt::format(FMT_COMPILE("resume=/dev/mapper/{}"), *swap_mappername)); | ||
} | ||
|
||
return std::make_optional<std::vector<std::string>>(kernel_params_list); | ||
} | ||
|
||
} // namespace gucc::fs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
#include "gucc/kernel_params.hpp" | ||
#include "gucc/logger.hpp" | ||
|
||
#include <cassert> | ||
|
||
#include <string> | ||
#include <string_view> | ||
#include <vector> | ||
|
||
#include <spdlog/sinks/callback_sink.h> | ||
#include <spdlog/spdlog.h> | ||
|
||
using namespace std::string_literals; | ||
using namespace std::string_view_literals; | ||
|
||
int main() { | ||
auto callback_sink = std::make_shared<spdlog::sinks::callback_sink_mt>([](const spdlog::details::log_msg&) { | ||
// noop | ||
}); | ||
auto logger = std::make_shared<spdlog::logger>("default", callback_sink); | ||
spdlog::set_default_logger(logger); | ||
gucc::logger::set_logger(logger); | ||
|
||
static constexpr auto DEFAULT_KERNEL_PARAMS = "quiet splash"sv; | ||
|
||
// btrfs with subvolumes | ||
{ | ||
const std::vector<gucc::fs::Partition> partitions{ | ||
gucc::fs::Partition{.fstype = "btrfs"s, .mountpoint = "/"s, .uuid_str = "6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"s, .device = "/dev/nvme0n1p1"s, .mount_opts = "defaults,noatime,compress=zstd,space_cache=v2,commit=120"s, .subvolume = "/@"s}, | ||
gucc::fs::Partition{.fstype = "btrfs"s, .mountpoint = "/home"s, .uuid_str = "6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"s, .device = "/dev/nvme0n1p1"s, .mount_opts = "defaults,noatime,compress=zstd,space_cache=v2,commit=120"s, .subvolume = "/@home"s}, | ||
gucc::fs::Partition{.fstype = "btrfs"s, .mountpoint = "/var/cache"s, .uuid_str = "6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"s, .device = "/dev/nvme0n1p1"s, .mount_opts = "defaults,noatime,compress=zstd,space_cache=v2,commit=120"s, .subvolume = "/@cache"s}, | ||
gucc::fs::Partition{.fstype = "fat32"s, .mountpoint = "/boot"s, .uuid_str = "8EFB-4B84"s, .device = "/dev/nvme0n1p2"s, .mount_opts = "defaults,noatime"s}, | ||
}; | ||
const auto& kernel_params = gucc::fs::get_kernel_params(partitions, DEFAULT_KERNEL_PARAMS); | ||
assert(kernel_params.has_value()); | ||
assert(kernel_params->size() == 5); | ||
assert((*kernel_params == std::vector<std::string>{"quiet", "splash", "rw", "rootflags=subvol=/@", "root=UUID=6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"})); | ||
} | ||
// invalid xfs (empty uuid) | ||
{ | ||
const std::vector<gucc::fs::Partition> partitions{ | ||
gucc::fs::Partition{.fstype = "xfs"s, .mountpoint = "/"s, .device = "/dev/nvme0n1p1"s, .mount_opts = "defaults,lazytime,noatime,attr2,inode64,logbsize=256k,noquota"s}, | ||
gucc::fs::Partition{.fstype = "fat16"s, .mountpoint = "/boot"s, .uuid_str = "8EFB-4B84"s, .device = "/dev/nvme0n1p2"s, .mount_opts = "defaults,noatime"s}, | ||
}; | ||
const auto& kernel_params = gucc::fs::get_kernel_params(partitions, DEFAULT_KERNEL_PARAMS); | ||
assert(!kernel_params.has_value()); | ||
} | ||
// invalid xfs (without root partition) | ||
{ | ||
const std::vector<gucc::fs::Partition> partitions{ | ||
gucc::fs::Partition{.fstype = "xfs"s, .mountpoint = "/home"s, .device = "/dev/nvme0n1p1"s, .mount_opts = "defaults,lazytime,noatime,attr2,inode64,logbsize=256k,noquota"s}, | ||
gucc::fs::Partition{.fstype = "fat16"s, .mountpoint = "/boot"s, .uuid_str = "8EFB-4B84"s, .device = "/dev/nvme0n1p2"s, .mount_opts = "defaults,noatime"s}, | ||
}; | ||
const auto& kernel_params = gucc::fs::get_kernel_params(partitions, DEFAULT_KERNEL_PARAMS); | ||
assert(!kernel_params.has_value()); | ||
} | ||
// basic xfs | ||
{ | ||
const std::vector<gucc::fs::Partition> partitions{ | ||
gucc::fs::Partition{.fstype = "xfs"s, .mountpoint = "/"s, .uuid_str = "6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"s, .device = "/dev/nvme0n1p1"s, .mount_opts = "defaults,lazytime,noatime,attr2,inode64,logbsize=256k,noquota"s}, | ||
gucc::fs::Partition{.fstype = "fat16"s, .mountpoint = "/boot"s, .uuid_str = "8EFB-4B84"s, .device = "/dev/nvme0n1p2"s, .mount_opts = "defaults,noatime"s}, | ||
}; | ||
const auto& kernel_params = gucc::fs::get_kernel_params(partitions, DEFAULT_KERNEL_PARAMS); | ||
assert(kernel_params.has_value()); | ||
assert(kernel_params->size() == 4); | ||
assert((*kernel_params == std::vector<std::string>{"quiet", "splash", "rw", "root=UUID=6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"})); | ||
} | ||
// swap xfs | ||
{ | ||
const std::vector<gucc::fs::Partition> partitions{ | ||
gucc::fs::Partition{.fstype = "xfs"s, .mountpoint = "/"s, .uuid_str = "6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"s, .device = "/dev/nvme0n1p1"s, .mount_opts = "defaults,lazytime,noatime,attr2,inode64,logbsize=256k,noquota"s}, | ||
gucc::fs::Partition{.fstype = "linuxswap"s, .mountpoint = ""s, .uuid_str = "59848b1b-c6be-48f4-b3e1-48179ea72dec"s, .device = "/dev/nvme0n1p3"s, .mount_opts = "defaults,noatime"s}, | ||
gucc::fs::Partition{.fstype = "vfat"s, .mountpoint = "/boot"s, .uuid_str = "8EFB-4B84"s, .device = "/dev/nvme0n1p2"s, .mount_opts = "defaults,noatime"s}, | ||
}; | ||
const auto& kernel_params = gucc::fs::get_kernel_params(partitions, DEFAULT_KERNEL_PARAMS); | ||
assert(kernel_params.has_value()); | ||
assert(kernel_params->size() == 5); | ||
assert((*kernel_params == std::vector<std::string>{"quiet", "splash", "rw", "root=UUID=6bdb3301-8efb-4b84-b0b7-4caeef26fd6f", "resume=UUID=59848b1b-c6be-48f4-b3e1-48179ea72dec"})); | ||
} | ||
// luks xfs | ||
{ | ||
const std::vector<gucc::fs::Partition> partitions{ | ||
gucc::fs::Partition{.fstype = "xfs"s, .mountpoint = "/"s, .uuid_str = "6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"s, .device = "/dev/nvme0n1p1"s, .mount_opts = "defaults,lazytime,noatime,attr2,inode64,logbsize=256k,noquota"s, .luks_mapper_name = "luks_device"s, .luks_uuid = "00e1b836-81b6-433f-83ca-0fd373e3cd50"s}, | ||
gucc::fs::Partition{.fstype = "linuxswap"s, .mountpoint = ""s, .uuid_str = ""s, .device = "/dev/nvme0n1p3"s, .mount_opts = "defaults,noatime"s}, | ||
gucc::fs::Partition{.fstype = "vfat"s, .mountpoint = "/boot"s, .uuid_str = "8EFB-4B84"s, .device = "/dev/nvme0n1p2"s, .mount_opts = "defaults,noatime"s}, | ||
}; | ||
const auto& kernel_params = gucc::fs::get_kernel_params(partitions, DEFAULT_KERNEL_PARAMS); | ||
assert(kernel_params.has_value()); | ||
assert(kernel_params->size() == 5); | ||
assert((*kernel_params == std::vector<std::string>{"quiet", "splash", "rw", "cryptdevice=UUID=00e1b836-81b6-433f-83ca-0fd373e3cd50:luks_device", "root=/dev/mapper/luks_device"})); | ||
} | ||
// luks swap xfs | ||
{ | ||
const std::vector<gucc::fs::Partition> partitions{ | ||
gucc::fs::Partition{.fstype = "xfs"s, .mountpoint = "/"s, .uuid_str = "6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"s, .device = "/dev/nvme0n1p1"s, .mount_opts = "defaults,lazytime,noatime,attr2,inode64,logbsize=256k,noquota"s, .luks_mapper_name = "luks_device"s, .luks_uuid = "00e1b836-81b6-433f-83ca-0fd373e3cd50"s}, | ||
gucc::fs::Partition{.fstype = "linuxswap"s, .mountpoint = ""s, .uuid_str = ""s, .device = "/dev/nvme0n1p3"s, .mount_opts = "defaults,noatime"s, .luks_mapper_name = "luks_swap_device"s, .luks_uuid = "59848b1b-c6be-48f4-b3e1-48179ea72dec"s}, | ||
gucc::fs::Partition{.fstype = "vfat"s, .mountpoint = "/boot"s, .uuid_str = "8EFB-4B84"s, .device = "/dev/nvme0n1p2"s, .mount_opts = "defaults,noatime"s}, | ||
}; | ||
const auto& kernel_params = gucc::fs::get_kernel_params(partitions, DEFAULT_KERNEL_PARAMS); | ||
assert(kernel_params.has_value()); | ||
assert(kernel_params->size() == 6); | ||
assert((*kernel_params == std::vector<std::string>{"quiet", "splash", "rw", "cryptdevice=UUID=00e1b836-81b6-433f-83ca-0fd373e3cd50:luks_device", "root=/dev/mapper/luks_device", "resume=/dev/mapper/luks_swap_device"})); | ||
} | ||
// invalid zfs | ||
{ | ||
const std::vector<gucc::fs::Partition> partitions{ | ||
gucc::fs::Partition{.fstype = "zfs"s, .mountpoint = "/"s, .uuid_str = "6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"s, .device = "/dev/nvme0n1p1"s, .mount_opts = "defaults,noatime,compress=zstd,space_cache=v2,commit=120"s}, | ||
gucc::fs::Partition{.fstype = "zfs"s, .mountpoint = "/home"s, .uuid_str = "6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"s, .device = "/dev/nvme0n1p1"s, .mount_opts = "defaults,noatime,compress=zstd,space_cache=v2,commit=120"s}, | ||
gucc::fs::Partition{.fstype = "zfs"s, .mountpoint = "/var/cache"s, .uuid_str = "6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"s, .device = "/dev/nvme0n1p1"s, .mount_opts = "defaults,noatime,compress=zstd,space_cache=v2,commit=120"s}, | ||
gucc::fs::Partition{.fstype = "vfat"s, .mountpoint = "/boot"s, .uuid_str = "8EFB-4B84"s, .device = "/dev/nvme0n1p2"s, .mount_opts = "defaults,noatime"s}, | ||
}; | ||
const auto& kernel_params = gucc::fs::get_kernel_params(partitions, DEFAULT_KERNEL_PARAMS); | ||
assert(!kernel_params.has_value()); | ||
} | ||
// valid zfs | ||
{ | ||
const std::vector<gucc::fs::Partition> partitions{ | ||
gucc::fs::Partition{.fstype = "zfs"s, .mountpoint = "/"s, .uuid_str = "6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"s, .device = "/dev/nvme0n1p1"s, .mount_opts = "defaults,noatime,compress=zstd,space_cache=v2,commit=120"s}, | ||
gucc::fs::Partition{.fstype = "zfs"s, .mountpoint = "/home"s, .uuid_str = "6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"s, .device = "/dev/nvme0n1p1"s, .mount_opts = "defaults,noatime,compress=zstd,space_cache=v2,commit=120"s}, | ||
gucc::fs::Partition{.fstype = "zfs"s, .mountpoint = "/var/cache"s, .uuid_str = "6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"s, .device = "/dev/nvme0n1p1"s, .mount_opts = "defaults,noatime,compress=zstd,space_cache=v2,commit=120"s}, | ||
gucc::fs::Partition{.fstype = "vfat"s, .mountpoint = "/boot"s, .uuid_str = "8EFB-4B84"s, .device = "/dev/nvme0n1p2"s, .mount_opts = "defaults,noatime"s}, | ||
}; | ||
const auto& kernel_params = gucc::fs::get_kernel_params(partitions, DEFAULT_KERNEL_PARAMS, "zpcachyos/ROOT"); | ||
assert(kernel_params.has_value()); | ||
assert(kernel_params->size() == 5); | ||
assert((*kernel_params == std::vector<std::string>{"quiet", "splash", "rw", "root=ZFS=zpcachyos/ROOT", "root=UUID=6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"})); | ||
} | ||
// luks btrfs with subvolumes | ||
{ | ||
const std::vector<gucc::fs::Partition> partitions{ | ||
gucc::fs::Partition{.fstype = "btrfs"s, .mountpoint = "/"s, .uuid_str = "6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"s, .device = "/dev/nvme0n1p1"s, .mount_opts = "defaults,noatime,compress=zstd,space_cache=v2,commit=120"s, .subvolume = "/@"s, .luks_mapper_name = "luks-6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"s, .luks_uuid = "6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"s}, | ||
gucc::fs::Partition{.fstype = "btrfs"s, .mountpoint = "/home"s, .uuid_str = "6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"s, .device = "/dev/nvme0n1p1"s, .mount_opts = "defaults,noatime,compress=zstd,space_cache=v2,commit=120"s, .subvolume = "/@home"s, .luks_mapper_name = "luks-6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"s, .luks_uuid = "6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"s}, | ||
gucc::fs::Partition{.fstype = "btrfs"s, .mountpoint = "/var/cache"s, .uuid_str = "6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"s, .device = "/dev/nvme0n1p1"s, .mount_opts = "defaults,noatime,compress=zstd,space_cache=v2,commit=120"s, .subvolume = "/@cache"s, .luks_mapper_name = "luks-6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"s, .luks_uuid = "6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"s}, | ||
gucc::fs::Partition{.fstype = "fat32"s, .mountpoint = "/boot"s, .uuid_str = "8EFB-4B84"s, .device = "/dev/nvme0n1p2"s, .mount_opts = "defaults,noatime"s}, | ||
}; | ||
const auto& kernel_params = gucc::fs::get_kernel_params(partitions, DEFAULT_KERNEL_PARAMS); | ||
assert(kernel_params.has_value()); | ||
assert(kernel_params->size() == 6); | ||
assert((*kernel_params == std::vector<std::string>{"quiet", "splash", "rw", "rootflags=subvol=/@", "cryptdevice=UUID=6bdb3301-8efb-4b84-b0b7-4caeef26fd6f:luks-6bdb3301-8efb-4b84-b0b7-4caeef26fd6f", "root=/dev/mapper/luks-6bdb3301-8efb-4b84-b0b7-4caeef26fd6f"})); | ||
} | ||
} |