Skip to content

Commit

Permalink
wip: bootstore network data management
Browse files Browse the repository at this point in the history
* update RSS/Bootstore data structures to be consistent with the Nexus
  API

* Active management of the boot store from the Nexus API handlers for
  network settings.

* Sled agent endpoints for managing early network bootstore data.
  • Loading branch information
rcgoodfellow committed Oct 12, 2023
1 parent 226a3e9 commit 9aa0dbd
Show file tree
Hide file tree
Showing 34 changed files with 1,607 additions and 531 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions clients/bootstrap-agent-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ progenitor::generate_api!(
derives = [schemars::JsonSchema],
replace = {
Ipv4Network = ipnetwork::Ipv4Network,
Ipv6Network = ipnetwork::Ipv6Network,
IpNetwork = ipnetwork::IpNetwork,
}
);

Expand Down
2 changes: 2 additions & 0 deletions clients/nexus-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ progenitor::generate_api!(
}),
replace = {
Ipv4Network = ipnetwork::Ipv4Network,
Ipv6Network = ipnetwork::Ipv6Network,
IpNetwork = ipnetwork::IpNetwork,
MacAddr = omicron_common::api::external::MacAddr,
Name = omicron_common::api::external::Name,
NewPasswordHash = omicron_passwords::NewPasswordHash,
Expand Down
26 changes: 24 additions & 2 deletions clients/sled-agent-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,33 @@
//! Interface for making API requests to a Sled Agent
use async_trait::async_trait;
use omicron_common::generate_logging_api;
use std::convert::TryFrom;
use uuid::Uuid;

generate_logging_api!("../../openapi/sled-agent.json");
progenitor::generate_api!(
spec = "../../openapi/sled-agent.json",
inner_type = slog::Logger,
pre_hook = (|log: &slog::Logger, request: &reqwest::Request| {
slog::debug!(log, "client request";
"method" => %request.method(),
"uri" => %request.url(),
"body" => ?&request.body(),
);
}),
post_hook = (|log: &slog::Logger, result: &Result<_, _>| {
slog::debug!(log, "client response"; "result" => ?result);
}),
//TODO trade the manual transformations later in this file for the
// replace directives below?
replace = {
//Ipv4Network = ipnetwork::Ipv4Network,
SwitchLocation = omicron_common::api::external::SwitchLocation,
Ipv6Network = ipnetwork::Ipv6Network,
IpNetwork = ipnetwork::IpNetwork,
PortFec = omicron_common::api::internal::shared::PortFec,
PortSpeed = omicron_common::api::internal::shared::PortSpeed,
}
);

impl omicron_common::api::external::ClientError for types::Error {
fn message(&self) -> String {
Expand Down
6 changes: 6 additions & 0 deletions clients/wicketd-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ progenitor::generate_api!(
RackOperationStatus = { derives = [ PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize ] },
RackNetworkConfig = { derives = [ PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize ] },
UplinkConfig = { derives = [ PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize ] },
PortConfigV1 = { derives = [ PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize ] },
BgpPeerConfig = { derives = [ PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize ] },
BgpConfig = { derives = [ PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize ] },
RouteConfig = { derives = [ PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize ] },
CurrentRssUserConfigInsensitive = { derives = [ PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize ] },
CurrentRssUserConfigSensitive = { derives = [ PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize ] },
CurrentRssUserConfig = { derives = [ PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize ] },
Expand All @@ -52,6 +56,8 @@ progenitor::generate_api!(
replace = {
Duration = std::time::Duration,
Ipv4Network = ipnetwork::Ipv4Network,
Ipv6Network = ipnetwork::Ipv6Network,
IpNetwork = ipnetwork::IpNetwork,
PutRssUserConfigInsensitive = wicket_common::rack_setup::PutRssUserConfigInsensitive,
EventReportForWicketdEngineSpec = wicket_common::update_events::EventReport,
StepEventForWicketdEngineSpec = wicket_common::update_events::StepEvent,
Expand Down
71 changes: 59 additions & 12 deletions common/src/api/internal/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//! Types shared between Nexus and Sled Agent.
use crate::api::external::{self, Name};
use ipnetwork::Ipv4Network;
use ipnetwork::{IpNetwork, Ipv4Network};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::{
Expand Down Expand Up @@ -77,9 +77,57 @@ pub struct RackNetworkConfig {
/// Last ip address to be used for configuring network infrastructure
pub infra_ip_last: Ipv4Addr,
/// Uplinks for connecting the rack to external networks
pub uplinks: Vec<UplinkConfig>,
pub ports: Vec<PortConfigV1>,
/// BGP configurations for connecting the rack to external networks
pub bgp: Vec<BgpConfig>,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, JsonSchema)]
pub struct BgpConfig {
/// The autonomous system number for the BGP configuration.
pub asn: u32,
/// The set of prefixes for the BGP router to originate.
pub originate: Vec<Ipv4Network>,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, JsonSchema)]
pub struct BgpPeerConfig {
/// Switch port the peer is reachable on.
pub asn: u32,
/// Switch port the peer is reachable on.
pub port: String,
/// Address of the peer.
pub addr: Ipv4Addr,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, JsonSchema)]
pub struct RouteConfig {
/// The destination of the route.
pub destination: IpNetwork,
/// The nexthop/gateway address.
pub nexthop: IpAddr,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, JsonSchema)]
pub struct PortConfigV1 {
/// The set of routes associated with this port.
pub routes: Vec<RouteConfig>,
/// This port's addresses.
pub addresses: Vec<IpNetwork>,
/// Switch the port belongs to.
pub switch: SwitchLocation,
/// Nmae of the port this config applies to.
pub port: String,
/// Port speed.
pub uplink_port_speed: PortSpeed,
/// Port forward error correction type.
pub uplink_port_fec: PortFec,
/// BGP peers on this port
pub bgp_peers: Vec<BgpPeerConfig>,
}

/// Deprecated, use PortConfigV1 instead. Cannot actually deprecate due to
/// <https://github.com/serde-rs/serde/issues/2195>
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, JsonSchema)]
pub struct UplinkConfig {
/// Gateway address
Expand All @@ -100,25 +148,24 @@ pub struct UplinkConfig {
}

/// A set of switch uplinks.
#[derive(Clone, Debug, Deserialize, JsonSchema)]
pub struct SwitchUplinks {
pub uplinks: Vec<HostUplinkConfig>,
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
pub struct SwitchPorts {
pub uplinks: Vec<HostPortConfig>,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, JsonSchema)]
pub struct HostUplinkConfig {
pub struct HostPortConfig {
/// Switchport to use for external connectivity
pub uplink_port: String,
pub port: String,

//TODO should suppot IPv4 and IPv6 with IpNetwork
/// IP Address and prefix (e.g., `192.168.0.1/16`) to apply to switchport
/// (must be in infra_ip pool)
pub uplink_cidr: Ipv4Network,
pub addrs: Vec<IpNetwork>,
}

impl From<UplinkConfig> for HostUplinkConfig {
fn from(u: UplinkConfig) -> Self {
Self { uplink_port: u.uplink_port, uplink_cidr: u.uplink_cidr }
impl From<PortConfigV1> for HostPortConfig {
fn from(x: PortConfigV1) -> Self {
Self { port: x.port, addrs: x.addresses }
}
}

Expand Down
4 changes: 4 additions & 0 deletions nexus/db-model/src/switch_port.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,11 @@ impl Into<external::SwitchPortRouteConfig> for SwitchPortRouteConfig {
#[diesel(table_name = switch_port_settings_bgp_peer_config)]
pub struct SwitchPortBgpPeerConfig {
pub port_settings_id: Uuid,

//TODO(ry) this should be associated with the BGP configuration
// not an individual peer.
pub bgp_announce_set_id: Uuid,

pub bgp_config_id: Uuid,
pub interface_name: String,
pub addr: IpNetwork,
Expand Down
59 changes: 28 additions & 31 deletions nexus/src/app/rack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ use omicron_common::api::external::AddressLotKind;
use omicron_common::api::external::DataPageParams;
use omicron_common::api::external::Error;
use omicron_common::api::external::IdentityMetadataCreateParams;
use omicron_common::api::external::IpNet;
use omicron_common::api::external::Ipv4Net;
use omicron_common::api::external::ListResultVec;
use omicron_common::api::external::LookupResult;
use omicron_common::api::external::Name;
Expand Down Expand Up @@ -380,7 +378,7 @@ impl super::Nexus {
})?;

for (idx, uplink_config) in
rack_network_config.uplinks.iter().enumerate()
rack_network_config.ports.iter().enumerate()
{
let switch = uplink_config.switch.to_string();
let switch_location = Name::from_str(&switch).map_err(|e| {
Expand Down Expand Up @@ -449,31 +447,32 @@ impl super::Nexus {
addresses: HashMap::new(),
};

let uplink_address =
IpNet::V4(Ipv4Net(uplink_config.uplink_cidr));
let address = Address {
address_lot: NameOrId::Name(address_lot_name.clone()),
address: uplink_address,
};
port_settings_params.addresses.insert(
"phy0".to_string(),
AddressConfig { addresses: vec![address] },
);

let dst = IpNet::from_str("0.0.0.0/0").map_err(|e| {
Error::internal_error(&format!(
"failed to parse provided default route CIDR: {e}"
))
})?;

let gw = IpAddr::V4(uplink_config.gateway_ip);
let vid = uplink_config.uplink_vid;
let route = Route { dst, gw, vid };

port_settings_params.routes.insert(
"phy0".to_string(),
RouteConfig { routes: vec![route] },
);
let addresses: Vec<Address> = uplink_config
.addresses
.iter()
.map(|a| Address {
address_lot: NameOrId::Name(address_lot_name.clone()),
address: (*a).into(),
})
.collect();

port_settings_params
.addresses
.insert("phy0".to_string(), AddressConfig { addresses });

let routes: Vec<Route> = uplink_config
.routes
.iter()
.map(|r| Route {
dst: r.destination.into(),
gw: r.nexthop,
vid: None,
})
.collect();

port_settings_params
.routes
.insert("phy0".to_string(), RouteConfig { routes });

match self
.db_datastore
Expand All @@ -498,9 +497,7 @@ impl super::Nexus {
opctx,
rack_id,
switch_location.into(),
Name::from_str(&uplink_config.uplink_port)
.unwrap()
.into(),
Name::from_str(&uplink_config.port).unwrap().into(),
)
.await?;

Expand Down
Loading

0 comments on commit 9aa0dbd

Please sign in to comment.