From f4aa1bc99bb902b50445d35d0d944cf8ab65a99d Mon Sep 17 00:00:00 2001 From: Renata Ravanelli Date: Mon, 12 Aug 2024 16:22:16 -0300 Subject: [PATCH] Use blkid instead of lsblk to get disk info when udev is not present - OSBuild does not allow udev rules in loop devices, for this reason can not rely on labels on the partitions to create the osmet image, due it use blkid instead of lsblk that relys on udev. Signed-off-by: Renata Ravanelli --- docs/release-notes.md | 1 + src/blockdev.rs | 87 ++++++++++++++++++++++++++++++------------- 2 files changed, 63 insertions(+), 25 deletions(-) diff --git a/docs/release-notes.md b/docs/release-notes.md index c79ea32f2..1147b0a8c 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -14,6 +14,7 @@ Minor changes: Internal changes: +- osmet: Use blkid to get partition information if udev is unavailable Packaging changes: diff --git a/src/blockdev.rs b/src/blockdev.rs index cb7fe5510..7ffc0e954 100644 --- a/src/blockdev.rs +++ b/src/blockdev.rs @@ -109,19 +109,34 @@ impl Disk { if devinfo.get("TYPE").map(|s| s.as_str()) != Some("part") { continue; } - let (mountpoint, swap) = match devinfo.get("MOUNTPOINT") { - Some(mp) if mp == "[SWAP]" => (None, true), - Some(mp) => (Some(mp.to_string()), false), - None => (None, false), - }; - result.push(Partition { - path: name.to_owned(), - label: devinfo.get("LABEL").map(<_>::to_string), - fstype: devinfo.get("FSTYPE").map(<_>::to_string), - parent: self.path.to_owned(), - mountpoint, - swap, - }); + // only trust lsblk output for the following fields if we have udev + if have_udev() { + let (mountpoint, swap) = match devinfo.get("MOUNTPOINT") { + Some(mp) if mp == "[SWAP]" => (None, true), + Some(mp) => (Some(mp.to_string()), false), + None => (None, false), + }; + result.push(Partition { + path: name.to_owned(), + label: devinfo.get("LABEL").map(<_>::to_string), + fstype: devinfo.get("FSTYPE").map(<_>::to_string), + parent: self.path.to_owned(), + mountpoint, + swap, + }); + } else { + let devinfo = blkid_single(Path::new(name))?; + // note TYPE here: blkid uses TYPE instead of FSTYPE + let fstype = devinfo.get("TYPE").map(<_>::to_string); + result.push(Partition { + path: name.to_owned(), + label: devinfo.get("LABEL").map(<_>::to_string), + fstype: fstype.to_owned(), + parent: self.path.to_owned(), + mountpoint: None, + swap: fstype.is_some_and(|s| s == "swap"), + }); + } } } Ok(result) @@ -800,6 +815,13 @@ pub fn lsblk_single(dev: &Path) -> Result> { Ok(devinfos.remove(0)) } +pub fn blkid_single(dev: &Path) -> Result> { + let mut devinfos = blkid(Some(vec![dev]))?; + if devinfos.len() !=1 { + bail!("expected one blkid result for {}, got: {:?}", dev.display(), devinfos); + } + Ok(devinfos.remove(0)) +} /// Returns all available filesystems. /// rereadpt mitigates possible issue with outdated UUIDs on different /// paths to the same disk: after 'ignition-ostree-firstboot-uuid' @@ -822,7 +844,7 @@ fn get_all_filesystems(rereadpt: bool) -> Result>> { } udev_settle()?; } - blkid() + blkid(None) } /// Returns filesystems with given label. @@ -884,7 +906,7 @@ fn split_blkid_line(line: &str) -> HashMap { fields } -fn blkid() -> Result>> { +fn blkid(dev: Option>) -> Result>> { // Run blkid with a clean cache to avoid collecting old devices which no // longer exist. // https://github.com/coreos/coreos-installer/pull/1288#discussion_r1312008111 @@ -893,19 +915,31 @@ fn blkid() -> Result>> { // the blkid -p below, which we use to probe the devices to not rely on // the blkid cache: // https://github.com/coreos/fedora-coreos-config/pull/2181#issuecomment-1397386896 - let devices = { - let mut cmd = Command::new("blkid"); - cmd.arg("--cache-file"); - cmd.arg("/dev/null"); - cmd.arg("-o"); - cmd.arg("device"); - cmd_output(&mut cmd)? - }; + let mut cmd_dev: Vec<&Path> = Vec::new(); + let devices; + if dev.is_none() { + devices = { + let mut cmd = Command::new("blkid"); + cmd.arg("--cache-file"); + cmd.arg("/dev/null"); + cmd.arg("-o"); + cmd.arg("device"); + cmd_output(&mut cmd)? + }; + cmd_dev.extend(devices + .lines() + .filter_map(|line|Some(Path::new(line.trim()))) + ); + } else { + if let Some(path) = dev { + cmd_dev.extend(path); + } + } let output = { let mut cmd = Command::new("blkid"); cmd.arg("-p"); - cmd.args(devices.lines()); + cmd.args(cmd_dev); cmd_output(&mut cmd)? }; @@ -1141,10 +1175,13 @@ fn disk_has_mbr(file: &mut (impl Read + Seek)) -> Result { Ok(sig == [0x55, 0xaa]) } +pub fn have_udev() -> bool { + Path::new("/run/udev/control").exists() +} pub fn udev_settle() -> Result<()> { // "udevadm settle" silently no-ops if the udev socket is missing, and // then lsblk can't find partition labels. Catch this early. - if !Path::new("/run/udev/control").exists() { + if !have_udev() { bail!("udevd socket missing; are we running in a container without /run/udev mounted?"); }