KubeOS/0003-fix-os-agent-use-findmnt-to-find-out-which-device-mo.patch

192 lines
9.5 KiB
Diff
Raw Normal View History

From 59de6f644def5555c41e2ef14317e9178c40259f Mon Sep 17 00:00:00 2001
From: Yuhang Wei <weiyuhang3@huawei.com>
Date: Wed, 27 Nov 2024 18:34:14 +0000
Subject: [PATCH 03/11] fix(os-agent): use findmnt to find out which device
mounted on /
use "findmnt -no SOURCE --mountpoint /" to get the device name mounted on /
use "lsblk -blno FSTYPE,SIZE" to get the fstype and partition size
This patch fixes the problem if there are multiple mountpoints on a device
Signed-off-by: Yuhang Wei <weiyuhang3@huawei.com>
---
KubeOS-Rust/manager/src/sys_mgmt/config.rs | 21 ++----
KubeOS-Rust/manager/src/utils/partition.rs | 86 +++++++++-------------
2 files changed, 41 insertions(+), 66 deletions(-)
diff --git a/KubeOS-Rust/manager/src/sys_mgmt/config.rs b/KubeOS-Rust/manager/src/sys_mgmt/config.rs
index 8e42fa18..a491a429 100644
--- a/KubeOS-Rust/manager/src/sys_mgmt/config.rs
+++ b/KubeOS-Rust/manager/src/sys_mgmt/config.rs
@@ -826,13 +826,10 @@ mod tests {
let mut executor = MockCommandExec::new();
// the output shows that current root menuentry is A
- let command_output1 = r#"vda 23622320128
-vda1 /boot/efi vfat 61865984 BOOT
-vda2 / ext4 3145728000 ROOT-A
-vda3 ext4 2621440000 ROOT-B
-vda4 /persist ext4 17791188992 PERSIST
-"#;
- executor.expect_run_command_with_output().times(1).returning(|_, _| Ok(command_output1.to_string()));
+ let findmnt_output1 = "/dev/vda2";
+ let lsblk_output1 = "ext4 3145728000\n";
+ executor.expect_run_command_with_output().times(1).returning(|_, _| Ok(findmnt_output1.to_string()));
+ executor.expect_run_command_with_output().times(1).returning(|_, _| Ok(lsblk_output1.to_string()));
let result = grub_cmdline.get_config_partition(executor).unwrap();
// it should return false because the current root menuentry is A and we want to configure current partition
@@ -840,14 +837,8 @@ vda4 /persist ext4 17791188992 PERSIST
let mut executor = MockCommandExec::new();
- // the output shows that current root menuentry is A
- let command_output1 = r#"vda 23622320128
-vda1 /boot/efi vfat 61865984 BOOT
-vda2 / ext4 3145728000 ROOT-A
-vda3 ext4 2621440000 ROOT-B
-vda4 /persist ext4 17791188992 PERSIST
-"#;
- executor.expect_run_command_with_output().times(1).returning(|_, _| Ok(command_output1.to_string()));
+ executor.expect_run_command_with_output().times(1).returning(|_, _| Ok(findmnt_output1.to_string()));
+ executor.expect_run_command_with_output().times(1).returning(|_, _| Ok(lsblk_output1.to_string()));
grub_cmdline.is_cur_partition = false;
let result = grub_cmdline.get_config_partition(executor).unwrap();
// it should return true because the current root menuentry is A and we want to configure next partition
diff --git a/KubeOS-Rust/manager/src/utils/partition.rs b/KubeOS-Rust/manager/src/utils/partition.rs
index 4941ee9d..b2c095c6 100644
--- a/KubeOS-Rust/manager/src/utils/partition.rs
+++ b/KubeOS-Rust/manager/src/utils/partition.rs
@@ -25,43 +25,33 @@ pub struct PartitionInfo {
/// get_partition_info returns the current partition info and the next partition info.
pub fn get_partition_info<T: CommandExecutor>(executor: &T) -> Result<(PartitionInfo, PartitionInfo), anyhow::Error> {
- let lsblk = executor.run_command_with_output("lsblk", &["-blno", "NAME,MOUNTPOINT,FSTYPE,SIZE,LABEL"])?;
let mut cur_partition = PartitionInfo::default();
let mut next_partition = PartitionInfo::default();
- let mut found_boot = 0;
- trace!("get_partition_info lsblk command output:\n{}", lsblk);
- for line in lsblk.lines() {
- let res: Vec<&str> = line.split_whitespace().collect();
- if res.len() == 5 && res[4] == "BOOT" {
- trace!("Found boot partition:\n{:?}", res);
- found_boot = 2;
- continue;
- }
- if found_boot > 0 {
- trace!("Handling two root partitions:\n{:?}", res);
- if res[1] == "/" {
- // current partition
- cur_partition.device = format!("/dev/{}", res[0]).to_string();
- cur_partition.fs_type = res[2].to_string();
- cur_partition.size = res[3]
- .parse()
- .with_context(|| format!("Failed to parse current partition size to i64: \"{}\"", res[3]))?;
- cur_partition.menuentry = if res[0].contains("2") { String::from("A") } else { String::from("B") };
- } else {
- // next partition
- next_partition.device = format!("/dev/{}", res[0]).to_string();
- next_partition.fs_type = res[1].to_string();
- next_partition.size = res[2]
- .parse()
- .with_context(|| format!("Failed to parse next partition size to i64: \"{}\"", res[2]))?;
- next_partition.menuentry = if res[0].contains("2") { String::from("A") } else { String::from("B") };
- }
- found_boot -= 1;
- }
+ cur_partition.device = executor.run_command_with_output("findmnt", &["-no", "SOURCE", "--mountpoint", "/"])?;
+ trace!("{} is mounted on /", cur_partition.device);
+ if cur_partition.device.contains('2') {
+ cur_partition.menuentry = String::from("A");
+ next_partition.menuentry = String::from("B");
+ next_partition.device = cur_partition.device.replace("2", "3");
+ } else if cur_partition.device.contains('3') {
+ cur_partition.menuentry = String::from("B");
+ next_partition.menuentry = String::from("A");
+ next_partition.device = cur_partition.device.replace("3", "2");
+ } else {
+ bail!("Failed to get partition info, / is not mounted on the second or the third partition");
}
- if cur_partition.menuentry.is_empty() || next_partition.menuentry.is_empty() {
- bail!("Failed to get partition info, lsblk output: {}", lsblk);
+ let lsblk = executor.run_command_with_output("lsblk", &["-blno", "FSTYPE,SIZE", &cur_partition.device])?;
+ trace!("get_partition_info lsblk command output:\n{}", lsblk);
+ let elements: Vec<&str> = lsblk.split_whitespace().collect();
+ if elements.len() != 2 {
+ bail!("Failed to get partition info of FSTYPE and SIZE, lsblk output: {}", lsblk);
}
+ cur_partition.fs_type = elements[0].to_string();
+ next_partition.fs_type = elements[0].to_string();
+ cur_partition.size = elements[1]
+ .parse()
+ .with_context(|| format!("Failed to parse current partition size to i64: \"{}\"", elements[1]))?;
+ next_partition.size = cur_partition.size;
Ok((cur_partition, next_partition))
}
@@ -94,14 +84,11 @@ mod tests {
#[test]
fn test_get_partition_info() {
init();
- let command_output1 = r#"vda 23622320128
-vda1 /boot/efi vfat 61865984 BOOT
-vda2 / ext4 3145728000 ROOT-A
-vda3 ext4 2621440000 ROOT-B
-vda4 /persist ext4 17791188992 PERSIST
-"#;
+ let findmnt_output1 = "/dev/vda2";
+ let lsblk_output1 = "ext4 3145728000\n";
let mut mock = MockCommandExec::new();
- mock.expect_run_command_with_output().times(1).returning(|_, _| Ok(command_output1.to_string()));
+ mock.expect_run_command_with_output().times(1).returning(|_, _| Ok(findmnt_output1.to_string()));
+ mock.expect_run_command_with_output().times(1).returning(|_, _| Ok(lsblk_output1.to_string()));
let res = get_partition_info(&mock).unwrap();
let expect_res = (
PartitionInfo {
@@ -114,25 +101,22 @@ vda4 /persist ext4 17791188992 PERSIST
device: "/dev/vda3".to_string(),
menuentry: "B".to_string(),
fs_type: "ext4".to_string(),
- size: 2621440000,
+ size: 3145728000,
},
);
assert_eq!(res, expect_res);
- let command_output2 = r#"vda 23622320128
-vda1 /boot/efi vfat 61865984 BOOT
-vda2 ext4 3145728000 ROOT-A
-vda3 / ext4 2621440000 ROOT-B
-vda4 /persist ext4 17791188992 PERSIST
-"#;
- mock.expect_run_command_with_output().times(1).returning(|_, _| Ok(command_output2.to_string()));
+ let findmnt_output2 = "/dev/vda3";
+ let lsblk_output2 = "ext4 3145728000\n";
+ mock.expect_run_command_with_output().times(1).returning(|_, _| Ok(findmnt_output2.to_string()));
+ mock.expect_run_command_with_output().times(1).returning(|_, _| Ok(lsblk_output2.to_string()));
let res = get_partition_info(&mock).unwrap();
let expect_res = (
PartitionInfo {
device: "/dev/vda3".to_string(),
menuentry: "B".to_string(),
fs_type: "ext4".to_string(),
- size: 2621440000,
+ size: 3145728000,
},
PartitionInfo {
device: "/dev/vda2".to_string(),
@@ -148,8 +132,8 @@ vda4 /persist ext4 17791188992 PERSIST
let res = get_partition_info(&mock);
assert!(res.is_err());
- let command_output4 = "sda4 / ext4 13000245248";
- mock.expect_run_command_with_output().times(1).returning(|_, _| Ok(command_output4.to_string()));
+ let findmnt_output3 = "/dev/vda4";
+ mock.expect_run_command_with_output().times(1).returning(|_, _| Ok(findmnt_output3.to_string()));
let res = get_partition_info(&mock);
assert!(res.is_err());
}
--
2.39.5 (Apple Git-154)