Skip to content

Commit

Permalink
Merge openebs#458
Browse files Browse the repository at this point in the history
458: CAS-461 support enumerating host block devices r=cjones1024 a=cjones1024

Initial support for enumerating block devices on a host.

Co-authored-by: Colin Jones <[email protected]>
  • Loading branch information
mayastor-bors and cjones1024 committed Oct 12, 2020
2 parents bdd5243 + d2934c4 commit 5dbaf6d
Show file tree
Hide file tree
Showing 10 changed files with 575 additions and 1 deletion.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions mayastor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ log = "0.4"
nix = "0.16"
once_cell = "1.3.1"
pin-utils = "0.1"
proc-mounts = "0.2"
prost = "0.6"
prost-derive = "0.6"
prost-types = "0.6"
Expand All @@ -72,6 +73,7 @@ tracing = "0.1"
tracing-futures = "0.2.4"
tracing-log = "0.1.1"
tracing-subscriber = "0.2.0"
udev = "0.4"
url = "2.1"
smol = "1.0.0"
dns-lookup = "1.0.4"
Expand Down
3 changes: 3 additions & 0 deletions mayastor/src/bin/cli/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::context::Context;

mod bdev_cli;
mod context;
mod device_cli;
mod nexus_child_cli;
mod nexus_cli;
mod pool_cli;
Expand Down Expand Up @@ -77,6 +78,7 @@ async fn main() -> Result<(), Status> {
.subcommand(nexus_cli::subcommands())
.subcommand(replica_cli::subcommands())
.subcommand(bdev_cli::subcommands())
.subcommand(device_cli::subcommands())
.subcommand(rebuild_cli::subcommands())
.subcommand(snapshot_cli::subcommands())
.get_matches();
Expand All @@ -85,6 +87,7 @@ async fn main() -> Result<(), Status> {

match matches.subcommand() {
("bdev", Some(args)) => bdev_cli::handler(ctx, args).await?,
("device", Some(args)) => device_cli::handler(ctx, args).await?,
("nexus", Some(args)) => nexus_cli::handler(ctx, args).await?,
("pool", Some(args)) => pool_cli::handler(ctx, args).await?,
("replica", Some(args)) => replica_cli::handler(ctx, args).await?,
Expand Down
185 changes: 185 additions & 0 deletions mayastor/src/bin/cli/device_cli.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
//!
//! methods to obtain information about block devices on the current host
use super::context::Context;
use ::rpc::mayastor as rpc;
use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
use colored_json::ToColoredJson;
use tonic::Status;

pub fn subcommands<'a, 'b>() -> App<'a, 'b> {
let list = SubCommand::with_name("list")
.about("List available (ie. unused) block devices")
.arg(
Arg::with_name("all")
.short("a")
.long("all")
.takes_value(false)
.help("List all block devices (ie. also include devices currently in use)"),
)
.arg(
Arg::with_name("raw")
.long("raw")
.takes_value(false)
.help("Display output as raw JSON"),
);

SubCommand::with_name("device")
.settings(&[
AppSettings::SubcommandRequiredElseHelp,
AppSettings::ColoredHelp,
AppSettings::ColorAlways,
])
.about("Host devices")
.subcommand(list)
}

pub async fn handler(
ctx: Context,
matches: &ArgMatches<'_>,
) -> Result<(), Status> {
match matches.subcommand() {
("list", Some(args)) => list_block_devices(ctx, args).await,
(cmd, _) => {
Err(Status::not_found(format!("command {} does not exist", cmd)))
}
}
}

fn get_partition_type(device: &rpc::BlockDevice) -> String {
if let Some(partition) = &device.partition {
format!("{}:{}", partition.scheme, partition.typeid)
} else {
String::from("")
}
}

async fn list_block_devices(
mut ctx: Context,
matches: &ArgMatches<'_>,
) -> Result<(), Status> {
let all = matches.is_present("all");

ctx.v2(&format!(
"Requesting list of {} block devices",
if all { "all" } else { "available" }
));

let reply = ctx
.client
.list_block_devices(rpc::ListBlockDevicesRequest {
all,
})
.await?;

if matches.is_present("raw") {
println!(
"{}",
serde_json::to_string_pretty(&reply.into_inner())
.unwrap()
.to_colored_json_auto()
.unwrap()
);
return Ok(());
}

let devices: &Vec<rpc::BlockDevice> = &reply.get_ref().devices;

if devices.is_empty() {
ctx.v1("No devices found");
return Ok(());
}

if all {
let table = devices
.iter()
.map(|device| {
let fstype: String;
let uuid: String;
let mountpoint: String;

if let Some(filesystem) = &device.filesystem {
fstype = filesystem.fstype.clone();
uuid = filesystem.uuid.clone();
mountpoint = filesystem.mountpoint.clone();
} else {
fstype = String::from("");
uuid = String::from("");
mountpoint = String::from("");
}

vec![
device.devname.clone(),
device.devtype.clone(),
device.devmajor.to_string(),
device.devminor.to_string(),
device.size.to_string(),
String::from(if device.available { "yes" } else { "no" }),
device.model.clone(),
get_partition_type(&device),
fstype,
uuid,
mountpoint,
device.devpath.clone(),
device
.devlinks
.iter()
.map(|s| format!("\"{}\"", s))
.collect::<Vec<String>>()
.join(" "),
]
})
.collect();

ctx.print_list(
vec![
"DEVNAME",
"DEVTYPE",
">MAJOR",
"MINOR",
">SIZE",
"AVAILABLE",
"MODEL",
"PARTTYPE",
"FSTYPE",
"FSUUID",
"MOUNTPOINT",
"DEVPATH",
"DEVLINKS",
],
table,
);
} else {
let table = devices
.iter()
.map(|device| {
vec![
device.devname.clone(),
device.devtype.clone(),
device.devmajor.to_string(),
device.devminor.to_string(),
device.size.to_string(),
device.model.clone(),
get_partition_type(&device),
device.devpath.clone(),
device
.devlinks
.iter()
.map(|s| format!("\"{}\"", s))
.collect::<Vec<String>>()
.join(" "),
]
})
.collect();

ctx.print_list(
vec![
"DEVNAME", "DEVTYPE", ">MAJOR", "MINOR", ">SIZE", "MODEL",
"PARTTYPE", "DEVPATH", "DEVLINKS",
],
table,
);
}

Ok(())
}
14 changes: 14 additions & 0 deletions mayastor/src/grpc/mayastor_grpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use crate::{
sync_config,
GrpcResult,
},
host::blk_device,
};

#[derive(Debug)]
Expand Down Expand Up @@ -414,4 +415,17 @@ impl mayastor_server::Mayastor for MayastorSvc {
})
.await
}

#[instrument(level = "debug", err)]
async fn list_block_devices(
&self,
request: Request<ListBlockDevicesRequest>,
) -> GrpcResult<ListBlockDevicesReply> {
let args = request.into_inner();
let reply = ListBlockDevicesReply {
devices: blk_device::list_block_devices(args.all).await?,
};
trace!("{:?}", reply);
Ok(Response::new(reply))
}
}
Loading

0 comments on commit 5dbaf6d

Please sign in to comment.