Skip to content

Commit a70596c

Browse files
committed
Wrap zone bundling into a single type
- Adds the `ZoneBundler` for managing the creation and listing of zones, and running background cleanup task. This is created pretty early, by the `StorageManager`, and cloned to the other objects that need access to bundles. - Move public free functions from the `zone_bundle` crate into methods on the `ZoneBundler`, and call them from the instance / service managers and sled agent. - Make the "list-all-zones" endpoint in the sled agent accept a filter directly and propagate to the listing routines inside the bundler. This removes filtering on the client. - Additional tests around listing / filtering.
1 parent 5165fc8 commit a70596c

12 files changed

+807
-943
lines changed

Cargo.lock

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

openapi/sled-agent.json

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -603,20 +603,20 @@
603603
}
604604
}
605605
},
606-
"/zones/bundle-cleanup/usage": {
606+
"/zones/bundle-cleanup/utilization": {
607607
"get": {
608-
"summary": "Return usage information about all zone bundles.",
609-
"operationId": "zone_bundle_usage",
608+
"summary": "Return utilization information about all zone bundles.",
609+
"operationId": "zone_bundle_utilization",
610610
"responses": {
611611
"200": {
612612
"description": "successful operation",
613613
"content": {
614614
"application/json": {
615615
"schema": {
616-
"title": "Map_of_BundleUsage",
616+
"title": "Map_of_BundleUtilization",
617617
"type": "object",
618618
"additionalProperties": {
619-
"$ref": "#/components/schemas/BundleUsage"
619+
"$ref": "#/components/schemas/BundleUtilization"
620620
}
621621
}
622622
}
@@ -635,6 +635,17 @@
635635
"get": {
636636
"summary": "List all zone bundles that exist, even for now-deleted zones.",
637637
"operationId": "zone_bundle_list_all",
638+
"parameters": [
639+
{
640+
"in": "query",
641+
"name": "filter",
642+
"description": "An optional substring used to filter zone bundles.",
643+
"schema": {
644+
"nullable": true,
645+
"type": "string"
646+
}
647+
}
648+
],
638649
"responses": {
639650
"200": {
640651
"description": "successful operation",
@@ -852,7 +863,7 @@
852863
}
853864
},
854865
"schemas": {
855-
"BundleUsage": {
866+
"BundleUtilization": {
856867
"description": "The portion of a debug dataset used for zone bundles.",
857868
"type": "object",
858869
"properties": {
@@ -907,13 +918,6 @@
907918
}
908919
]
909920
},
910-
"storage_dirs": {
911-
"description": "The directories searched for bundles to prune.",
912-
"type": "array",
913-
"items": {
914-
"type": "string"
915-
}
916-
},
917921
"storage_limit": {
918922
"description": "The limit on the dataset quota available for zone bundles.",
919923
"allOf": [
@@ -926,7 +930,6 @@
926930
"required": [
927931
"period",
928932
"priority",
929-
"storage_dirs",
930933
"storage_limit"
931934
]
932935
},

sled-agent/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ slog-term.workspace = true
6767
smf.workspace = true
6868
sp-sim.workspace = true
6969
tar.workspace = true
70-
tempfile.workspace = true
7170
thiserror.workspace = true
7271
tofino.workspace = true
7372
tokio = { workspace = true, features = [ "full" ] }

sled-agent/src/bin/zone-bundle.rs

Lines changed: 40 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ impl ListFields {
8282
}
8383

8484
#[derive(Clone, Copy, Debug, clap::ValueEnum)]
85-
enum UsageFields {
85+
enum UtilizationFields {
8686
Directory,
8787
BytesUsed,
8888
BytesAvailable,
@@ -91,9 +91,9 @@ enum UsageFields {
9191
PctQuota,
9292
}
9393

94-
impl std::fmt::Display for UsageFields {
94+
impl std::fmt::Display for UtilizationFields {
9595
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
96-
use UsageFields::*;
96+
use UtilizationFields::*;
9797
match self {
9898
Directory => write!(f, "directory"),
9999
BytesUsed => write!(f, "bytes-used"),
@@ -105,9 +105,9 @@ impl std::fmt::Display for UsageFields {
105105
}
106106
}
107107

108-
impl UsageFields {
108+
impl UtilizationFields {
109109
fn all() -> Vec<Self> {
110-
use UsageFields::*;
110+
use UtilizationFields::*;
111111
vec![
112112
Directory,
113113
BytesUsed,
@@ -178,14 +178,14 @@ enum Cmd {
178178
/// Set parameters of the zone bundle cleanup context.
179179
#[clap(visible_alias = "set-context")]
180180
SetCleanupContext(SetCleanupContextArgs),
181-
/// Return the usage of the datasets allocated for zone bundles.
182-
Usage {
181+
/// Return the utilization of the datasets allocated for zone bundles.
182+
Utilization {
183183
/// Generate parseable output.
184184
#[arg(long, short, default_value_t = false)]
185185
parseable: bool,
186186
/// Fields to print.
187-
#[arg(long, short = 'o', default_values_t = UsageFields::all(), value_delimiter = ',')]
188-
fields: Vec<UsageFields>,
187+
#[arg(long, short = 'o', default_values_t = UtilizationFields::all(), value_delimiter = ',')]
188+
fields: Vec<UtilizationFields>,
189189
},
190190
/// Trigger an explicit request to cleanup low-priority zone bundles.
191191
Cleanup,
@@ -234,19 +234,10 @@ async fn main() -> anyhow::Result<()> {
234234
}
235235
Cmd::List { filter, parseable, fields } => {
236236
let bundles = client
237-
.zone_bundle_list_all()
237+
.zone_bundle_list_all(filter.as_deref())
238238
.await
239239
.context("failed to list zone bundles")?
240-
.into_inner()
241-
.into_iter()
242-
.filter(|bundle| {
243-
if let Some(filter) = &filter {
244-
bundle.id.zone_name.contains(filter)
245-
} else {
246-
true
247-
}
248-
})
249-
.collect::<Vec<_>>();
240+
.into_inner();
250241
if bundles.is_empty() {
251242
return Ok(());
252243
}
@@ -383,7 +374,6 @@ async fn main() -> anyhow::Result<()> {
383374
.zone_bundle_cleanup_context()
384375
.await
385376
.context("failed to fetch cleanup context")?;
386-
println!("Storage directories: {:?}", context.storage_dirs);
387377
println!("Period: {}s", context.period.0.secs);
388378
println!("Priority: {:?}", context.priority.0);
389379
println!("Storage limit: {}%", context.storage_limit.0);
@@ -408,42 +398,44 @@ async fn main() -> anyhow::Result<()> {
408398
.await
409399
.context("failed to update zone bundle cleanup context")?;
410400
}
411-
Cmd::Usage { parseable, fields } => {
412-
let usage_by_dir = client
413-
.zone_bundle_usage()
401+
Cmd::Utilization { parseable, fields } => {
402+
let utilization_by_dir = client
403+
.zone_bundle_utilization()
414404
.await
415-
.context("failed to get zone bundle usage")?;
405+
.context("failed to get zone bundle utilization")?;
416406
const BYTES_USED_SIZE: usize = 16;
417407
const BYTES_AVAIL_SIZE: usize = 16;
418408
const QUOTA_SIZE: usize = 16;
419409
const PCT_OF_AVAIL_SIZE: usize = 10;
420410
const PCT_OF_QUOTA_SIZE: usize = 10;
421-
if !usage_by_dir.is_empty() {
422-
use UsageFields::*;
411+
if !utilization_by_dir.is_empty() {
412+
use UtilizationFields::*;
423413
if parseable {
424-
for (dir, usage) in usage_by_dir.iter() {
414+
for (dir, utilization) in utilization_by_dir.iter() {
425415
for (i, field) in fields.iter().enumerate() {
426416
match field {
427417
Directory => print!("{}", dir),
428-
BytesUsed => print!("{}", usage.bytes_used),
418+
BytesUsed => {
419+
print!("{}", utilization.bytes_used)
420+
}
429421
BytesAvailable => {
430-
print!("{}", usage.bytes_available)
422+
print!("{}", utilization.bytes_available)
431423
}
432424
DatasetQuota => {
433-
print!("{}", usage.dataset_quota)
425+
print!("{}", utilization.dataset_quota)
434426
}
435427
PctAvailable => print!(
436428
"{}",
437429
as_pct(
438-
usage.bytes_used,
439-
usage.bytes_available
430+
utilization.bytes_used,
431+
utilization.bytes_available
440432
)
441433
),
442434
PctQuota => print!(
443435
"{}",
444436
as_pct(
445-
usage.bytes_used,
446-
usage.dataset_quota
437+
utilization.bytes_used,
438+
utilization.dataset_quota
447439
)
448440
),
449441
}
@@ -454,8 +446,11 @@ async fn main() -> anyhow::Result<()> {
454446
println!();
455447
}
456448
} else {
457-
let dir_col_size =
458-
usage_by_dir.keys().map(|d| d.len()).max().unwrap();
449+
let dir_col_size = utilization_by_dir
450+
.keys()
451+
.map(|d| d.len())
452+
.max()
453+
.unwrap();
459454
for field in fields.iter() {
460455
match field {
461456
Directory => {
@@ -481,34 +476,34 @@ async fn main() -> anyhow::Result<()> {
481476
print!(" ");
482477
}
483478
println!();
484-
for (dir, usage) in usage_by_dir.iter() {
479+
for (dir, utilization) in utilization_by_dir.iter() {
485480
for field in fields.iter() {
486481
match field {
487482
Directory => print!("{:dir_col_size$}", dir),
488483
BytesUsed => print!(
489484
"{:BYTES_USED_SIZE$}",
490-
as_human_bytes(usage.bytes_used)
485+
as_human_bytes(utilization.bytes_used)
491486
),
492487
BytesAvailable => print!(
493488
"{:BYTES_AVAIL_SIZE$}",
494-
as_human_bytes(usage.bytes_available)
489+
as_human_bytes(utilization.bytes_available)
495490
),
496491
DatasetQuota => print!(
497492
"{:QUOTA_SIZE$}",
498-
as_human_bytes(usage.dataset_quota)
493+
as_human_bytes(utilization.dataset_quota)
499494
),
500495
PctAvailable => print!(
501496
"{:PCT_OF_AVAIL_SIZE$}",
502497
as_pct_str(
503-
usage.bytes_used,
504-
usage.bytes_available
498+
utilization.bytes_used,
499+
utilization.bytes_available
505500
)
506501
),
507502
PctQuota => print!(
508503
"{:PCT_OF_QUOTA_SIZE$}",
509504
as_pct_str(
510-
usage.bytes_used,
511-
usage.dataset_quota
505+
utilization.bytes_used,
506+
utilization.dataset_quota
512507
)
513508
),
514509
}

sled-agent/src/bootstrap/hardware.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ impl HardwareMonitor {
220220
switch_zone_bootstrap_address,
221221
sled_config.switch_zone_maghemite_links.clone(),
222222
storage_manager.resources().clone(),
223+
storage_manager.zone_bundler().clone(),
223224
)
224225
.await?;
225226

0 commit comments

Comments
 (0)