Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use blkid instead of lsblk to get disk info when udev is not present #1511

Merged
merged 1 commit into from
Sep 4, 2024

Conversation

ravanelli
Copy link
Member

  • 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, we
    need to skip this part and pass only the fstype
    for the it to be mounted.

Copy link
Member

@jlebon jlebon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, how about instead, we keep the interface the same (no new command-line arguments), but in get_partitions, we check if udev is present (e.g. check for /run/udev/control; we have code that does something similar already), and if so then use lsblk(), otherwise use blkid().

Both return a Result<Vec<HashMap<String, String>>> we can iterate over. But of course in the blkid case, some of the key names to pull from will be different.

src/osmet/mod.rs Outdated Show resolved Hide resolved
@jlebon
Copy link
Member

jlebon commented Aug 13, 2024

Both return a Result<Vec<HashMap<String, String>>> we can iterate over. But of course in the blkid case, some of the key names to pull from will be different.

Though I think this is glossing over an important detail. blkid() will return information about all devices, whereas lsblk() only returns information about the passed device. Since we can still use lsblk() at least to get the list of partitions on the disk, we can then call a blkid_single() that only does blkid on one device (or just change blkid() to take an dev: Option<String>) to get the info we need. So basically something like:

fn get_partitions(&self) -> Result<Vec<Partition>> {
    // walk each device in the output
    let mut result: Vec<Partition> = Vec::new();
    for devinfo in lsblk(Path::new(&self.path), true)? {
        if let Some(name) = devinfo.get("NAME") {
            // Only return partitions.  Skip the whole-disk device, as well
            // as holders like LVM or RAID devices using one of the partitions.
            if devinfo.get("TYPE").map(|s| s.as_str()) != Some("part") {
                continue;
            }
            // 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(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,
                    parent: self.path.to_owned(),
                    None,
                    fstype.is_some_and(|s| s == "swap"),
                });
            }
        }
    }
    Ok(result)
}

@ravanelli
Copy link
Member Author

Though I think this is glossing over an important detail. blkid()

Great, in the current code I used bklid for a single device as well adding the dev path:

     Command::new("blkid");
      cmd.arg(path);

Fixing the rest ;)

@ravanelli ravanelli changed the title Add root and boot option for osmet image Use blkid instead of lsblk to get disk info when udev is not present Aug 14, 2024
@ravanelli ravanelli marked this pull request as ready for review August 14, 2024 18:27
docs/release-notes.md Outdated Show resolved Hide resolved
src/blockdev.rs Outdated Show resolved Hide resolved
src/blockdev.rs Outdated Show resolved Hide resolved
src/blockdev.rs Outdated Show resolved Hide resolved
src/blockdev.rs Outdated Show resolved Hide resolved
@ravanelli ravanelli force-pushed the liveiso branch 2 times, most recently from 9ecd906 to f4aa1bc Compare August 21, 2024 01:23
src/blockdev.rs Outdated Show resolved Hide resolved
src/blockdev.rs Outdated Show resolved Hide resolved
src/blockdev.rs Outdated

cmd_dev.extend(devices
.lines()
.filter_map(|line|Some(Path::new(line.trim())))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can just use map here if we don't need filtering functionality.

@@ -1141,10 +1175,13 @@ fn disk_has_mbr(file: &mut (impl Read + Seek)) -> Result<bool> {
Ok(sig == [0x55, 0xaa])
}

pub fn have_udev() -> bool {
Path::new("/run/udev/control").exists()
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: spacing

src/blockdev.rs Outdated
Comment on lines 918 to 938
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);
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A more idiomatic way to restructure all this is:

let cmd_dev = if let Some(paths) = dev {
    paths
} else {
    let devices = {
        ...
    };
    devices.lines().map(|line| Path::new(line.trim())).collect()
};

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the free rust class @jlebon ;)

@ravanelli ravanelli force-pushed the liveiso branch 2 times, most recently from d73ae86 to 0c30375 Compare September 2, 2024 17:17
- 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 <[email protected]>
Copy link
Member

@jlebon jlebon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just added spacing and tweaked some of the variable names.

LGTM!

@jlebon jlebon merged commit 26f2d8a into coreos:main Sep 4, 2024
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants