192 lines
9.5 KiB
Diff
192 lines
9.5 KiB
Diff
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)
|
|
|