Skip to content

Commit e627935

Browse files
authored
Add support for clickhouse keeper inventory collection (#6810)
I made small change to the types stored in inventory to not collect OmicronZoneUuids for each keeper. This allows collection based on DNS names alone. The zone ids were never actually used for anything anyway. Note that this won't collect anything right now because we won't have any DNS names for clickhouse-admin-keepers.
1 parent 868bc45 commit e627935

File tree

17 files changed

+361
-91
lines changed

17 files changed

+361
-91
lines changed

Cargo.lock

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

clickhouse-admin/types/src/lib.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -907,7 +907,17 @@ impl KeeperConf {
907907
/// dropshot servers running in `ClickhouseKeeper` zones. state. We include the
908908
/// leader committed log index known to the current keeper node (whether or not
909909
/// it is the leader) to determine which configuration is newest.
910-
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, JsonSchema)]
910+
#[derive(
911+
Clone,
912+
Debug,
913+
PartialEq,
914+
Eq,
915+
PartialOrd,
916+
Ord,
917+
Deserialize,
918+
Serialize,
919+
JsonSchema,
920+
)]
911921
#[serde(rename_all = "snake_case")]
912922
pub struct ClickhouseKeeperClusterMembership {
913923
/// Keeper ID of the keeper being queried

clients/clickhouse-admin-client/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,7 @@ progenitor::generate_api!(
2323
TypedUuidForOmicronZoneKind = omicron_uuid_kinds::OmicronZoneUuid,
2424
KeeperConfigurableSettings = clickhouse_admin_api::KeeperConfigurableSettings,
2525
ServerConfigurableSettings = clickhouse_admin_api::ServerConfigurableSettings,
26+
ClickhouseKeeperClusterMembership = clickhouse_admin_types::ClickhouseKeeperClusterMembership,
27+
KeeperId = clickhouse_admin_types::KeeperId
2628
}
2729
);

nexus/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ camino.workspace = true
2222
camino-tempfile.workspace = true
2323
clap.workspace = true
2424
chrono.workspace = true
25+
clickhouse-admin-client.workspace = true
2526
cockroach-admin-client.workspace = true
2627
crucible-agent-client.workspace = true
2728
crucible-pantry-client.workspace = true

nexus/db-model/src/inventory.rs

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@
66
77
use crate::omicron_zone_config::{self, OmicronZoneNic};
88
use crate::schema::{
9-
hw_baseboard_id, inv_caboose, inv_collection, inv_collection_error,
10-
inv_dataset, inv_nvme_disk_firmware, inv_omicron_zone,
11-
inv_omicron_zone_nic, inv_physical_disk, inv_root_of_trust,
12-
inv_root_of_trust_page, inv_service_processor, inv_sled_agent,
13-
inv_sled_omicron_zones, inv_zpool, sw_caboose, sw_root_of_trust_page,
9+
hw_baseboard_id, inv_caboose, inv_clickhouse_keeper_membership,
10+
inv_collection, inv_collection_error, inv_dataset, inv_nvme_disk_firmware,
11+
inv_omicron_zone, inv_omicron_zone_nic, inv_physical_disk,
12+
inv_root_of_trust, inv_root_of_trust_page, inv_service_processor,
13+
inv_sled_agent, inv_sled_omicron_zones, inv_zpool, sw_caboose,
14+
sw_root_of_trust_page,
1415
};
1516
use crate::typed_uuid::DbTypedUuid;
1617
use crate::PhysicalDiskKind;
@@ -21,6 +22,7 @@ use crate::{
2122
use anyhow::{anyhow, bail, Context, Result};
2223
use chrono::DateTime;
2324
use chrono::Utc;
25+
use clickhouse_admin_types::{ClickhouseKeeperClusterMembership, KeeperId};
2426
use diesel::backend::Backend;
2527
use diesel::deserialize::{self, FromSql};
2628
use diesel::expression::AsExpression;
@@ -46,6 +48,7 @@ use omicron_uuid_kinds::ZpoolKind;
4648
use omicron_uuid_kinds::ZpoolUuid;
4749
use omicron_uuid_kinds::{CollectionKind, OmicronZoneKind};
4850
use omicron_uuid_kinds::{CollectionUuid, OmicronZoneUuid};
51+
use std::collections::BTreeSet;
4952
use std::net::{IpAddr, SocketAddrV6};
5053
use thiserror::Error;
5154
use uuid::Uuid;
@@ -1726,6 +1729,68 @@ impl InvOmicronZoneNic {
17261729
}
17271730
}
17281731

