Skip to content

Commit

Permalink
[sled-agent] WIP pargs/pstack of oxide processes
Browse files Browse the repository at this point in the history
  • Loading branch information
papertigers committed Nov 20, 2024
1 parent 69de8b6 commit 85fb330
Show file tree
Hide file tree
Showing 12 changed files with 335 additions and 30 deletions.
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.

2 changes: 2 additions & 0 deletions illumos-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ pub mod zpool;

pub const PFEXEC: &str = "/usr/bin/pfexec";
pub const ZONEADM: &str = "/usr/sbin/zoneadm";
pub const PARGS: &str = "/usr/bin/pargs";
pub const PSTACK: &str = "/usr/bin/pstack";

#[derive(Debug)]
pub struct CommandFailureInfo {
Expand Down
2 changes: 1 addition & 1 deletion illumos-utils/src/zone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::{execute, PFEXEC};
use omicron_common::address::SLED_PREFIX;
use omicron_uuid_kinds::OmicronZoneUuid;

const DLADM: &str = "/usr/sbin/dladm";
pub const DLADM: &str = "/usr/sbin/dladm";
pub const IPADM: &str = "/usr/sbin/ipadm";
pub const SVCADM: &str = "/usr/sbin/svcadm";
pub const SVCCFG: &str = "/usr/sbin/svccfg";
Expand Down
42 changes: 42 additions & 0 deletions openapi/sled-agent.json
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,48 @@
}
}
},
"/support/pargs-info": {
"get": {
"operationId": "support_pargs_info",
"responses": {
"200": {
"description": "",
"content": {
"*/*": {
"schema": {}
}
}
},
"4XX": {
"$ref": "#/components/responses/Error"
},
"5XX": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/support/pstack-info": {
"get": {
"operationId": "support_pstack_info",
"responses": {
"200": {
"description": "",
"content": {
"*/*": {
"schema": {}
}
}
},
"4XX": {
"$ref": "#/components/responses/Error"
},
"5XX": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/support/zoneadm-info": {
"get": {
"operationId": "support_zoneadm_info",
Expand Down
1 change: 1 addition & 0 deletions sled-agent/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ display-error-chain.workspace = true
dropshot.workspace = true
flate2.workspace = true
flume.workspace = true
fs-err.workspace = true
futures.workspace = true
glob.workspace = true
hex.workspace = true
Expand Down
16 changes: 16 additions & 0 deletions sled-agent/api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,22 @@ pub trait SledAgentApi {
async fn support_ipadm_info(
request_context: RequestContext<Self::Context>,
) -> Result<HttpResponseOk<FreeformBody>, HttpError>;

#[endpoint {
method = GET,
path = "/support/pargs-info",
}]
async fn support_pargs_info(
request_context: RequestContext<Self::Context>,
) -> Result<HttpResponseOk<FreeformBody>, HttpError>;

#[endpoint {
method = GET,
path = "/support/pstack-info",
}]
async fn support_pstack_info(
request_context: RequestContext<Self::Context>,
) -> Result<HttpResponseOk<FreeformBody>, HttpError>;
}

#[derive(Clone, Debug, Deserialize, JsonSchema, Serialize)]
Expand Down
34 changes: 33 additions & 1 deletion sled-agent/src/http_entrypoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
use super::sled_agent::SledAgent;
use crate::sled_agent::Error as SledAgentError;
use crate::support_bundle::SupportBundleCommandHttpOutput;
use crate::support_bundle::command::SupportBundleCommandHttpOutput;
use crate::zone_bundle::BundleError;
use bootstore::schemes::v0::NetworkConfig;
use camino::Utf8PathBuf;
Expand Down Expand Up @@ -795,4 +795,36 @@ impl SledAgentApi for SledAgentImpl {

Ok(HttpResponseOk(FreeformBody(output.into())))
}

async fn support_pargs_info(
request_context: RequestContext<Self::Context>,
) -> Result<HttpResponseOk<FreeformBody>, HttpError> {
let sa = request_context.context();
let output = sa
.support_pargs_info()
.await
.into_iter()
.map(|cmd| cmd.get_output())
.collect::<Vec<_>>()
.as_slice()
.join("\n\n");

Ok(HttpResponseOk(FreeformBody(output.into())))
}

async fn support_pstack_info(
request_context: RequestContext<Self::Context>,
) -> Result<HttpResponseOk<FreeformBody>, HttpError> {
let sa = request_context.context();
let output = sa
.support_pstack_info()
.await
.into_iter()
.map(|cmd| cmd.get_output())
.collect::<Vec<_>>()
.as_slice()
.join("\n\n");

Ok(HttpResponseOk(FreeformBody(output.into())))
}
}
12 changes: 12 additions & 0 deletions sled-agent/src/sim/http_entrypoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,18 @@ impl SledAgentApi for SledAgentSimImpl {
) -> Result<HttpResponseOk<FreeformBody>, HttpError> {
method_unimplemented()
}

async fn support_pargs_info(
_request_context: RequestContext<Self::Context>,
) -> Result<HttpResponseOk<FreeformBody>, HttpError> {
method_unimplemented()
}

async fn support_pstack_info(
_request_context: RequestContext<Self::Context>,
) -> Result<HttpResponseOk<FreeformBody>, HttpError> {
method_unimplemented()
}
}

fn method_unimplemented<T>() -> Result<T, HttpError> {
Expand Down
12 changes: 12 additions & 0 deletions sled-agent/src/sled_agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1363,6 +1363,18 @@ impl SledAgent {
) -> Vec<Result<SupportBundleCmdOutput, SupportBundleCmdError>> {
support_bundle::ipadm_info().await
}

pub(crate) async fn support_pargs_info(
&self,
) -> Vec<Result<SupportBundleCmdOutput, SupportBundleCmdError>> {
support_bundle::pargs_oxide_processes().await
}

pub(crate) async fn support_pstack_info(
&self,
) -> Vec<Result<SupportBundleCmdOutput, SupportBundleCmdError>> {
support_bundle::pstack_oxide_processes().await
}
}

#[derive(From, thiserror::Error, Debug)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use std::{process::Command, time::Duration};

use futures::{stream::FuturesUnordered, StreamExt};
use illumos_utils::{zone::IPADM, PFEXEC, ZONEADM};
use illumos_utils::{zone::IPADM, PARGS, PFEXEC, PSTACK, ZONEADM};
use thiserror::Error;
use tokio::io::AsyncReadExt;

const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10);
pub const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10);

pub trait SupportBundleCommandHttpOutput {
fn get_output(self) -> String;
Expand Down Expand Up @@ -122,7 +121,7 @@ async fn execute(
}

/// Spawn a command that's allowed to execute within a given time limit.
async fn execute_command_with_timeout(
pub async fn execute_command_with_timeout(
command: Command,
duration: Duration,
) -> Result<SupportBundleCmdOutput, SupportBundleCmdError> {
Expand All @@ -137,58 +136,47 @@ async fn execute_command_with_timeout(
}
}

fn zoneadm_list() -> Command {
pub fn zoneadm_list() -> Command {
let mut cmd = std::process::Command::new(PFEXEC);
cmd.env_clear().arg(ZONEADM).arg("list").arg("-cip");
cmd
}

fn ipadm_show_interface() -> Command {
pub fn ipadm_show_interface() -> Command {
let mut cmd = std::process::Command::new(PFEXEC);
cmd.env_clear().arg(IPADM).arg("show-if");
cmd
}

fn ipadm_show_addr() -> Command {
pub fn ipadm_show_addr() -> Command {
let mut cmd = std::process::Command::new(PFEXEC);
cmd.env_clear().arg(IPADM).arg("show-addr");
cmd
}

fn ipadm_show_prop() -> Command {
pub fn ipadm_show_prop() -> Command {
let mut cmd = std::process::Command::new(PFEXEC);
cmd.env_clear().arg(IPADM).arg("show-prop");
cmd
}

/*
* Public API
*/

/// List all zones on a sled.
pub async fn zoneadm_info(
) -> Result<SupportBundleCmdOutput, SupportBundleCmdError> {
execute_command_with_timeout(zoneadm_list(), DEFAULT_TIMEOUT).await
pub fn pargs_process(pid: i32) -> Command {
let mut cmd = std::process::Command::new(PFEXEC);
cmd.env_clear().arg(PARGS).arg("-ae").arg(pid.to_string());
cmd
}

/// Retrieve various `ipadm` command output for the system.
pub async fn ipadm_info(
) -> Vec<Result<SupportBundleCmdOutput, SupportBundleCmdError>> {
[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<SupportBundleCmdOutput, SupportBundleCmdError>>>()
.await
pub fn pstack_process(pid: i32) -> Command {
let mut cmd = std::process::Command::new(PFEXEC);
cmd.env_clear().arg(PSTACK).arg(pid.to_string());
cmd
}

#[cfg(test)]
mod test {
use std::{process::Command, time::Duration};

use crate::support_bundle::*;
use crate::support_bundle::command::*;

#[tokio::test]
async fn test_long_running_command_is_aborted() {
Expand Down
Loading

0 comments on commit 85fb330

Please sign in to comment.