From 81c5d00412e83f556854e56eecf5125fda98aacc 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 | 88 +++++++++++++++++++++++++++++++------------ 2 files changed, 64 insertions(+), 25 deletions(-) diff --git a/docs/release-notes.md b/docs/release-notes.md index c79ea32f..1147b0a8 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 cb7fe551..504a5a73 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,17 @@ 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 +848,7 @@ fn get_all_filesystems(rereadpt: bool) -> Result>> { } udev_settle()?; } - blkid() + blkid(None) } /// Returns filesystems with given label. @@ -884,7 +910,7 @@ fn split_blkid_line(line: &str) -> HashMap { fields } -fn blkid() -> Result>> { +fn blkid(devices: 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 +919,27 @@ 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 found_devices; // need this for &Path refs to outlive the else block + let devices: Vec<&Path> = if let Some(paths) = devices { + paths + } else { + found_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)? + }; + found_devices + .lines() + .map(|line| Path::new(line.trim())) + .collect() }; - let output = { let mut cmd = Command::new("blkid"); cmd.arg("-p"); - cmd.args(devices.lines()); + cmd.args(devices); cmd_output(&mut cmd)? }; @@ -1141,10 +1175,14 @@ 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?"); }