1732+
#[derive(Queryable, Clone, Debug, Selectable, Insertable)]
1733+
#[diesel(table_name = inv_clickhouse_keeper_membership)]
1734+
pub struct InvClickhouseKeeperMembership {
1735+
pub inv_collection_id: DbTypedUuid<CollectionKind>,
1736+
pub queried_keeper_id: i64,
1737+
pub leader_committed_log_index: i64,
1738+
pub raft_config: Vec<i64>,
1739+
}
1740+
1741+
impl TryFrom<InvClickhouseKeeperMembership>
1742+
for ClickhouseKeeperClusterMembership
1743+
{
1744+
type Error = anyhow::Error;
1745+
1746+
fn try_from(value: InvClickhouseKeeperMembership) -> anyhow::Result<Self> {
1747+
let err_msg = "clickhouse keeper ID is negative";
1748+
let mut raft_config = BTreeSet::new();
1749+
// We are not worried about duplicates here, as each
1750+
// `clickhouse-admin-keeper` reports about its local, unique keeper.
1751+
// This uniqueness is guaranteed by the blueprint generation mechanism.
1752+
for id in value.raft_config {
1753+
raft_config.insert(KeeperId(id.try_into().context(err_msg)?));
1754+
}
1755+
Ok(ClickhouseKeeperClusterMembership {
1756+
queried_keeper: KeeperId(
1757+
value.queried_keeper_id.try_into().context(err_msg)?,
1758+
),
1759+
leader_committed_log_index: value
1760+
.leader_committed_log_index
1761+
.try_into()
1762+
.context("log index is negative")?,
1763+
raft_config,
1764+
})
1765+
}
1766+
}
1767+
1768+
impl InvClickhouseKeeperMembership {
1769+
pub fn new(
1770+
inv_collection_id: CollectionUuid,
1771+
membership: ClickhouseKeeperClusterMembership,
1772+
) -> anyhow::Result<InvClickhouseKeeperMembership> {
1773+
let err_msg = "clickhouse keeper ID > 2^63";
1774+
let mut raft_config = Vec::with_capacity(membership.raft_config.len());
1775+
for id in membership.raft_config {
1776+
raft_config.push(id.0.try_into().context(err_msg)?);
1777+
}
1778+
Ok(InvClickhouseKeeperMembership {
1779+
inv_collection_id: inv_collection_id.into(),
1780+
queried_keeper_id: membership
1781+
.queried_keeper
1782+
.0
1783+
.try_into()
1784+
.context(err_msg)?,
1785+
leader_committed_log_index: membership
1786+
.leader_committed_log_index
1787+
.try_into()
1788+
.context("log index > 2^63")?,
1789+
raft_config,
1790+
})
1791+
}
1792+
}
1793+
17291794
#[cfg(test)]
17301795
mod test {
17311796
use nexus_types::inventory::NvmeFirmware;

nexus/db-model/src/schema.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1568,6 +1568,15 @@ table! {
15681568
}
15691569
}
15701570

1571+
table! {
1572+
inv_clickhouse_keeper_membership (inv_collection_id, queried_keeper_id) {
1573+
inv_collection_id -> Uuid,
1574+
queried_keeper_id -> Int8,
1575+
leader_committed_log_index -> Int8,
1576+
raft_config -> Array<Int8>,
1577+
}
1578+
}
1579+
15711580
/* blueprints */
15721581

