Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions sled-diagnostics/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ libc.workspace = true
omicron-workspace-hack.workspace = true
once_cell.workspace = true
oxlog.workspace = true
parallel-task-set.workspace = true
rand.workspace = true
schemars.workspace = true
serde.workspace = true
Expand Down
124 changes: 82 additions & 42 deletions sled-diagnostics/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

//! Diagnostics for an Oxide sled that exposes common support commands.

use futures::{StreamExt, stream::FuturesUnordered};
use futures::StreamExt;
use futures::stream::FuturesUnordered;
use parallel_task_set::ParallelTaskSet;
use slog::Logger;

#[macro_use]
Expand All @@ -29,6 +31,9 @@ pub use crate::queries::{
};
use queries::*;

/// Max number of ptool commands to run in parallel
const MAX_PTOOL_PARALLELISM: usize = 50;

/// List all zones on a sled.
pub async fn zoneadm_info()
-> Result<SledDiagnosticsCmdOutput, SledDiagnosticsCmdError> {
Expand All @@ -38,33 +43,43 @@ pub async fn zoneadm_info()
/// Retrieve various `ipadm` command output for the system.
pub async fn ipadm_info()
-> Vec<Result<SledDiagnosticsCmdOutput, SledDiagnosticsCmdError>> {
[ipadm_show_interface(), ipadm_show_addr(), ipadm_show_prop()]
.into_iter()
.map(|c| async move {
execute_command_with_timeout(c, DEFAULT_TIMEOUT).await
})
.collect::<FuturesUnordered<_>>()
.collect::<Vec<Result<_, _>>>()
.await
let mut results = Vec::new();
let mut commands = ParallelTaskSet::new();
for command in
[ipadm_show_interface(), ipadm_show_addr(), ipadm_show_prop()]
{
if let Some(res) = commands
.spawn(execute_command_with_timeout(command, DEFAULT_TIMEOUT))
.await
{
results.push(res);
}
}
results.extend(commands.join_all().await);
results
}

/// Retrieve various `dladm` command output for the system.
pub async fn dladm_info()
-> Vec<Result<SledDiagnosticsCmdOutput, SledDiagnosticsCmdError>> {
[
let mut results = Vec::new();
let mut commands = ParallelTaskSet::new();
for command in [
dladm_show_phys(),
dladm_show_ether(),
dladm_show_link(),
dladm_show_vnic(),
dladm_show_linkprop(),
]
.into_iter()
.map(|c| async move {
execute_command_with_timeout(c, DEFAULT_TIMEOUT).await
})
.collect::<FuturesUnordered<_>>()
.collect::<Vec<Result<_, _>>>()
.await
] {
if let Some(res) = commands
.spawn(execute_command_with_timeout(command, DEFAULT_TIMEOUT))
.await
{
results.push(res);
}
}
results.extend(commands.join_all().await);
results
}

pub async fn nvmeadm_info()
Expand All @@ -83,14 +98,23 @@ pub async fn pargs_oxide_processes(
Err(e) => return vec![Err(e.into())],
};

pids.iter()
.map(|pid| pargs_process(*pid))
.map(|c| async move {
execute_command_with_timeout(c, DEFAULT_TIMEOUT).await
})
.collect::<FuturesUnordered<_>>()
.collect::<Vec<Result<_, _>>>()
.await
let mut results = Vec::new();
let mut commands =
ParallelTaskSet::new_with_parallelism(MAX_PTOOL_PARALLELISM);
for pid in pids {
if let Some(res) = commands
.spawn(execute_command_with_timeout(
pargs_process(pid),
DEFAULT_TIMEOUT,
))
.await
{
results.push(res);
}
}

results.extend(commands.join_all().await);
results
}

pub async fn pstack_oxide_processes(
Expand All @@ -104,14 +128,22 @@ pub async fn pstack_oxide_processes(
Err(e) => return vec![Err(e.into())],
};

pids.iter()
.map(|pid| pstack_process(*pid))
.map(|c| async move {
execute_command_with_timeout(c, DEFAULT_TIMEOUT).await
})
.collect::<FuturesUnordered<_>>()
.collect::<Vec<Result<_, _>>>()
.await
let mut results = Vec::new();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit, here and below, you could use Vec::with_capacity(pids.len())

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 10de4e4

let mut commands =
ParallelTaskSet::new_with_parallelism(MAX_PTOOL_PARALLELISM);
for pid in pids {
if let Some(res) = commands
.spawn(execute_command_with_timeout(
pstack_process(pid),
DEFAULT_TIMEOUT,
))
.await
{
results.push(res);
}
}
results.extend(commands.join_all().await);
results
}

pub async fn pfiles_oxide_processes(
Expand All @@ -125,14 +157,22 @@ pub async fn pfiles_oxide_processes(
Err(e) => return vec![Err(e.into())],
};

pids.iter()
.map(|pid| pfiles_process(*pid))
.map(|c| async move {
execute_command_with_timeout(c, DEFAULT_TIMEOUT).await
})
.collect::<FuturesUnordered<_>>()
.collect::<Vec<Result<_, _>>>()
.await
let mut results = Vec::new();
let mut commands =
ParallelTaskSet::new_with_parallelism(MAX_PTOOL_PARALLELISM);
for pid in pids {
if let Some(res) = commands
.spawn(execute_command_with_timeout(
pfiles_process(pid),
DEFAULT_TIMEOUT,
))
.await
{
results.push(res);
}
}
results.extend(commands.join_all().await);
results
}

/// Retrieve various `zfs` command output for the system.
Expand Down
Loading