Skip to content

Commit d848827

Browse files
leftwoAlan Hanson
andauthored
Added pantry support to omdb (#8513)
Allow omdb to connect to and query a pantry endpoint. Right now we support, status, volume <id>, and is-finished <job-id> --------- Co-authored-by: Alan Hanson <alan@oxide.computer>
1 parent 84c9ffe commit d848827

File tree

5 files changed

+182
-18
lines changed

5 files changed

+182
-18
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dev-tools/omdb/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ chrono.workspace = true
2020
clap.workspace = true
2121
crossterm.workspace = true
2222
crucible-agent-client.workspace = true
23+
crucible-pantry-client.workspace = true
2324
csv.workspace = true
2425
diesel.workspace = true
2526
dropshot.workspace = true
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
5+
//! omdb commands that query a crucible-pantry
6+
7+
use anyhow::Context;
8+
use anyhow::bail;
9+
use clap::Args;
10+
use clap::Subcommand;
11+
use crucible_pantry_client::Client;
12+
use crucible_pantry_client::types::VolumeStatus;
13+
use tabled::Tabled;
14+
use uuid::Uuid;
15+
16+
use crate::Omdb;
17+
use crate::helpers::CONNECTION_OPTIONS_HEADING;
18+
19+
/// Arguments to the "omdb crucible-pantry" subcommand
20+
#[derive(Debug, Args)]
21+
pub struct CruciblePantryArgs {
22+
/// URL of the crucible pantry internal API
23+
#[clap(
24+
long,
25+
env = "OMDB_CRUCIBLE_PANTRY_URL",
26+
global = true,
27+
help_heading = CONNECTION_OPTIONS_HEADING,
28+
)]
29+
crucible_pantry_url: Option<String>,
30+
31+
#[command(subcommand)]
32+
command: CruciblePantryCommands,
33+
}
34+
35+
/// Subcommands for the "omdb crucible-pantry" subcommand
36+
#[derive(Debug, Subcommand)]
37+
enum CruciblePantryCommands {
38+
/// Print information about a pantry jobs finished status
39+
IsFinished(FinishedArgs),
40+
/// Print information about the pantry
41+
Status,
42+
/// Print information about a specific volume
43+
Volume(VolumeArgs),
44+
}
45+
46+
#[derive(Debug, Args, Clone)]
47+
struct FinishedArgs {
48+
/// The Job ID
49+
id: String,
50+
}
51+
52+
#[derive(Debug, Args, Clone)]
53+
struct VolumeArgs {
54+
/// The UUID of the volume
55+
uuid: Uuid,
56+
}
57+
58+
impl CruciblePantryArgs {
59+
/// Run a `omdb crucible-pantry` subcommand.
60+
pub(crate) async fn run_cmd(
61+
&self,
62+
_omdb: &Omdb,
63+
) -> Result<(), anyhow::Error> {
64+
// The crucible pantry URL is required, but can come from the
65+
// environment, in which case it won't be on the command line.
66+
let Some(crucible_pantry_url) = &self.crucible_pantry_url else {
67+
bail!(
68+
"crucible pantry URL must be specified with \
69+
--crucible-pantry-url or by setting the environment variable \
70+
OMDB_CRUCIBLE_PANTRY_URL"
71+
);
72+
};
73+
let client = Client::new(crucible_pantry_url);
74+
75+
match &self.command {
76+
CruciblePantryCommands::IsFinished(id) => {
77+
cmd_is_finished(&client, id).await
78+
}
79+
CruciblePantryCommands::Status => cmd_pantry_status(&client).await,
80+
CruciblePantryCommands::Volume(uuid) => {
81+
cmd_volume_info(&client, uuid).await
82+
}
83+
}
84+
}
85+
}
86+
87+
/// Runs `omdb crucible-pantry volume`
88+
async fn cmd_is_finished(
89+
client: &crucible_pantry_client::Client,
90+
args: &FinishedArgs,
91+
) -> Result<(), anyhow::Error> {
92+
let is_finished =
93+
client.is_job_finished(&args.id).await.context("checking jobs")?;
94+
println!("Job: {} reports is_finished: {:?}", args.id, is_finished);
95+
Ok(())
96+
}
97+
98+
/// Runs `omdb crucible-pantry volume`
99+
async fn cmd_volume_info(
100+
client: &crucible_pantry_client::Client,
101+
args: &VolumeArgs,
102+
) -> Result<(), anyhow::Error> {
103+
let volume = args.uuid.to_string();
104+
let VolumeStatus { active, num_job_handles, seen_active } =
105+
*client.volume_status(&volume).await.context("listing volumes")?;
106+
107+
println!(" active: {}", active);
108+
println!(" num_job_handles: {}", num_job_handles);
109+
println!(" seen_active: {}", seen_active);
110+
Ok(())
111+
}
112+
113+
#[derive(Tabled)]
114+
#[tabled(rename_all = "SCREAMING_SNAKE_CASE")]
115+
struct VolumeInfo {
116+
volume_id: String,
117+
active: String,
118+
num_job_handles: String,
119+
seen_active: String,
120+
}
121+
122+
/// Runs `omdb crucible-pantry status`
123+
async fn cmd_pantry_status(
124+
client: &crucible_pantry_client::Client,
125+
) -> Result<(), anyhow::Error> {
126+
let status = client.pantry_status().await.context("listing volumes")?;
127+
128+
println!("num_job_handles {:?}", status.num_job_handles);
129+
println!("Volumes found: {}", status.volumes.len());
130+
131+
let mut rows = Vec::new();
132+
for v in &status.volumes {
133+
// let vs = client.volume_status(&v).await.context("listing volumes")?;
134+
match client.volume_status(&v).await.context("listing volumes") {
135+
Ok(vs) => {
136+
rows.push(VolumeInfo {
137+
volume_id: v.clone().to_string(),
138+
active: vs.active.clone().to_string(),
139+
num_job_handles: vs.num_job_handles.clone().to_string(),
140+
seen_active: vs.seen_active.clone().to_string(),
141+
});
142+
}
143+
Err(e) => {
144+
println!("Failed to get info for volume {v}: {e}");
145+
}
146+
}
147+
}
148+
let table = tabled::Table::new(rows)
149+
.with(tabled::settings::Style::empty())
150+
.with(tabled::settings::Padding::new(0, 1, 0, 0))
151+
.to_string();
152+
153+
println!("{}", table);
154+
155+
Ok(())
156+
}