15731582
table! {

nexus/db-model/src/schema_versions.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use std::collections::BTreeMap;
1717
///
1818
/// This must be updated when you change the database schema. Refer to
1919
/// schema/crdb/README.adoc in the root of this repository for details.
20-
pub const SCHEMA_VERSION: SemverVersion = SemverVersion::new(108, 0, 0);
20+
pub const SCHEMA_VERSION: SemverVersion = SemverVersion::new(109, 0, 0);
2121

2222
/// List of all past database schema versions, in *reverse* order
2323
///
@@ -29,6 +29,7 @@ static KNOWN_VERSIONS: Lazy<Vec<KnownVersion>> = Lazy::new(|| {
2929
// | leaving the first copy as an example for the next person.
3030
// v
3131
// KnownVersion::new(next_int, "unique-dirname-with-the-sql-files"),
32+
KnownVersion::new(109, "inv-clickhouse-keeper-membership"),
3233
KnownVersion::new(108, "internet-gateway"),
3334
KnownVersion::new(107, "add-instance-boot-disk"),
3435
KnownVersion::new(106, "dataset-kinds-update"),

nexus/db-queries/src/db/datastore/inventory.rs

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use anyhow::Context;
1616
use async_bb8_diesel::AsyncConnection;
1717
use async_bb8_diesel::AsyncRunQueryDsl;
1818
use async_bb8_diesel::AsyncSimpleConnection;
19+
use clickhouse_admin_types::ClickhouseKeeperClusterMembership;
1920
use diesel::expression::SelectableHelper;
2021
use diesel::sql_types::Nullable;
2122
use diesel::BoolExpressionMethods;
@@ -36,6 +37,7 @@ use nexus_db_model::HwPowerStateEnum;
3637
use nexus_db_model::HwRotSlot;
3738
use nexus_db_model::HwRotSlotEnum;
3839
use nexus_db_model::InvCaboose;
40+
use nexus_db_model::InvClickhouseKeeperMembership;
3941
use nexus_db_model::InvCollection;
4042
use nexus_db_model::InvCollectionError;
4143
use nexus_db_model::InvDataset;
@@ -244,6 +246,17 @@ impl DataStore {
244246
})
245247
.collect::<Result<Vec<InvOmicronZoneNic>, _>>()?;
246248

249+
let mut inv_clickhouse_keeper_memberships = Vec::new();
250+
for membership in &collection.clickhouse_keeper_cluster_membership {
251+
inv_clickhouse_keeper_memberships.push(
252+
InvClickhouseKeeperMembership::new(
253+
collection_id,
254+
membership.clone(),
255+
)
256+
.map_err(|e| Error::internal_error(&e.to_string()))?,
257+
);
258+
}
259+
247260
// This implementation inserts all records associated with the
248261
// collection in one transaction. This is primarily for simplicity. It
249262
// means we don't have to worry about other readers seeing a
@@ -953,6 +966,15 @@ impl DataStore {
953966
.await?;
954967
}
955968

969+
// Insert the clickhouse keeper memberships we've received
970+
{
971+
use db::schema::inv_clickhouse_keeper_membership::dsl;
972+
diesel::insert_into(dsl::inv_clickhouse_keeper_membership)
973+
.values(inv_clickhouse_keeper_memberships)
974+
.execute_async(&conn)
975+
.await?;
976+
}
977+
956978
// Finally, insert the list of errors.
957979
{
958980
use db::schema::inv_collection_error::dsl as errors_dsl;
@@ -1221,6 +1243,7 @@ impl DataStore {
12211243
nnics,
12221244
nzpools,
12231245
nerrors,
1246+
nclickhouse_keeper_membership,
12241247
) = conn
12251248
.transaction_async(|conn| async move {
12261249
// Remove the record describing the collection itself.
@@ -1374,6 +1397,18 @@ impl DataStore {
13741397
.await?
13751398
};
13761399

1400+
// Remove rows for clickhouse keeper membership
1401+
let nclickhouse_keeper_membership = {
1402+
use db::schema::inv_clickhouse_keeper_membership::dsl;
1403+
diesel::delete(
1404+
dsl::inv_clickhouse_keeper_membership.filter(
1405+
dsl::inv_collection_id.eq(db_collection_id),
1406+
),
1407+
)
1408+
.execute_async(&conn)
1409+
.await?
1410+
};
1411+
13771412
Ok((
13781413
ncollections,
13791414
nsps,
@@ -1389,6 +1424,7 @@ impl DataStore {
13891424
nnics,
13901425
nzpools,
13911426
nerrors,
1427+
nclickhouse_keeper_membership,
13921428
))
13931429
})
13941430
.await
@@ -1415,6 +1451,7 @@ impl DataStore {
14151451
"nnics" => nnics,
14161452
"nzpools" => nzpools,
14171453
"nerrors" => nerrors,
1454+
"nclickhouse_keeper_membership" => nclickhouse_keeper_membership
14181455
);
14191456

14201457
Ok(())
@@ -2264,6 +2301,37 @@ impl DataStore {
22642301
map.zones.zones.push(zone);
22652302
}
22662303

2304+
// Now load the clickhouse keeper cluster memberships
2305+
let clickhouse_keeper_cluster_membership = {
2306+
use db::schema::inv_clickhouse_keeper_membership::dsl;
2307+
let mut memberships = BTreeSet::new();
2308+
let mut paginator = Paginator::new(batch_size);
2309+
while let Some(p) = paginator.next() {
2310+
let batch = paginated(
2311+
dsl::inv_clickhouse_keeper_membership,
2312+
dsl::queried_keeper_id,
2313+
&p.current_pagparams(),
2314+
)
2315+
.filter(dsl::inv_collection_id.eq(db_id))
2316+
.select(InvClickhouseKeeperMembership::as_select())
2317+
.load_async(&*conn)
2318+
.await
2319+
.map_err(|e| {
2320+
public_error_from_diesel(e, ErrorHandler::Server)
2321+
})?;
2322+
paginator = p.found_batch(&batch, &|row| row.queried_keeper_id);
2323+
for membership in batch.into_iter() {
2324+
memberships.insert(
2325+
ClickhouseKeeperClusterMembership::try_from(membership)
2326+
.map_err(|e| {
2327+
Error::internal_error(&format!("{e:#}",))
2328+
})?,
2329+
);
2330+
}
2331+
}
2332+
memberships
2333+
};
2334+
22672335
bail_unless!(
22682336
omicron_zone_nics.is_empty(),
22692337
"found extra Omicron zone NICs: {:?}",
@@ -2285,9 +2353,7 @@ impl DataStore {
22852353
rot_pages_found,
22862354
sled_agents,
22872355
omicron_zones,
2288-
// Currently unused
2289-
// See: https://github.com/oxidecomputer/omicron/issues/6578
2290-
clickhouse_keeper_cluster_membership: BTreeMap::new(),
2356+
clickhouse_keeper_cluster_membership,
22912357
})
22922358
}
22932359
}

nexus/inventory/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ workspace = true
1111
anyhow.workspace = true
1212
base64.workspace = true
1313
chrono.workspace = true
14+
clickhouse-admin-client.workspace = true
1415
clickhouse-admin-types.workspace = true
1516
futures.workspace = true
1617
gateway-client.workspace = true

nexus/inventory/src/builder.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ use nexus_types::inventory::ServiceProcessor;
3232
use nexus_types::inventory::SledAgent;
3333
use nexus_types::inventory::Zpool;
3434
use omicron_uuid_kinds::CollectionKind;
35-
use omicron_uuid_kinds::OmicronZoneUuid;
3635
use omicron_uuid_kinds::SledUuid;
3736
use std::collections::BTreeMap;
3837
use std::collections::BTreeSet;
@@ -95,7 +94,7 @@ pub struct CollectionBuilder {
9594
sleds: BTreeMap<SledUuid, SledAgent>,
9695
omicron_zones: BTreeMap<SledUuid, OmicronZonesFound>,
9796
clickhouse_keeper_cluster_membership:
98-
BTreeMap<OmicronZoneUuid, ClickhouseKeeperClusterMembership>,
97+
BTreeSet<ClickhouseKeeperClusterMembership>,
9998

10099
// We just generate one UUID for each collection.
101100
id_rng: TypedUuidRng<CollectionKind>,
@@ -124,7 +123,7 @@ impl CollectionBuilder {
124123
rot_pages_found: BTreeMap::new(),
125124
sleds: BTreeMap::new(),
126125
omicron_zones: BTreeMap::new(),
127-
clickhouse_keeper_cluster_membership: BTreeMap::new(),
126+
clickhouse_keeper_cluster_membership: BTreeSet::new(),
128127
id_rng: TypedUuidRng::from_entropy(),
129128
}
130129
}
@@ -571,10 +570,9 @@ impl CollectionBuilder {
571570
/// clickhouse-admin service running in the keeper zones.
572571
pub fn found_clickhouse_keeper_cluster_membership(
573572
&mut self,
574-
zone_id: OmicronZoneUuid,
575573
membership: ClickhouseKeeperClusterMembership,
576574
) {
577-
self.clickhouse_keeper_cluster_membership.insert(zone_id, membership);
575+
self.clickhouse_keeper_cluster_membership.insert(membership);
578576
}
579577
}
580578

0 commit comments

Comments
 (0)