Skip to content

Commit 642d95a

Browse files
committed
[sled-agent-config-reconciler] Add DumpSetupTask
1 parent a9e3ba8 commit 642d95a

File tree

6 files changed

+190
-20
lines changed

6 files changed

+190
-20
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
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+
//! Long-running tokio task responsible for updating the dump device setup in
6+
//! response to changes in available disks.
7+
8+
use crate::InternalDisksReceiver;
9+
use crate::dump_setup::DumpSetup;
10+
use sled_storage::config::MountConfig;
11+
use sled_storage::disk::Disk;
12+
use slog::Logger;
13+
use slog::error;
14+
use std::collections::HashSet;
15+
use std::ops::Deref;
16+
use std::sync::Arc;
17+
use tokio::sync::watch;
18+
19+
pub(crate) fn spawn(
20+
internal_disks_rx: InternalDisksReceiver,
21+
external_disks_rx: watch::Receiver<HashSet<Disk>>,
22+
mount_config: Arc<MountConfig>,
23+
base_log: &Logger,
24+
) {
25+
tokio::spawn(
26+
DumpSetupTask::new(
27+
internal_disks_rx,
28+
external_disks_rx,
29+
mount_config,
30+
base_log,
31+
)
32+
.run(),
33+
);
34+
}
35+
36+
struct DumpSetupTask {
37+
// Input channels on which we receive updates about disk changes.
38+
internal_disks_rx: InternalDisksReceiver,
39+
external_disks_rx: watch::Receiver<HashSet<Disk>>,
40+
41+
// Invokes dumpadm(8) and savecore(8) when new disks are encountered
42+
dump_setup: DumpSetup,
43+
44+
// Set of internal + external disks we most recently passed to `dump_setup`.
45+
last_disks_used: HashSet<Disk>,
46+
47+
log: Logger,
48+
}
49+
50+
impl DumpSetupTask {
51+
fn new(
52+
internal_disks_rx: InternalDisksReceiver,
53+
external_disks_rx: watch::Receiver<HashSet<Disk>>,
54+
mount_config: Arc<MountConfig>,
55+
base_log: &Logger,
56+
) -> Self {
57+
Self {
58+
internal_disks_rx,
59+
external_disks_rx,
60+
dump_setup: DumpSetup::new(base_log, mount_config),
61+
last_disks_used: HashSet::new(),
62+
log: base_log.new(slog::o!("component" => "DumpSetupTask")),
63+
}
64+
}
65+
66+
async fn run(mut self) {
67+
loop {
68+
self.update_setup_if_needed().await;
69+
70+
// Wait for changes on either input channel. Exit if either channel
71+
// is closed, which should never happen in production.
72+
tokio::select! {
73+
// Cancel-safe per docs on `changed()`
74+
res = self.internal_disks_rx.changed() => {
75+
if res.is_err() {
76+
error!(
77+
self.log,
78+
"internal disks channel closed: exiting task"
79+
);
80+
return;
81+
}
82+
}
83+
84+
// Cancel-safe per docs on `changed()`
85+
res = self.external_disks_rx.changed() => {
86+
if res.is_err() {
87+
error!(
88+
self.log,
89+
"external disks channel closed: exiting task"
90+
);
91+
return;
92+
}
93+
}
94+
}
95+
}
96+
}
97+
98+
async fn update_setup_if_needed(&mut self) {
99+
// Combine internal and external disks.
100+
let disks_avail = self
101+
.internal_disks_rx
102+
.borrow_and_update_raw_disks()
103+
.iter()
104+
.map(|d| d.deref().clone())
105+
.chain(self.external_disks_rx.borrow_and_update().iter().cloned())
106+
.collect::<HashSet<_>>();
107+
108+
if disks_avail != self.last_disks_used {
109+
self.dump_setup.update_dumpdev_setup(disks_avail.iter()).await;
110+
self.last_disks_used = disks_avail;
111+
}
112+
}
113+
}

sled-agent/config-reconciler/src/handle.rs

+18-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44

