Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewjstone committed Nov 20, 2023
1 parent 1e67e61 commit 0d44c2a
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 4 deletions.
20 changes: 20 additions & 0 deletions nexus/db-queries/src/db/datastore/inventory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ use nexus_db_model::InvServiceProcessor;
use nexus_db_model::SpType;
use nexus_db_model::SpTypeEnum;
use nexus_db_model::SwCaboose;
use nexus_types::inventory::BaseboardId;
use nexus_types::inventory::Collection;
use omicron_common::api::external::Error;
use omicron_common::api::external::InternalContext;
Expand Down Expand Up @@ -798,6 +799,25 @@ impl DataStore {
Ok(())
}

// Find the primary key for `hw_baseboard_id` given a `BaseboardId`
pub async fn find_hw_baseboard_id(
&self,
opctx: &OpContext,
baseboard_id: BaseboardId,
) -> Result<Uuid, Error> {
opctx.authorize(authz::Action::Read, &authz::INVENTORY).await?;
let conn = self.pool_connection_authorized(opctx).await?;
use db::schema::hw_baseboard_id::dsl;
dsl::hw_baseboard_id
.filter(dsl::serial_number.eq(baseboard_id.serial_number))
.filter(dsl::part_number.eq(baseboard_id.part_number))
.select(dsl::id)
.limit(1)
.first_async::<Uuid>(&*conn)
.await
.map_err(|e| public_error_from_diesel(e, ErrorHandler::Server))
}

/// Attempt to read the latest collection while limiting queries to `limit`
/// records
pub async fn inventory_get_latest_collection(
Expand Down
3 changes: 3 additions & 0 deletions nexus/db-queries/src/db/datastore/rack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ impl DataStore {

// Return the rack subnet, reconfiguration epoch, and all current
// underlay allocations for the rack.
//
// Order allocations by `subnet_octet`
pub async fn rack_subnet_allocations(
&self,
opctx: &OpContext,
Expand All @@ -240,6 +242,7 @@ impl DataStore {
rack_dsl::reconfiguration_epoch,
Option::<SledUnderlaySubnetAllocation>::as_select(),
))
.order_by(subnet_dsl::subnet_octet.asc())
.load_async(&*self.pool_connection_authorized(opctx).await?)
.await
.map_err(|e| public_error_from_diesel(e, ErrorHandler::Server))
Expand Down
51 changes: 47 additions & 4 deletions nexus/src/app/rack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use gateway_client::types::SpType;
use ipnetwork::IpNetwork;
use nexus_db_model::DnsGroup;
use nexus_db_model::InitialDnsGroup;
use nexus_db_model::SledUnderlaySubnetAllocation;
use nexus_db_model::{SwitchLinkFec, SwitchLinkSpeed};
use nexus_db_queries::authz;
use nexus_db_queries::context::OpContext;
Expand Down Expand Up @@ -45,6 +46,7 @@ use omicron_common::api::external::LookupResult;
use omicron_common::api::external::Name;
use omicron_common::api::external::NameOrId;
use omicron_common::api::internal::shared::ExternalPortDiscovery;
use omicron_common::bail_unless;
use sled_agent_client::types::EarlyNetworkConfigBody;
use sled_agent_client::types::{
BgpConfig, BgpPeerConfig, EarlyNetworkConfig, PortConfigV1,
Expand Down Expand Up @@ -774,11 +776,52 @@ impl super::Nexus {
opctx: &OpContext,
sled: UninitializedSled,
) -> Result<(), Error> {
// fetch all the existing allocations via self.rack_id - This only works for a
// a single rack right now
//let allocations = self.db_datastore.rack_subnet_allocations(opctx, rack_id)?;
// First, get the hw_baseboard_id for the given UninitializedSled
let limit = NonZeroU32::new(50).unwrap();
let collection = self
.db_datastore
.inventory_get_latest_collection(opctx, limit)
.await?;

let baseboard_id = sled.baseboard.into();
let hw_baseboard_id =
self.db_datastore.find_hw_baseboard_id(opctx, baseboard_id).await?;

// Fetch all the existing allocations via self.rack_id
// This only works for a single rack right now
let allocations = self
.db_datastore
.rack_subnet_allocations(opctx, sled.rack_id)
.await?;

// Then calculate the allocation for the new sled
// Calculate the allocation for the new sled by choosing the minimim
// octet. The returned allocations are ordered by octet, so we will know
// when we have a free one. However, if we already have an allocation
// for the given sled then reuse that one.
const MIN_SUBNET_OCTET: i16 = 33;
let mut new_allocation = SledUnderlaySubnetAllocation {
rack_id: sled.rack_id,
sled_id: Uuid::new_v4(),
subnet_octet: MIN_SUBNET_OCTET,
hw_baseboard_id,
};
for (subnet, epoch, allocation) in allocations {
if let Some(allocation) = allocation {
if allocation.hw_baseboard_id == new_allocation.hw_baseboard_id
{
// We already have an allocation for this sled.
new_allocation = allocation;
break;
}
if allocation.subnet_octet == new_allocation.subnet_octet {
bail_unless!(
new_allocation.subnet_octet < 255,
"Too many sled subnets allocated"
);
new_allocation.subnet_octet += 1;
}
}
}

// Then write the allocation and bump the reconfiguration epoch

Expand Down
8 changes: 8 additions & 0 deletions nexus/types/src/inventory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ use std::sync::Arc;
use strum::EnumIter;
use uuid::Uuid;

use crate::external_api::views::Baseboard;

/// Results of collecting hardware/software inventory from various Omicron
/// components
///
Expand Down Expand Up @@ -108,6 +110,12 @@ pub struct BaseboardId {
pub serial_number: String,
}

impl From<Baseboard> for BaseboardId {
fn from(value: Baseboard) -> Self {
BaseboardId { part_number: value.part, serial_number: value.serial }
}
}

/// Caboose contents found during a collection
///
/// These are normalized in the database. Each distinct `Caboose` is assigned a
Expand Down

0 comments on commit 0d44c2a

Please sign in to comment.