-
Notifications
You must be signed in to change notification settings - Fork 40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ensures datasets get propagated into RSS blueprint #7000
Changes from 4 commits
73bd549
2f448f0
a7c6f1b
a62b283
9a9fe45
5a92eac
2aa4a0e
6506ce0
b100385
784e377
96bf17f
6f6a87c
084d6f8
03ea021
1ae6ba7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3128,6 +3128,7 @@ | |
"type": "object", | ||
"properties": { | ||
"address": { | ||
"nullable": true, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Before this PR: The public-facing API to "add a dataset to the DB" required a SocketAddr type. This is an artifact which was partially fixed by #2000 - unfortunately, there is code which still uses these IP/port pairs if they exist, but they are not required to exist for a dataset record to be created. Anyway - TL;DR, they're optional, as they should be. |
||
"description": "Address on which a service is responding to requests for the dataset.", | ||
"type": "string" | ||
}, | ||
|
@@ -3141,7 +3142,6 @@ | |
} | ||
}, | ||
"required": [ | ||
"address", | ||
"kind" | ||
] | ||
}, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,8 +34,9 @@ use omicron_common::backoff::{ | |
retry_notify_ext, retry_policy_internal_service_aggressive, BackoffError, | ||
}; | ||
use omicron_common::disk::{ | ||
DatasetKind, DatasetName, DatasetsConfig, DiskVariant, | ||
OmicronPhysicalDiskConfig, OmicronPhysicalDisksConfig, | ||
CompressionAlgorithm, DatasetConfig, DatasetKind, DatasetName, | ||
DatasetsConfig, DiskVariant, OmicronPhysicalDiskConfig, | ||
OmicronPhysicalDisksConfig, | ||
}; | ||
use omicron_common::ledger::{self, Ledger, Ledgerable}; | ||
use omicron_common::policy::{ | ||
|
@@ -45,7 +46,8 @@ use omicron_common::policy::{ | |
SINGLE_NODE_CLICKHOUSE_REDUNDANCY, | ||
}; | ||
use omicron_uuid_kinds::{ | ||
ExternalIpUuid, GenericUuid, OmicronZoneUuid, SledUuid, ZpoolUuid, | ||
DatasetUuid, ExternalIpUuid, GenericUuid, OmicronZoneUuid, SledUuid, | ||
ZpoolUuid, | ||
}; | ||
use rand::prelude::SliceRandom; | ||
use schemars::JsonSchema; | ||
|
@@ -94,6 +96,9 @@ pub enum PlanError { | |
#[error("Ran out of sleds / U2 storage pools")] | ||
NotEnoughSleds, | ||
|
||
#[error("Unexpected dataset kind: {0}")] | ||
UnexpectedDataset(String), | ||
|
||
#[error("Found only v1 service plan")] | ||
FoundV1, | ||
|
||
|
@@ -119,6 +124,54 @@ pub struct SledConfig { | |
pub zones: Vec<BlueprintZoneConfig>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Struggling to comment the right line here -- I'm trying to comment on the
That's what this PR is most significantly trying to fix |
||
} | ||
|
||
impl SledConfig { | ||
/// Adds a zone to the Sled's configuration, as well as any number of | ||
/// durable datasets. | ||
pub fn add_zone_and_datasets(&mut self, zone: BlueprintZoneConfig) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is RSS's version of "whenever you add a zone, make sure you track all possible datasets used by that zone too". |
||
let fs_dataset_name = DatasetName::new( | ||
zone.filesystem_pool.clone().expect("Missing pool"), | ||
DatasetKind::TransientZone { | ||
name: illumos_utils::zone::zone_name( | ||
zone.zone_type.kind().zone_prefix(), | ||
Some(zone.id), | ||
), | ||
}, | ||
); | ||
|
||
// Always add a transient filesystem dataset. | ||
let fs_dataset = DatasetConfig { | ||
id: DatasetUuid::new_v4(), | ||
name: fs_dataset_name, | ||
compression: CompressionAlgorithm::Off, | ||
quota: None, | ||
reservation: None, | ||
}; | ||
self.datasets.datasets.insert(fs_dataset.id, fs_dataset); | ||
|
||
// If a durable dataset exists, add it. | ||
if let Some(dataset) = zone.zone_type.durable_dataset() { | ||
let id = DatasetUuid::new_v4(); | ||
self.datasets.datasets.insert( | ||
id, | ||
DatasetConfig { | ||
id, | ||
name: dataset.into(), | ||
compression: CompressionAlgorithm::Off, | ||
quota: None, | ||
reservation: None, | ||
}, | ||
); | ||
} | ||
|
||
// Add the zone. | ||
// | ||
// Currently this is pushing back to a Vec; we could inspect to | ||
// ensure this function is idempotent, but it currently is not | ||
// re-callable. | ||
self.zones.push(zone); | ||
} | ||
} | ||
|
||
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] | ||
pub struct Plan { | ||
pub services: HashMap<SocketAddrV6, SledConfig>, | ||
|
@@ -472,6 +525,41 @@ impl Plan { | |
.iter() | ||
.map(|disk| ZpoolName::new_external(disk.pool_id)) | ||
.collect(); | ||
|
||
// Add all non-discretionary datasets, self-provisioned on the U.2, to the blueprint. | ||
for zpool in &sled_info.u2_zpools { | ||
for intrinsic_dataset in | ||
sled_storage::dataset::U2_EXPECTED_DATASETS | ||
{ | ||
let name = intrinsic_dataset.get_name(); | ||
let kind = match name { | ||
sled_storage::dataset::ZONE_DATASET => { | ||
DatasetKind::TransientZoneRoot | ||
} | ||
sled_storage::dataset::U2_DEBUG_DATASET => { | ||
DatasetKind::Debug | ||
} | ||
_ => { | ||
return Err(PlanError::UnexpectedDataset( | ||
name.to_string(), | ||
)) | ||
} | ||
}; | ||
|
||
let config = DatasetConfig { | ||
id: DatasetUuid::new_v4(), | ||
name: DatasetName::new(zpool.clone(), kind), | ||
compression: intrinsic_dataset.get_compression(), | ||
quota: intrinsic_dataset.get_quota(), | ||
reservation: None, | ||
}; | ||
sled_info | ||
.request | ||
.datasets | ||
.datasets | ||
.insert(config.id, config); | ||
} | ||
} | ||
} | ||
|
||
// We'll stripe most services across all available Sleds, round-robin | ||
|
@@ -509,7 +597,7 @@ impl Plan { | |
sled.alloc_dataset_from_u2s(DatasetKind::InternalDns)?; | ||
let filesystem_pool = Some(dataset_name.pool().clone()); | ||
|
||
sled.request.zones.push(BlueprintZoneConfig { | ||
sled.request.add_zone_and_datasets(BlueprintZoneConfig { | ||
disposition: BlueprintZoneDisposition::InService, | ||
id, | ||
filesystem_pool, | ||
|
@@ -544,7 +632,7 @@ impl Plan { | |
let dataset_name = | ||
sled.alloc_dataset_from_u2s(DatasetKind::Cockroach)?; | ||
let filesystem_pool = Some(dataset_name.pool().clone()); | ||
sled.request.zones.push(BlueprintZoneConfig { | ||
sled.request.add_zone_and_datasets(BlueprintZoneConfig { | ||
disposition: BlueprintZoneDisposition::InService, | ||
id, | ||
zone_type: BlueprintZoneType::CockroachDb( | ||
|
@@ -592,7 +680,7 @@ impl Plan { | |
let dataset_name = sled.alloc_dataset_from_u2s(dataset_kind)?; | ||
let filesystem_pool = Some(dataset_name.pool().clone()); | ||
|
||
sled.request.zones.push(BlueprintZoneConfig { | ||
sled.request.add_zone_and_datasets(BlueprintZoneConfig { | ||
disposition: BlueprintZoneDisposition::InService, | ||
id, | ||
zone_type: BlueprintZoneType::ExternalDns( | ||
|
@@ -629,7 +717,7 @@ impl Plan { | |
.unwrap(); | ||
let (nic, external_ip) = svc_port_builder.next_nexus(id)?; | ||
let filesystem_pool = Some(sled.alloc_zpool_from_u2s()?); | ||
sled.request.zones.push(BlueprintZoneConfig { | ||
sled.request.add_zone_and_datasets(BlueprintZoneConfig { | ||
disposition: BlueprintZoneDisposition::InService, | ||
id, | ||
zone_type: BlueprintZoneType::Nexus( | ||
|
@@ -673,7 +761,7 @@ impl Plan { | |
.host_zone_with_one_backend(id, ServiceName::Oximeter, address) | ||
.unwrap(); | ||
let filesystem_pool = Some(sled.alloc_zpool_from_u2s()?); | ||
sled.request.zones.push(BlueprintZoneConfig { | ||
sled.request.add_zone_and_datasets(BlueprintZoneConfig { | ||
disposition: BlueprintZoneDisposition::InService, | ||
id, | ||
zone_type: BlueprintZoneType::Oximeter( | ||
|
@@ -701,7 +789,7 @@ impl Plan { | |
let dataset_name = | ||
sled.alloc_dataset_from_u2s(DatasetKind::Clickhouse)?; | ||
let filesystem_pool = Some(dataset_name.pool().clone()); | ||
sled.request.zones.push(BlueprintZoneConfig { | ||
sled.request.add_zone_and_datasets(BlueprintZoneConfig { | ||
disposition: BlueprintZoneDisposition::InService, | ||
id, | ||
zone_type: BlueprintZoneType::Clickhouse( | ||
|
@@ -736,7 +824,7 @@ impl Plan { | |
address, | ||
) | ||
.unwrap(); | ||
sled.request.zones.push(BlueprintZoneConfig { | ||
sled.request.add_zone_and_datasets(BlueprintZoneConfig { | ||
disposition: BlueprintZoneDisposition::InService, | ||
id, | ||
zone_type: BlueprintZoneType::CruciblePantry( | ||
|
@@ -762,7 +850,7 @@ impl Plan { | |
) | ||
.unwrap(); | ||
|
||
sled.request.zones.push(BlueprintZoneConfig { | ||
sled.request.add_zone_and_datasets(BlueprintZoneConfig { | ||
disposition: BlueprintZoneDisposition::InService, | ||
id, | ||
zone_type: BlueprintZoneType::Crucible( | ||
|
@@ -823,7 +911,7 @@ impl Plan { | |
.host_zone_with_one_backend(id, svcname, ntp_address) | ||
.unwrap(); | ||
|
||
sled.request.zones.push(BlueprintZoneConfig { | ||
sled.request.add_zone_and_datasets(BlueprintZoneConfig { | ||
disposition: BlueprintZoneDisposition::InService, | ||
id, | ||
zone_type, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 I figure this will have ripple effects which is why you didn't do it in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it's a mechanical change, so I figured I'd punt it out when I get to a less conflict-y place