55
use camino::Utf8PathBuf;
6-
use illumos_utils::dladm::EtherstubVnic;
76
use illumos_utils::zpool::PathInPool;
87
use key_manager::StorageKeyRequester;
98
use nexus_sled_agent_shared::inventory::InventoryDataset;
@@ -14,10 +13,12 @@ use omicron_common::disk::DatasetName;
1413
use omicron_common::disk::DiskIdentity;
1514
use sled_agent_api::ArtifactConfig;
1615
use sled_storage::config::MountConfig;
16+
use sled_storage::disk::Disk;
1717
use sled_storage::manager::NestedDatasetConfig;
1818
use sled_storage::manager::NestedDatasetListOptions;
1919
use sled_storage::manager::NestedDatasetLocation;
2020
use slog::Logger;
21+
use std::collections::HashSet;
2122
use std::sync::Arc;
2223
use std::sync::OnceLock;
2324
use tokio::sync::watch;
@@ -45,6 +46,7 @@ use crate::SledAgentFacilities;
4546
use crate::TimeSyncStatus;
4647
use crate::dataset_serialization_task::DatasetTaskHandle;
4748
use crate::dataset_serialization_task::NestedDatasetMountError;
49+
use crate::dump_setup_task;
4850
use crate::internal_disks::InternalDisksReceiver;
4951
use crate::ledger::LedgerTaskHandle;
5052
use crate::raw_disks;
@@ -68,6 +70,7 @@ pub struct ConfigReconcilerSpawnToken {
6870
time_sync_config: TimeSyncConfig,
6971
reconciler_result_tx: watch::Sender<ReconcilerResult>,
7072
currently_managed_zpools_tx: watch::Sender<Arc<CurrentlyManagedZpools>>,
73+
external_disks_tx: watch::Sender<HashSet<Disk>>,
7174
ledger_task_log: Logger,
7275
reconciler_task_log: Logger,
7376
}
@@ -111,6 +114,16 @@ impl ConfigReconcilerHandle {
111114
base_log,
112115
);
113116

