src/tools/disks.rs: implement get_disks (similar to the one in PVE::Diskmanage)
But no ceph support for now. Also no support for old cciss block devices.
This commit is contained in:
parent
f03a0e509e
commit
c26aad405f
|
@ -562,3 +562,202 @@ pub fn get_partition_type_info() -> Result<HashMap<String, Vec<String>>, Error>
|
|||
}
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum DiskUsageType {
|
||||
Unused,
|
||||
Mounted,
|
||||
LVM,
|
||||
ZFS,
|
||||
DeviceMapper,
|
||||
Partitions,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DiskUsageInfo {
|
||||
pub name: String,
|
||||
pub used: DiskUsageType,
|
||||
pub disk_type: DiskType,
|
||||
pub vendor: Option<String>,
|
||||
pub model: Option<String>,
|
||||
pub wwn: Option<String>,
|
||||
pub size: u64,
|
||||
pub serial: Option<String>,
|
||||
pub devpath: Option<std::path::PathBuf>,
|
||||
pub gpt: bool,
|
||||
pub rpm: Option<u64>,
|
||||
}
|
||||
|
||||
fn scan_partitions(
|
||||
disk_manager: Arc<DiskManage>,
|
||||
lvm_devices: &HashSet<String>,
|
||||
zfs_devices: &HashSet<String>,
|
||||
device: &str,
|
||||
) -> Result<DiskUsageType, Error> {
|
||||
|
||||
let mut sys_path = std::path::PathBuf::from("/sys/block");
|
||||
sys_path.push(device);
|
||||
|
||||
let mut used = DiskUsageType::Unused;
|
||||
|
||||
let mut found_lvm = false;
|
||||
let mut found_zfs = false;
|
||||
let mut found_mountpoints = false;
|
||||
let mut found_dm = false;
|
||||
let mut found_partitions = false;
|
||||
|
||||
for item in crate::tools::fs::read_subdir(libc::AT_FDCWD, &sys_path)? {
|
||||
let item = item?;
|
||||
let name = match item.file_name().to_str() {
|
||||
Ok(name) => name,
|
||||
Err(_) => continue, // skip non utf8 entries
|
||||
};
|
||||
if !name.starts_with(device) { continue; }
|
||||
|
||||
found_partitions = true;
|
||||
|
||||
let mut part_path = sys_path.clone();
|
||||
part_path.push(name);
|
||||
|
||||
let data = disk_manager.clone().disk_by_sys_path(&part_path)?;
|
||||
|
||||
if lvm_devices.contains(name) {
|
||||
found_lvm = true;
|
||||
}
|
||||
|
||||
if data.is_mounted()? {
|
||||
found_mountpoints = true;
|
||||
}
|
||||
|
||||
if data.has_holders()? {
|
||||
found_dm = true;
|
||||
}
|
||||
|
||||
if zfs_devices.contains(name) {
|
||||
found_zfs = true;
|
||||
}
|
||||
}
|
||||
|
||||
if found_mountpoints {
|
||||
used = DiskUsageType::Mounted;
|
||||
} else if found_lvm {
|
||||
used = DiskUsageType::LVM;
|
||||
} else if found_zfs {
|
||||
used = DiskUsageType::ZFS;
|
||||
} else if found_dm {
|
||||
used = DiskUsageType::DeviceMapper;
|
||||
} else if found_partitions {
|
||||
used = DiskUsageType::Partitions;
|
||||
}
|
||||
|
||||
Ok(used)
|
||||
}
|
||||
|
||||
pub fn get_disks(
|
||||
// filter - list of device names (without leading /dev)
|
||||
disks: Option<Vec<String>>,
|
||||
// do no include data from smartctl
|
||||
no_smart: bool,
|
||||
) -> Result<HashMap<String, DiskUsageInfo>, Error> {
|
||||
|
||||
let disk_manager = DiskManage::new();
|
||||
|
||||
let partition_type_map = get_partition_type_info()?;
|
||||
|
||||
let zfs_devices = zfs_devices(&partition_type_map, None)?;
|
||||
|
||||
let lvm_devices = get_lvm_devices(&partition_type_map)?;
|
||||
|
||||
// fixme: ceph journals/volumes
|
||||
|
||||
lazy_static::lazy_static!{
|
||||
static ref ISCSI_PATH_REGEX: regex::Regex =
|
||||
regex::Regex::new(r"host[^/]*/session[^/]*").unwrap();
|
||||
static ref BLOCKDEV_REGEX: regex::Regex =
|
||||
regex::Regex::new(r"^(:?(:?h|s|x?v)d[a-z]+)|(:?nvme\d+n\d+)$").unwrap();
|
||||
}
|
||||
|
||||
let mut result = HashMap::new();
|
||||
|
||||
for item in crate::tools::fs::scan_subdir(libc::AT_FDCWD, "/sys/block", &BLOCKDEV_REGEX)? {
|
||||
let item = item?;
|
||||
|
||||
let name = item.file_name().to_str().unwrap().to_string();
|
||||
|
||||
if let Some(ref disks) = disks {
|
||||
if !disks.contains(&name) { continue; }
|
||||
}
|
||||
|
||||
let sys_path = format!("/sys/block/{}", name);
|
||||
|
||||
if let Ok(target) = std::fs::read_link(&sys_path) {
|
||||
if let Some(target) = target.to_str() {
|
||||
if ISCSI_PATH_REGEX.is_match(target) { continue; } // skip iSCSI devices
|
||||
}
|
||||
}
|
||||
|
||||
let data = disk_manager.clone().disk_by_sys_path(&sys_path)?;
|
||||
|
||||
let size = match data.size() {
|
||||
Ok(size) => size,
|
||||
Err(_) => continue, // skip devices with unreadable size
|
||||
};
|
||||
|
||||
let disk_type = match data.guess_disk_type() {
|
||||
Ok(disk_type) => disk_type,
|
||||
Err(_) => continue, // skip devices with undetectable type
|
||||
};
|
||||
|
||||
let mut usage = DiskUsageType::Unused;
|
||||
|
||||
if lvm_devices.contains(&name) {
|
||||
usage = DiskUsageType::LVM;
|
||||
}
|
||||
|
||||
match data.is_mounted() {
|
||||
Ok(true) => usage = DiskUsageType::Mounted,
|
||||
Ok(false) => {},
|
||||
Err(_) => continue, // skip devices with undetectable mount status
|
||||
}
|
||||
|
||||
if zfs_devices.contains(&name) {
|
||||
usage = DiskUsageType::ZFS;
|
||||
}
|
||||
|
||||
let vendor = data.vendor().unwrap_or(None).
|
||||
map(|s| s.to_string_lossy().trim().to_string());
|
||||
|
||||
let model = data.model().map(|s| s.to_string_lossy().into_owned());
|
||||
|
||||
let serial = data.serial().map(|s| s.to_string_lossy().into_owned());
|
||||
|
||||
let devpath = data.device_path().map(|p| p.to_owned());
|
||||
|
||||
let wwn = data.wwn().map(|s| s.to_string_lossy().into_owned());
|
||||
|
||||
if usage != DiskUsageType::Mounted {
|
||||
match scan_partitions(disk_manager.clone(), &lvm_devices, &zfs_devices, &name) {
|
||||
Ok(part_usage) => {
|
||||
if part_usage != DiskUsageType::Unused {
|
||||
usage = part_usage;
|
||||
}
|
||||
},
|
||||
Err(_) => continue, // skip devices if scan_partitions fail
|
||||
};
|
||||
}
|
||||
|
||||
let info = DiskUsageInfo {
|
||||
name: name.clone(),
|
||||
vendor, model, serial, devpath, size, wwn, disk_type,
|
||||
used: usage,
|
||||
gpt: data.has_gpt(),
|
||||
rpm: data.ata_rotation_rate_rpm(),
|
||||
};
|
||||
|
||||
println!("GOT {:?}", info);
|
||||
|
||||
result.insert(name, info);
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue