Skip to content

Commit 463a368

Browse files
authored
[sled-agent] Add support for Support Bundle command execution (#7011)
This PR lays the groundwork for executing system commands and returning their output as raw data (both on success and failure) via the internal sled-agent HTTP API. Command execution collects both stdout and stdout in an interleaved fashion so that the command output is exactly how an operator would have seen it if they were sitting at the terminal.
1 parent 15305ae commit 463a368

File tree

8 files changed

+358
-1
lines changed

8 files changed

+358
-1
lines changed

illumos-utils/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ pub mod zone;
3434
pub mod zpool;
3535

3636
pub const PFEXEC: &str = "/usr/bin/pfexec";
37+
pub const ZONEADM: &str = "/usr/sbin/zoneadm";
3738

3839
#[derive(Debug)]
3940
pub struct CommandFailureInfo {

openapi/sled-agent.json

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,48 @@
673673
}
674674
}
675675
},
676+
"/support/ipadm-info": {
677+
"get": {
678+
"operationId": "support_ipadm_info",
679+
"responses": {
680+
"200": {
681+
"description": "",
682+
"content": {
683+
"*/*": {
684+
"schema": {}
685+
}
686+
}
687+
},
688+
"4XX": {
689+
"$ref": "#/components/responses/Error"
690+
},
691+
"5XX": {
692+
"$ref": "#/components/responses/Error"
693+
}
694+
}
695+
}
696+
},
697+
"/support/zoneadm-info": {
698+
"get": {
699+
"operationId": "support_zoneadm_info",
700+
"responses": {
701+
"200": {
702+
"description": "",
703+
"content": {
704+
"*/*": {
705+
"schema": {}
706+
}
707+
}
708+
},
709+
"4XX": {
710+
"$ref": "#/components/responses/Error"
711+
},
712+
"5XX": {
713+
"$ref": "#/components/responses/Error"
714+
}
715+
}
716+
}
717+
},
676718
"/switch-ports": {
677719
"post": {
678720
"operationId": "uplink_ensure",

sled-agent/api/src/lib.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,22 @@ pub trait SledAgentApi {
529529
request_context: RequestContext<Self::Context>,
530530
body: TypedBody<ExternalIpGatewayMap>,
531531
) -> Result<HttpResponseUpdatedNoContent, HttpError>;
532+
533+
#[endpoint {
534+
method = GET,
535+
path = "/support/zoneadm-info",
536+
}]
537+
async fn support_zoneadm_info(
538+
request_context: RequestContext<Self::Context>,
539+
) -> Result<HttpResponseOk<FreeformBody>, HttpError>;
540+
541+
#[endpoint {
542+
method = GET,
543+
path = "/support/ipadm-info",
544+
}]
545+
async fn support_ipadm_info(
546+
request_context: RequestContext<Self::Context>,
547+
) -> Result<HttpResponseOk<FreeformBody>, HttpError>;
532548
}
533549

534550
#[derive(Clone, Debug, Deserialize, JsonSchema, Serialize)]

sled-agent/src/http_entrypoints.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
77
use super::sled_agent::SledAgent;
88
use crate::sled_agent::Error as SledAgentError;
9+
use crate::support_bundle::SupportBundleCommandHttpOutput;
910
use crate::zone_bundle::BundleError;
1011
use bootstore::schemes::v0::NetworkConfig;
1112
use camino::Utf8PathBuf;
@@ -770,4 +771,28 @@ impl SledAgentApi for SledAgentImpl {
770771
sa.set_eip_gateways(body.into_inner()).await?;
771772
Ok(HttpResponseUpdatedNoContent())
772773
}
774+
775+
async fn support_zoneadm_info(
776+
request_context: RequestContext<Self::Context>,
777+
) -> Result<HttpResponseOk<FreeformBody>, HttpError> {
778+
let sa = request_context.context();
779+
let res = sa.support_zoneadm_info().await;
780+
Ok(HttpResponseOk(FreeformBody(res.get_output().into())))
781+
}
782+
783+
async fn support_ipadm_info(
784+
request_context: RequestContext<Self::Context>,
785+
) -> Result<HttpResponseOk<FreeformBody>, HttpError> {
786+
let sa = request_context.context();
787+
let output = sa
788+
.support_ipadm_info()
789+
.await
790+
.into_iter()
791+
.map(|cmd| cmd.get_output())
792+
.collect::<Vec<_>>()
793+
.as_slice()
794+
.join("\n\n");
795+
796+
Ok(HttpResponseOk(FreeformBody(output.into())))
797+
}
773798
}

sled-agent/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub mod server;
3636
pub mod services;
3737
mod sled_agent;
3838
mod storage_monitor;
39+
mod support_bundle;
3940
mod swap_device;
4041
mod updates;
4142
mod vmm_reservoir;

sled-agent/src/sim/http_entrypoints.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,18 @@ impl SledAgentApi for SledAgentSimImpl {
542542
) -> Result<HttpResponseOk<BootstoreStatus>, HttpError> {
543543
method_unimplemented()
544544
}
545+
546+
async fn support_zoneadm_info(
547+
_request_context: RequestContext<Self::Context>,
548+
) -> Result<HttpResponseOk<FreeformBody>, HttpError> {
549+
method_unimplemented()
550+
}
551+
552+
async fn support_ipadm_info(
553+
_request_context: RequestContext<Self::Context>,
554+
) -> Result<HttpResponseOk<FreeformBody>, HttpError> {
555+
method_unimplemented()
556+
}
545557
}
546558

547559
fn method_unimplemented<T>() -> Result<T, HttpError> {

sled-agent/src/sled_agent.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@ use crate::params::OmicronZoneTypeExt;
1919
use crate::probe_manager::ProbeManager;
2020
use crate::services::{self, ServiceManager};
2121
use crate::storage_monitor::StorageMonitorHandle;
22+
use crate::support_bundle::{SupportBundleCmdError, SupportBundleCmdOutput};
2223
use crate::updates::{ConfigUpdates, UpdateManager};
2324
use crate::vmm_reservoir::{ReservoirMode, VmmReservoirManager};
24-
use crate::zone_bundle;
2525
use crate::zone_bundle::BundleError;
26+
use crate::{support_bundle, zone_bundle};
2627
use bootstore::schemes::v0 as bootstore;
2728
use camino::Utf8PathBuf;
2829
use derive_more::From;
@@ -1350,6 +1351,18 @@ impl SledAgent {
13501351
datasets,
13511352
})
13521353
}
1354+
1355+
pub(crate) async fn support_zoneadm_info(
1356+
&self,
1357+
) -> Result<SupportBundleCmdOutput, SupportBundleCmdError> {
1358+
support_bundle::zoneadm_info().await
1359+
}
1360+
1361+
pub(crate) async fn support_ipadm_info(
1362+
&self,
1363+
) -> Vec<Result<SupportBundleCmdOutput, SupportBundleCmdError>> {
1364+
support_bundle::ipadm_info().await
1365+
}
13531366
}
13541367

13551368
#[derive(From, thiserror::Error, Debug)]

0 commit comments

Comments
 (0)