117+
// Spawn the task that manages dump devices.
118+
let (external_disks_tx, external_disks_rx) =
119+
watch::channel(HashSet::new());
120+
dump_setup_task::spawn(
121+
internal_disks_rx.clone(),
122+
external_disks_rx,
123+
Arc::clone(&mount_config),
124+
base_log,
125+
);
126+
114127
let (reconciler_result_tx, reconciler_result_rx) =
115128
watch::channel(ReconcilerResult::default());
116129
let (currently_managed_zpools_tx, currently_managed_zpools_rx) =
@@ -142,6 +155,7 @@ impl ConfigReconcilerHandle {
142155
time_sync_config,
143156
reconciler_result_tx,
144157
currently_managed_zpools_tx,
158+
external_disks_tx,
145159
ledger_task_log: base_log
146160
.new(slog::o!("component" => "SledConfigLedgerTask")),
147161
reconciler_task_log: base_log
@@ -164,7 +178,6 @@ impl ConfigReconcilerHandle {
164178
U: SledAgentArtifactStore,
165179
>(
166180
&self,
167-
underlay_vnic: EtherstubVnic,
168181
sled_agent_facilities: T,
169182
sled_agent_artifact_store: U,
170183
token: ConfigReconcilerSpawnToken,
@@ -174,6 +187,7 @@ impl ConfigReconcilerHandle {
174187
time_sync_config,
175188
reconciler_result_tx,
176189
currently_managed_zpools_tx,
190+
external_disks_tx,
177191
ledger_task_log,
178192
reconciler_task_log,
179193
} = token;
@@ -198,12 +212,13 @@ impl ConfigReconcilerHandle {
198212
}
199213

200214
reconciler_task::spawn(
215+
Arc::clone(self.internal_disks_rx.mount_config()),
201216
key_requester,
202217
time_sync_config,
203-
underlay_vnic,
204218
current_config_rx,
205219
reconciler_result_tx,
206220
currently_managed_zpools_tx,
221+
external_disks_tx,
207222
sled_agent_facilities,
208223
reconciler_task_log,
209224
);

sled-agent/config-reconciler/src/internal_disks.rs

+4
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,10 @@ impl InternalDisksReceiver {
154154
)
155155
}
156156

157+
pub(crate) fn mount_config(&self) -> &Arc<MountConfig> {
158+
&self.mount_config
159+
}
160+
157161
fn spawn_with_disk_adopter<T: DiskAdopter>(
158162
mount_config: Arc<MountConfig>,
159163
raw_disks_rx: watch::Receiver<IdMap<RawDiskWithId>>,

sled-agent/config-reconciler/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151

5252
mod dataset_serialization_task;
5353
mod disks_common;
54+
mod dump_setup_task;
5455
mod handle;
5556
mod internal_disks;
5657
mod ledger;

sled-agent/config-reconciler/src/reconciler_task.rs

+15-10
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66
77
use chrono::DateTime;
88
use chrono::Utc;
9-
use illumos_utils::dladm::EtherstubVnic;
109
use illumos_utils::zpool::PathInPool;
1110
use key_manager::StorageKeyRequester;
1211
use nexus_sled_agent_shared::inventory::OmicronSledConfig;
12+
use sled_storage::config::MountConfig;
13+
use sled_storage::disk::Disk;
1314
use slog::Logger;
15+
use std::collections::HashSet;
1416
use std::sync::Arc;
1517
use std::time::Duration;
1618
use std::time::Instant;
@@ -23,30 +25,38 @@ use crate::sled_agent_facilities::SledAgentFacilities;
2325
mod external_disks;
2426
mod zones;
2527

28+
use self::external_disks::ExternalDisks;
29+
2630
pub use self::external_disks::CurrentlyManagedZpools;
2731
pub use self::external_disks::CurrentlyManagedZpoolsReceiver;
2832
pub use self::zones::TimeSyncError;
2933
pub use self::zones::TimeSyncStatus;
3034

3135
#[allow(clippy::too_many_arguments)]
3236
pub(crate) fn spawn<T: SledAgentFacilities>(
37+
mount_config: Arc<MountConfig>,
3338
key_requester: StorageKeyRequester,
3439
time_sync_config: TimeSyncConfig,
35-
underlay_vnic: EtherstubVnic,
3640
current_config_rx: watch::Receiver<CurrentSledConfig>,
3741
reconciler_result_tx: watch::Sender<ReconcilerResult>,
3842
currently_managed_zpools_tx: watch::Sender<Arc<CurrentlyManagedZpools>>,
43+
external_disks_tx: watch::Sender<HashSet<Disk>>,
3944
sled_agent_facilities: T,
4045
log: Logger,
4146
) {
47+
let external_disks = ExternalDisks::new(
48+
mount_config,
49+
currently_managed_zpools_tx,
50+
external_disks_tx,
51+
);
52+
4253
tokio::spawn(
4354
ReconcilerTask {
4455
key_requester,
4556
time_sync_config,
46-
underlay_vnic,
4757
current_config_rx,
4858
reconciler_result_tx,
49-
currently_managed_zpools_tx,
59+
external_disks,
5060
sled_agent_facilities,
5161
log,
5262
}
@@ -123,16 +133,11 @@ struct LatestReconcilerTaskResultInner {
123133
struct ReconcilerTask<T> {
124134
key_requester: StorageKeyRequester,
125135
time_sync_config: TimeSyncConfig,
126-
underlay_vnic: EtherstubVnic,
127136
current_config_rx: watch::Receiver<CurrentSledConfig>,
128137
reconciler_result_tx: watch::Sender<ReconcilerResult>,
129-
currently_managed_zpools_tx: watch::Sender<Arc<CurrentlyManagedZpools>>,
138+
external_disks: ExternalDisks,
130139
sled_agent_facilities: T,
131140
log: Logger,
132-
// TODO where do we want to do dump setup? Needs both internal and external
133-
// disks. Maybe this task, or maybe a task just for dump setup?
134-
// Invokes dumpadm(8) and savecore(8) when new disks are encountered
135-
// dump_setup: DumpSetup,
136141
}
137142

138143
impl<T: SledAgentFacilities> ReconcilerTask<T> {

0 commit comments

Comments
 (0)