dev-tools/omdb/src/bin/omdb/main.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ use std::net::SocketAddrV6;
4848
use tokio::net::TcpSocket;
4949

5050
mod crucible_agent;
51+
mod crucible_pantry;
5152
mod db;
5253
mod helpers;
5354
mod mgs;
@@ -82,6 +83,7 @@ async fn main_impl() -> Result<(), anyhow::Error> {
8283
}
8384
OmdbCommands::SledAgent(sled) => sled.run_cmd(&args, &log).await,
8485
OmdbCommands::CrucibleAgent(crucible) => crucible.run_cmd(&args).await,
86+
OmdbCommands::CruciblePantry(crucible) => crucible.run_cmd(&args).await,
8587
}
8688
}
8789

@@ -284,6 +286,8 @@ impl Omdb {
284286
enum OmdbCommands {
285287
/// Debug a specific crucible-agent
286288
CrucibleAgent(crucible_agent::CrucibleAgentArgs),
289+
/// Query a specific crucible-pantry
290+
CruciblePantry(crucible_pantry::CruciblePantryArgs),
287291
/// Query the control plane database (CockroachDB)
288292
Db(db::DbArgs),
289293
/// Debug a specific Management Gateway Service instance

dev-tools/omdb/tests/usage_errors.out

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,16 @@ Omicron debugger (unstable)
99
Usage: omdb [OPTIONS] <COMMAND>
1010

1111
Commands:
12-
crucible-agent Debug a specific crucible-agent
13-
db Query the control plane database (CockroachDB)
14-
mgs Debug a specific Management Gateway Service instance
15-
nexus Debug a specific Nexus instance
16-
oximeter Query oximeter collector state
17-
oxql Enter the Oximeter Query Language shell for interactive querying
18-
reconfigurator Interact with the Reconfigurator system
19-
sled-agent Debug a specific Sled
20-
help Print this message or the help of the given subcommand(s)
12+
crucible-agent Debug a specific crucible-agent
13+
crucible-pantry Query a specific crucible-pantry
14+
db Query the control plane database (CockroachDB)
15+
mgs Debug a specific Management Gateway Service instance
16+
nexus Debug a specific Nexus instance
17+
oximeter Query oximeter collector state
18+
oxql Enter the Oximeter Query Language shell for interactive querying
19+
reconfigurator Interact with the Reconfigurator system
20+
sled-agent Debug a specific Sled
21+
help Print this message or the help of the given subcommand(s)
2122

2223
Options:
2324
--log-level <LOG_LEVEL> log level filter [env: LOG_LEVEL=] [default: warn]
@@ -42,15 +43,16 @@ using internal APIs. This is a prototype. The commands and output are unstable
4243
Usage: omdb [OPTIONS] <COMMAND>
4344

4445
Commands:
45-
crucible-agent Debug a specific crucible-agent
46-
db Query the control plane database (CockroachDB)
47-
mgs Debug a specific Management Gateway Service instance
48-
nexus Debug a specific Nexus instance
49-
oximeter Query oximeter collector state
50-
oxql Enter the Oximeter Query Language shell for interactive querying
51-
reconfigurator Interact with the Reconfigurator system
52-
sled-agent Debug a specific Sled
53-
help Print this message or the help of the given subcommand(s)
46+
crucible-agent Debug a specific crucible-agent
47+
crucible-pantry Query a specific crucible-pantry
48+
db Query the control plane database (CockroachDB)
49+
mgs Debug a specific Management Gateway Service instance
50+
nexus Debug a specific Nexus instance
51+
oximeter Query oximeter collector state
52+
oxql Enter the Oximeter Query Language shell for interactive querying
53+
reconfigurator Interact with the Reconfigurator system
54+
sled-agent Debug a specific Sled
55+
help Print this message or the help of the given subcommand(s)
5456

5557
Options:
5658
--log-level <LOG_LEVEL>

0 commit comments

Comments
 (0)