From a1a70fdbc4003f274f7b7f5c21c0deaee12eb46e Mon Sep 17 00:00:00 2001 From: Levon Tarver Date: Sat, 31 Aug 2024 02:15:20 +0000 Subject: [PATCH] WIP: breakout bgp peer import/export/communities --- common/src/api/external/mod.rs | 65 +- nexus/db-model/src/switch_port.rs | 34 +- .../src/db/datastore/switch_port.rs | 258 +------ nexus/src/app/rack.rs | 6 +- nexus/src/app/switch_port.rs | 6 +- nexus/src/external_api/http_entrypoints.rs | 132 ++-- nexus/tests/integration_tests/switch_port.rs | 6 +- nexus/tests/output/nexus_tags.txt | 9 + .../output/uncovered-authz-endpoints.txt | 9 + nexus/types/src/external_api/params.rs | 21 +- openapi/nexus.json | 682 +++++++++++++++++- 11 files changed, 883 insertions(+), 345 deletions(-) diff --git a/common/src/api/external/mod.rs b/common/src/api/external/mod.rs index 13f72c9a90..59c0513286 100644 --- a/common/src/api/external/mod.rs +++ b/common/src/api/external/mod.rs @@ -2238,7 +2238,7 @@ pub struct SwitchPortSettingsView { pub routes: Vec, /// BGP peer settings. - pub bgp_peers: Vec, + pub bgp_peers: Vec, /// Layer 3 IP address settings. pub addresses: Vec, @@ -2517,7 +2517,7 @@ pub struct SwitchPortBgpPeerConfig { /// parameter is a reference to global BGP parameters. The `interface_name` /// indicates what interface the peer should be contacted on. #[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, PartialEq)] -pub struct BgpPeer { +pub struct BgpPeerCombined { /// The global BGP configuration used for establishing a session with this /// peer. pub bgp_config: NameOrId, @@ -2579,6 +2579,67 @@ pub struct BgpPeer { pub vlan_id: Option, } +/// The information required to configure a BGP peer. +#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, PartialEq)] +pub struct BgpPeer { + /// The global BGP configuration used for establishing a session with this + /// peer. + pub bgp_config: NameOrId, + + /// The name of interface to peer on. This is relative to the port + /// configuration this BGP peer configuration is a part of. For example this + /// value could be phy0 to refer to a primary physical interface. Or it + /// could be vlan47 to refer to a VLAN interface. + pub interface_name: String, + + /// The address of th e host to peer with. + pub addr: oxnet::IpNet, + + /// How long to hold peer connections between keepalives (seconds). + pub hold_time: u32, + + /// How long to hold a peer in idle before attempting a new session + /// (seconds). + pub idle_hold_time: u32, + + /// How long to delay sending an open request after establishing a TCP + /// session (seconds). + pub delay_open: u32, + + /// How long to to wait between TCP connection retries (seconds). + pub connect_retry: u32, + + /// How often to send keepalive requests (seconds). + pub keepalive: u32, + + /// Require that a peer has a specified ASN. + pub remote_asn: Option, + + /// Require messages from a peer have a minimum IP time to live field. + pub min_ttl: Option, + + /// Use the given key for TCP-MD5 authentication with the peer. + pub md5_auth_key: Option, + + /// Apply the provided multi-exit discriminator (MED) updates sent to the peer. + pub multi_exit_discriminator: Option, + + /// Apply a local preference to routes received from this peer. + pub local_pref: Option, + + /// Enforce that the first AS in paths received from this peer is the peer's AS. + pub enforce_first_as: bool, + + /// Enable import policies + pub allow_import_list_active: bool, + + /// Enable export policies + pub allow_export_list_active: bool, + + /// Associate a VLAN ID with a peer. + pub vlan_id: Option, +} + /// A BGP peer configuration to remove from an interface #[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, PartialEq)] pub struct BgpPeerRemove { diff --git a/nexus/db-model/src/switch_port.rs b/nexus/db-model/src/switch_port.rs index 3d551a1249..ee57a3066f 100644 --- a/nexus/db-model/src/switch_port.rs +++ b/nexus/db-model/src/switch_port.rs @@ -20,8 +20,10 @@ use diesel::AsChangeset; use ipnetwork::IpNetwork; use nexus_types::external_api::params; use nexus_types::identity::Resource; -use omicron_common::api::external::{self, BgpAllowedPrefix, BgpCommunity}; -use omicron_common::api::external::{BgpPeer, ImportExportPolicy}; +use omicron_common::api::external::{ + self, BgpAllowedPrefix, BgpCommunity, NameOrId, +}; +use omicron_common::api::external::{BgpPeerCombined, ImportExportPolicy}; use omicron_common::api::internal::shared::{PortFec, PortSpeed}; use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -620,6 +622,32 @@ pub struct SwitchPortBgpPeerConfig { pub vlan_id: Option, } +impl Into for SwitchPortBgpPeerConfig { + fn into(self) -> external::BgpPeer { + external::BgpPeer { + bgp_config: NameOrId::Id(self.bgp_config_id), + interface_name: self.interface_name, + addr: self.addr.into(), + hold_time: self.hold_time.into(), + idle_hold_time: self.idle_hold_time.into(), + delay_open: self.delay_open.into(), + connect_retry: self.connect_retry.into(), + keepalive: self.keepalive.into(), + remote_asn: self.remote_asn.map(Into::into), + min_ttl: self.min_ttl.map(Into::into), + md5_auth_key: self.md5_auth_key, + multi_exit_discriminator: self + .multi_exit_discriminator + .map(Into::into), + local_pref: self.local_pref.map(Into::into), + enforce_first_as: self.enforce_first_as, + allow_import_list_active: self.allow_import_list_active, + allow_export_list_active: self.allow_export_list_active, + vlan_id: self.vlan_id.map(Into::into), + } + } +} + #[derive( Queryable, Insertable, @@ -710,7 +738,7 @@ impl SwitchPortBgpPeerConfig { port_settings_id: Uuid, bgp_config_id: Uuid, interface_name: String, - p: &BgpPeer, + p: &BgpPeerCombined, ) -> Self { Self { port_settings_id, diff --git a/nexus/db-queries/src/db/datastore/switch_port.rs b/nexus/db-queries/src/db/datastore/switch_port.rs index ddb8a9c380..f8b3a61c64 100644 --- a/nexus/db-queries/src/db/datastore/switch_port.rs +++ b/nexus/db-queries/src/db/datastore/switch_port.rs @@ -72,9 +72,9 @@ pub struct BgpPeerConfig { pub vlan_id: Option, } -impl Into for BgpPeerConfig { - fn into(self) -> external::BgpPeer { - external::BgpPeer { +impl Into for BgpPeerConfig { + fn into(self) -> external::BgpPeerCombined { + external::BgpPeerCombined { bgp_config: self.bgp_config_id.into(), interface_name: self.interface_name.clone(), addr: self.addr.ip(), @@ -1413,12 +1413,9 @@ impl DataStore { &self, opctx: &OpContext, configuration: NameOrId, - ) -> ListResultVec { + ) -> ListResultVec { use db::schema::switch_port_settings as port_settings; use db::schema::switch_port_settings_bgp_peer_config as bgp_peer_config; - use db::schema::switch_port_settings_bgp_peer_config_allow_export as allow_export; - use db::schema::switch_port_settings_bgp_peer_config_allow_import as allow_import; - use db::schema::switch_port_settings_bgp_peer_config_communities as communities; let conn = self.pool_connection_authorized(opctx).await?; let err = OptionalError::new(); @@ -1466,92 +1463,8 @@ impl DataStore { } })?; - let mut configs: Vec = vec![]; - - for peer in peers { - // get allowed import - let prefixes_to_import: Vec = allow_import::table - .filter(allow_import::addr.eq(peer.addr)) - .filter(allow_import::interface_name.eq(peer.interface_name.clone())) - .filter(allow_import::port_settings_id.eq(peer.port_settings_id)) - .select(allow_import::prefix) - .load_async(&conn) - .await - .map_err(|e| { - let message = "error while looking up bgp peer import configuration"; - error!(opctx.log, "{message}"; "error" => ?e); - err.bail(Error::internal_error(message)) - })?; - - let allowed_import = if prefixes_to_import.is_empty() { - ImportExportPolicy::NoFiltering - } else { - ImportExportPolicy::Allow(prefixes_to_import.into_iter().map(Into::into).collect()) - }; - - // get allowed export - let prefixes_to_export: Vec = allow_export::table - .filter(allow_export::addr.eq(peer.addr)) - .filter(allow_export::interface_name.eq(peer.interface_name.clone())) - .filter(allow_export::port_settings_id.eq(peer.port_settings_id)) - .select(allow_export::prefix) - .load_async(&conn) - .await - .map_err(|e| { - let message = - "error while looking up bgp peer export configuration"; - error!(opctx.log, "{message}"; "error" => ?e); - err.bail(Error::internal_error(message)) - })?; - - let allowed_export = if prefixes_to_export.is_empty() { - ImportExportPolicy::NoFiltering - } else { - ImportExportPolicy::Allow(prefixes_to_export.into_iter().map(Into::into).collect()) - }; - - // get communities - let communities: Vec = communities::table - .filter(communities::addr.eq(peer.addr)) - .filter(communities::interface_name.eq(peer.interface_name.clone())) - .filter(communities::port_settings_id.eq(peer.port_settings_id)) - .select(communities::community) - .load_async(&conn) - .await - .map_err(|e| { - let message = - "error while looking up bgp peer communities"; - error!(opctx.log, "{message}"; "error" => ?e); - err.bail(Error::internal_error(message)) - })?; - - // build config - let config = BgpPeerConfig { - port_settings_id: peer.port_settings_id, - bgp_config_id: peer.bgp_config_id, - interface_name: peer.interface_name, - addr: peer.addr, - hold_time: peer.hold_time, - idle_hold_time: peer.idle_hold_time, - delay_open: peer.delay_open, - connect_retry: peer.connect_retry, - keepalive: peer.keepalive, - remote_asn: peer.remote_asn, - min_ttl: peer.min_ttl, - md5_auth_key: peer.md5_auth_key, - multi_exit_discriminator: peer.multi_exit_discriminator, - local_pref: peer.local_pref, - enforce_first_as: peer.enforce_first_as, - allowed_import, - allowed_export, - communities: communities.into_iter().map(Into::into).collect(), - vlan_id: peer.vlan_id, - }; - // push - configs.push(config); - } - Ok(configs) + Ok(peers) } }) .await @@ -1578,7 +1491,7 @@ impl DataStore { opctx: &OpContext, configuration: NameOrId, bgp_peer: BgpPeer, - ) -> CreateResult { + ) -> CreateResult { use db::schema::bgp_config; use db::schema::switch_port_settings_bgp_peer_config as bgp_peer_config; @@ -1663,129 +1576,6 @@ impl DataStore { } }?; - // create import list if enabled - let allow_import_list_active = match new_settings.allowed_import.clone() { - ImportExportPolicy::NoFiltering => false, - ImportExportPolicy::Allow(prefixes) => { - use db::schema::switch_port_settings_bgp_peer_config_allow_import as allow_import; - let to_insert: Vec = prefixes - .clone() - .into_iter() - .map(|x| SwitchPortBgpPeerConfigAllowImport { - port_settings_id, - interface_name: new_settings.interface_name.clone(), - addr: new_settings.addr.into(), - prefix: x.into(), - }) - .collect(); - - diesel::insert_into(allow_import::table) - .values(to_insert) - .execute_async(&conn) - .await - .map_err(|e: diesel::result::Error| { - let message = "error while creating bgp allowed import configuration"; - match e { - diesel::result::Error::DatabaseError(kind, _) => { - match kind { - diesel::result::DatabaseErrorKind::UniqueViolation => { - err.bail(Error::conflict("allowed import configuration conflicts with an existing configuration")) - }, - diesel::result::DatabaseErrorKind::NotNullViolation => { - err.bail(Error::invalid_request("a required field is not populated")) - }, - _ => err.bail(Error::internal_error(message)), - } - }, - _ => err.bail(Error::internal_error(message)), - } - })?; - - true - }, - }; - - // create export list if enabled - let allow_export_list_active = match new_settings.allowed_export.clone() { - ImportExportPolicy::NoFiltering => false, - ImportExportPolicy::Allow(prefixes) => { - use db::schema::switch_port_settings_bgp_peer_config_allow_export as allow_export; - let to_insert: Vec = prefixes - .clone() - .into_iter() - .map(|x| SwitchPortBgpPeerConfigAllowExport { - port_settings_id, - interface_name: new_settings.interface_name.clone(), - addr: new_settings.addr.into(), - prefix: x.into(), - }) - .collect(); - - diesel::insert_into(allow_export::table) - .values(to_insert) - .execute_async(&conn) - .await - .map_err(|e: diesel::result::Error| { - let message = "error while creating bgp allowed export configuration"; - match e { - diesel::result::Error::DatabaseError(kind, _) => { - match kind { - diesel::result::DatabaseErrorKind::UniqueViolation => { - err.bail(Error::conflict("allowed export configuration conflicts with an existing configuration")) - }, - diesel::result::DatabaseErrorKind::NotNullViolation => { - err.bail(Error::invalid_request("a required field is not populated")) - }, - _ => err.bail(Error::internal_error(message)), - } - }, - _ => err.bail(Error::internal_error(message)), - } - })?; - - true - }, - }; - - // create communities - if !new_settings.communities.is_empty() { - use db::schema::switch_port_settings_bgp_peer_config_communities as peer_communities; - let to_insert: Vec = new_settings - .communities - .clone() - .into_iter() - .map(|x| SwitchPortBgpPeerConfigCommunity { - port_settings_id, - interface_name: new_settings.interface_name.clone(), - addr: new_settings.addr.into(), - community: x.into(), - }) - .collect(); - - diesel::insert_into(peer_communities::table) - .values(to_insert) - .execute_async(&conn) - .await - .map_err(|e: diesel::result::Error| { - let message = "error while creating bgp communities for peer"; - match e { - diesel::result::Error::DatabaseError(kind, _) => { - match kind { - diesel::result::DatabaseErrorKind::UniqueViolation => { - err.bail(Error::conflict("peer communities configuration conflicts with an existing configuration")) - }, - diesel::result::DatabaseErrorKind::NotNullViolation => { - err.bail(Error::invalid_request("a required field is not populated")) - }, - _ => err.bail(Error::internal_error(message)), - } - }, - _ => err.bail(Error::internal_error(message)), - } - })?; - - } - let bgp_peer_config = SwitchPortBgpPeerConfig { port_settings_id, bgp_config_id, @@ -1802,8 +1592,8 @@ impl DataStore { multi_exit_discriminator: new_settings.multi_exit_discriminator.map(Into::into), local_pref: new_settings.local_pref.map(Into::into), enforce_first_as: new_settings.enforce_first_as, - allow_import_list_active, - allow_export_list_active, + allow_import_list_active: new_settings.allow_import_list_active, + allow_export_list_active: new_settings.allow_import_list_active, vlan_id: new_settings.vlan_id.map(Into::into), }; @@ -1830,29 +1620,7 @@ impl DataStore { } })?; - let config = BgpPeerConfig { - port_settings_id, - bgp_config_id, - interface_name: peer.interface_name, - addr: peer.addr, - hold_time: peer.hold_time, - idle_hold_time: peer.idle_hold_time, - delay_open: peer.delay_open, - connect_retry: peer.connect_retry, - keepalive: peer.keepalive, - remote_asn: peer.remote_asn, - min_ttl: peer.min_ttl, - md5_auth_key: peer.md5_auth_key, - multi_exit_discriminator: peer.multi_exit_discriminator, - local_pref: peer.local_pref, - enforce_first_as: peer.enforce_first_as, - allowed_import: new_settings.allowed_import, - allowed_export: new_settings.allowed_export, - communities: new_settings.communities, - vlan_id: peer.vlan_id, - }; - - Ok(config) + Ok(peer) } }) .await @@ -3187,7 +2955,7 @@ async fn do_switch_port_settings_create( .get_results_async(conn) .await?; - let mut peer_by_addr: BTreeMap = + let mut peer_by_addr: BTreeMap = BTreeMap::new(); let mut bgp_peer_config = Vec::new(); @@ -3618,8 +3386,8 @@ mod test { SwitchPortConfigCreate, SwitchPortGeometry, SwitchPortSettingsCreate, }; use omicron_common::api::external::{ - BgpPeer, IdentityMetadataCreateParams, ImportExportPolicy, Name, - NameOrId, + BgpPeerCombined, IdentityMetadataCreateParams, ImportExportPolicy, + Name, NameOrId, }; use omicron_test_utils::dev; use std::collections::HashMap; @@ -3682,7 +3450,7 @@ mod test { bgp_peers: HashMap::from([( "phy0".into(), BgpPeerConfig { - peers: vec![BgpPeer { + peers: vec![BgpPeerCombined { bgp_config: NameOrId::Name( "test-bgp-config".parse().unwrap(), ), diff --git a/nexus/src/app/rack.rs b/nexus/src/app/rack.rs index d2690eaf13..52c2351641 100644 --- a/nexus/src/app/rack.rs +++ b/nexus/src/app/rack.rs @@ -51,7 +51,7 @@ use nexus_types::identity::Resource; use nexus_types::internal_api::params::DnsRecord; use omicron_common::address::{get_64_subnet, Ipv6Subnet, RACK_PREFIX}; use omicron_common::api::external::AddressLotKind; -use omicron_common::api::external::BgpPeer; +use omicron_common::api::external::BgpPeerCombined; use omicron_common::api::external::DataPageParams; use omicron_common::api::external::Error; use omicron_common::api::external::IdentityMetadataCreateParams; @@ -649,10 +649,10 @@ impl super::Nexus { .routes .insert("phy0".to_string(), RouteConfig { routes }); - let peers: Vec = uplink_config + let peers: Vec = uplink_config .bgp_peers .iter() - .map(|r| BgpPeer { + .map(|r| BgpPeerCombined { bgp_config: NameOrId::Name( format!("as{}", r.asn).parse().unwrap(), ), diff --git a/nexus/src/app/switch_port.rs b/nexus/src/app/switch_port.rs index ad5cc90198..eae653b9d5 100644 --- a/nexus/src/app/switch_port.rs +++ b/nexus/src/app/switch_port.rs @@ -9,6 +9,7 @@ use dpd_client::types::LinkId; use dpd_client::types::PortId; use http::StatusCode; use nexus_db_model::SwitchPortAddressConfig; +use nexus_db_model::SwitchPortBgpPeerConfig; use nexus_db_model::SwitchPortBgpPeerConfigAllowExport; use nexus_db_model::SwitchPortBgpPeerConfigAllowImport; use nexus_db_model::SwitchPortBgpPeerConfigCommunity; @@ -19,7 +20,6 @@ use nexus_db_model::SwitchPortRouteConfig; use nexus_db_queries::authz; use nexus_db_queries::context::OpContext; use nexus_db_queries::db; -use nexus_db_queries::db::datastore::BgpPeerConfig; use nexus_db_queries::db::datastore::UpdatePrecondition; use nexus_db_queries::db::model::{SwitchPort, SwitchPortSettings}; use nexus_db_queries::db::DataStore; @@ -301,7 +301,7 @@ impl super::Nexus { &self, opctx: &OpContext, configuration: NameOrId, - ) -> ListResultVec { + ) -> ListResultVec { opctx.authorize(authz::Action::Read, &authz::FLEET).await?; self.db_datastore .switch_port_configuration_bgp_peer_list(opctx, configuration) @@ -313,7 +313,7 @@ impl super::Nexus { opctx: &OpContext, configuration: NameOrId, bgp_peer: BgpPeer, - ) -> CreateResult { + ) -> CreateResult { opctx.authorize(authz::Action::CreateChild, &authz::FLEET).await?; self.db_datastore .switch_port_configuration_bgp_peer_add( diff --git a/nexus/src/external_api/http_entrypoints.rs b/nexus/src/external_api/http_entrypoints.rs index 0e7efa5dcc..8a794ebbec 100644 --- a/nexus/src/external_api/http_entrypoints.rs +++ b/nexus/src/external_api/http_entrypoints.rs @@ -41,12 +41,10 @@ use nexus_db_queries::db::lookup::ImageLookup; use nexus_db_queries::db::lookup::ImageParentLookup; use nexus_db_queries::db::model::Name; use nexus_types::external_api::shared::{BfdStatus, ProbeInfo}; -use omicron_common::api::external::BgpAnnounceSet; use omicron_common::api::external::BgpAnnouncement; use omicron_common::api::external::BgpConfig; use omicron_common::api::external::BgpExported; use omicron_common::api::external::BgpImportedRouteIpv4; -use omicron_common::api::external::BgpPeer; use omicron_common::api::external::BgpPeerStatus; use omicron_common::api::external::DataPageParams; use omicron_common::api::external::Disk; @@ -82,6 +80,7 @@ use omicron_common::api::external::{ AddressLotCreateResponse, BgpAllowedPrefix, }; use omicron_common::api::external::{AggregateBgpMessageHistory, BgpCommunity}; +use omicron_common::api::external::{BgpAnnounceSet, BgpPeer}; use omicron_common::bail_unless; use omicron_uuid_kinds::GenericUuid; use parse_display::Display; @@ -4353,27 +4352,24 @@ async fn networking_switch_port_configuration_bgp_peer_remove( /// List prefixes allowed to be imported by a given bgp peer #[endpoint { method = GET, - path ="/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/{bgp_peer}/allow-import", + path ="/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/allow-import", tags = ["system/networking"], }] async fn networking_switch_port_configuration_bgp_peer_allow_import_list( rqctx: RequestContext, - path_params: Path, + path_params: Path, + query: Query, ) -> Result>, HttpError> { let apictx = rqctx.context(); let handler = async { let nexus = &apictx.context.nexus; - let params::SwitchPortSettingsBgpPeerInfoSelector { - configuration, - bgp_peer, - } = path_params.into_inner(); let opctx = crate::context::op_context_for_external_api(&rqctx).await?; let settings = nexus .switch_port_configuration_bgp_peer_allow_import_list( &opctx, - configuration, - bgp_peer, + path_params.into_inner().configuration, + query.into_inner().peer_address, ) .await?; @@ -4389,29 +4385,26 @@ async fn networking_switch_port_configuration_bgp_peer_allow_import_list( /// Add prefix to bgp peer allowed import list #[endpoint { method = POST, - path ="/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/{bgp_peer}/allow-import/add", + path ="/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/allow-import/add", tags = ["system/networking"], }] async fn networking_switch_port_configuration_bgp_peer_allow_import_add( rqctx: RequestContext, - path_params: Path, + path_params: Path, prefix: TypedBody, ) -> Result, HttpError> { let apictx = rqctx.context(); let handler = async { let nexus = &apictx.context.nexus; - let params::SwitchPortSettingsBgpPeerInfoSelector { - configuration, - bgp_peer, - } = path_params.into_inner(); let opctx = crate::context::op_context_for_external_api(&rqctx).await?; + let prefix = prefix.into_inner(); let settings = nexus .switch_port_configuration_bgp_peer_allow_import_add( &opctx, - configuration, - bgp_peer, - prefix.into_inner(), + path_params.into_inner().configuration, + prefix.peer_address, + prefix, ) .await?; Ok(HttpResponseCreated(settings.into())) @@ -4426,29 +4419,26 @@ async fn networking_switch_port_configuration_bgp_peer_allow_import_add( /// Remove prefix from bgp peer allowed import list #[endpoint { method = POST, - path ="/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/{bgp_peer}/allow-import/remove", + path ="/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/allow-import/remove", tags = ["system/networking"], }] async fn networking_switch_port_configuration_bgp_peer_allow_import_remove( rqctx: RequestContext, - path_params: Path, + path_params: Path, prefix: TypedBody, ) -> Result { let apictx = rqctx.context(); let handler = async { let nexus = &apictx.context.nexus; - let params::SwitchPortSettingsBgpPeerInfoSelector { - configuration, - bgp_peer, - } = path_params.into_inner(); let opctx = crate::context::op_context_for_external_api(&rqctx).await?; + let prefix = prefix.into_inner(); nexus .switch_port_configuration_bgp_peer_allow_import_remove( &opctx, - configuration, - bgp_peer, - prefix.into_inner(), + path_params.into_inner().configuration, + prefix.peer_address, + prefix, ) .await?; Ok(HttpResponseDeleted()) @@ -4463,27 +4453,24 @@ async fn networking_switch_port_configuration_bgp_peer_allow_import_remove( /// List prefixes allowed to be exported by a given bgp peer #[endpoint { method = GET, - path ="/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/{bgp_peer}/allow-export", + path ="/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/allow-export", tags = ["system/networking"], }] async fn networking_switch_port_configuration_bgp_peer_allow_export_list( rqctx: RequestContext, - path_params: Path, + path_params: Path, + query: Query, ) -> Result>, HttpError> { let apictx = rqctx.context(); let handler = async { let nexus = &apictx.context.nexus; - let params::SwitchPortSettingsBgpPeerInfoSelector { - configuration, - bgp_peer, - } = path_params.into_inner(); let opctx = crate::context::op_context_for_external_api(&rqctx).await?; let settings = nexus .switch_port_configuration_bgp_peer_allow_export_list( &opctx, - configuration, - bgp_peer, + path_params.into_inner().configuration, + query.into_inner().peer_address, ) .await?; @@ -4499,29 +4486,26 @@ async fn networking_switch_port_configuration_bgp_peer_allow_export_list( /// Add prefix to bgp peer allowed export list #[endpoint { method = POST, - path ="/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/{bgp_peer}/allow-export/add", + path ="/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/allow-export/add", tags = ["system/networking"], }] async fn networking_switch_port_configuration_bgp_peer_allow_export_add( rqctx: RequestContext, - path_params: Path, + path_params: Path, prefix: TypedBody, ) -> Result, HttpError> { let apictx = rqctx.context(); let handler = async { let nexus = &apictx.context.nexus; - let params::SwitchPortSettingsBgpPeerInfoSelector { - configuration, - bgp_peer, - } = path_params.into_inner(); let opctx = crate::context::op_context_for_external_api(&rqctx).await?; + let prefix = prefix.into_inner(); let settings = nexus .switch_port_configuration_bgp_peer_allow_export_add( &opctx, - configuration, - bgp_peer, - prefix.into_inner(), + path_params.into_inner().configuration, + prefix.peer_address, + prefix, ) .await?; Ok(HttpResponseCreated(settings.into())) @@ -4536,29 +4520,26 @@ async fn networking_switch_port_configuration_bgp_peer_allow_export_add( /// Remove prefix from bgp peer allowed export list #[endpoint { method = POST, - path ="/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/{bgp_peer}/allow-export/remove", + path ="/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/allow-export/remove", tags = ["system/networking"], }] async fn networking_switch_port_configuration_bgp_peer_allow_export_remove( rqctx: RequestContext, - path_params: Path, + path_params: Path, prefix: TypedBody, ) -> Result { let apictx = rqctx.context(); let handler = async { let nexus = &apictx.context.nexus; - let params::SwitchPortSettingsBgpPeerInfoSelector { - configuration, - bgp_peer, - } = path_params.into_inner(); let opctx = crate::context::op_context_for_external_api(&rqctx).await?; + let prefix = prefix.into_inner(); nexus .switch_port_configuration_bgp_peer_allow_export_remove( &opctx, - configuration, - bgp_peer, - prefix.into_inner(), + path_params.into_inner().configuration, + prefix.peer_address, + prefix, ) .await?; Ok(HttpResponseDeleted()) @@ -4573,27 +4554,24 @@ async fn networking_switch_port_configuration_bgp_peer_allow_export_remove( /// List communities assigned to a bgp peer #[endpoint { method = GET, - path ="/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/{bgp_peer}/community", + path ="/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/community", tags = ["system/networking"], }] async fn networking_switch_port_configuration_bgp_peer_community_list( rqctx: RequestContext, - path_params: Path, + path_params: Path, + query: Query, ) -> Result>, HttpError> { let apictx = rqctx.context(); let handler = async { let nexus = &apictx.context.nexus; - let params::SwitchPortSettingsBgpPeerInfoSelector { - configuration, - bgp_peer, - } = path_params.into_inner(); let opctx = crate::context::op_context_for_external_api(&rqctx).await?; let settings = nexus .switch_port_configuration_bgp_peer_community_list( &opctx, - configuration, - bgp_peer, + path_params.into_inner().configuration, + query.into_inner().peer_address, ) .await?; Ok(HttpResponseOk(settings.into_iter().map(Into::into).collect())) @@ -4608,29 +4586,26 @@ async fn networking_switch_port_configuration_bgp_peer_community_list( /// Add community to bgp peer #[endpoint { method = POST, - path ="/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/{bgp_peer}/community/add", + path ="/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/community/add", tags = ["system/networking"], }] async fn networking_switch_port_configuration_bgp_peer_community_add( rqctx: RequestContext, - path_params: Path, + path_params: Path, community: TypedBody, ) -> Result, HttpError> { let apictx = rqctx.context(); let handler = async { let nexus = &apictx.context.nexus; - let params::SwitchPortSettingsBgpPeerInfoSelector { - configuration, - bgp_peer, - } = path_params.into_inner(); let opctx = crate::context::op_context_for_external_api(&rqctx).await?; + let community = community.into_inner(); let settings = nexus .switch_port_configuration_bgp_peer_community_add( &opctx, - configuration, - bgp_peer, - community.into_inner(), + path_params.into_inner().configuration, + community.peer_address, + community, ) .await?; Ok(HttpResponseCreated(settings.into())) @@ -4645,29 +4620,26 @@ async fn networking_switch_port_configuration_bgp_peer_community_add( /// Remove community from bgp peer #[endpoint { method = POST, - path ="/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/{bgp_peer}/community/remove", + path ="/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/community/remove", tags = ["system/networking"], }] async fn networking_switch_port_configuration_bgp_peer_community_remove( rqctx: RequestContext, - path_params: Path, + path_params: Path, community: TypedBody, ) -> Result { let apictx = rqctx.context(); let handler = async { let nexus = &apictx.context.nexus; - let params::SwitchPortSettingsBgpPeerInfoSelector { - configuration, - bgp_peer, - } = path_params.into_inner(); let opctx = crate::context::op_context_for_external_api(&rqctx).await?; + let community = community.into_inner(); nexus .switch_port_configuration_bgp_peer_community_remove( &opctx, - configuration, - bgp_peer, - community.into_inner(), + path_params.into_inner().configuration, + community.peer_address, + community, ) .await?; Ok(HttpResponseDeleted()) diff --git a/nexus/tests/integration_tests/switch_port.rs b/nexus/tests/integration_tests/switch_port.rs index 2c77da2a6c..7e94c71ec9 100644 --- a/nexus/tests/integration_tests/switch_port.rs +++ b/nexus/tests/integration_tests/switch_port.rs @@ -18,8 +18,8 @@ use nexus_types::external_api::params::{ use nexus_types::external_api::views::Rack; use omicron_common::api::external::ImportExportPolicy; use omicron_common::api::external::{ - self, AddressLotKind, BgpPeer, IdentityMetadataCreateParams, LinkFec, - LinkSpeed, NameOrId, SwitchPort, SwitchPortSettingsView, + self, AddressLotKind, BgpPeerCombined, IdentityMetadataCreateParams, + LinkFec, LinkSpeed, NameOrId, SwitchPort, SwitchPortSettingsView, }; type ControlPlaneTestContext = @@ -298,7 +298,7 @@ async fn test_port_settings_basic_crud(ctx: &ControlPlaneTestContext) { settings.bgp_peers.insert( "phy0".into(), BgpPeerConfig { - peers: vec![BgpPeer { + peers: vec![BgpPeerCombined { bgp_config: NameOrId::Name("as47".parse().unwrap()), interface_name: "phy0".to_string(), addr: "1.2.3.4".parse().unwrap(), diff --git a/nexus/tests/output/nexus_tags.txt b/nexus/tests/output/nexus_tags.txt index de546a3028..ee766b7665 100644 --- a/nexus/tests/output/nexus_tags.txt +++ b/nexus/tests/output/nexus_tags.txt @@ -198,6 +198,15 @@ networking_switch_port_configuration_address_add POST /v1/system/networking/ networking_switch_port_configuration_address_list GET /v1/system/networking/switch-port-configuration/{configuration}/address networking_switch_port_configuration_address_remove POST /v1/system/networking/switch-port-configuration/{configuration}/address/remove networking_switch_port_configuration_bgp_peer_add POST /v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/add +networking_switch_port_configuration_bgp_peer_allow_export_add POST /v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/allow-export/add +networking_switch_port_configuration_bgp_peer_allow_export_list GET /v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/allow-export +networking_switch_port_configuration_bgp_peer_allow_export_remove POST /v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/allow-export/remove +networking_switch_port_configuration_bgp_peer_allow_import_add POST /v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/allow-import/add +networking_switch_port_configuration_bgp_peer_allow_import_list GET /v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/allow-import +networking_switch_port_configuration_bgp_peer_allow_import_remove POST /v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/allow-import/remove +networking_switch_port_configuration_bgp_peer_community_add POST /v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/community/add +networking_switch_port_configuration_bgp_peer_community_list GET /v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/community +networking_switch_port_configuration_bgp_peer_community_remove POST /v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/community/remove networking_switch_port_configuration_bgp_peer_list GET /v1/system/networking/switch-port-configuration/{configuration}/bgp-peer networking_switch_port_configuration_bgp_peer_remove POST /v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/remove networking_switch_port_configuration_create POST /v1/system/networking/switch-port-configuration diff --git a/nexus/tests/output/uncovered-authz-endpoints.txt b/nexus/tests/output/uncovered-authz-endpoints.txt index d42d061073..d578b87b37 100644 --- a/nexus/tests/output/uncovered-authz-endpoints.txt +++ b/nexus/tests/output/uncovered-authz-endpoints.txt @@ -7,6 +7,9 @@ ping (get "/v1/ping") networking_switch_port_status (get "/v1/system/hardware/switch-port/{port}/status") networking_switch_port_configuration_address_list (get "/v1/system/networking/switch-port-configuration/{configuration}/address") networking_switch_port_configuration_bgp_peer_list (get "/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer") +networking_switch_port_configuration_bgp_peer_allow_export_list (get "/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/allow-export") +networking_switch_port_configuration_bgp_peer_allow_import_list (get "/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/allow-import") +networking_switch_port_configuration_bgp_peer_community_list (get "/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/community") networking_switch_port_configuration_geometry_view (get "/v1/system/networking/switch-port-configuration/{configuration}/geometry") networking_switch_port_configuration_link_list (get "/v1/system/networking/switch-port-configuration/{configuration}/link") networking_switch_port_configuration_link_view (get "/v1/system/networking/switch-port-configuration/{configuration}/link/{link}") @@ -21,6 +24,12 @@ logout (post "/v1/logout") networking_switch_port_configuration_address_add (post "/v1/system/networking/switch-port-configuration/{configuration}/address/add") networking_switch_port_configuration_address_remove (post "/v1/system/networking/switch-port-configuration/{configuration}/address/remove") networking_switch_port_configuration_bgp_peer_add (post "/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/add") +networking_switch_port_configuration_bgp_peer_allow_export_add (post "/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/allow-export/add") +networking_switch_port_configuration_bgp_peer_allow_export_remove (post "/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/allow-export/remove") +networking_switch_port_configuration_bgp_peer_allow_import_add (post "/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/allow-import/add") +networking_switch_port_configuration_bgp_peer_allow_import_remove (post "/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/allow-import/remove") +networking_switch_port_configuration_bgp_peer_community_add (post "/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/community/add") +networking_switch_port_configuration_bgp_peer_community_remove (post "/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/community/remove") networking_switch_port_configuration_bgp_peer_remove (post "/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/remove") networking_switch_port_configuration_geometry_set (post "/v1/system/networking/switch-port-configuration/{configuration}/geometry") networking_switch_port_configuration_link_create (post "/v1/system/networking/switch-port-configuration/{configuration}/link") diff --git a/nexus/types/src/external_api/params.rs b/nexus/types/src/external_api/params.rs index fb8abafdf7..e569f465b4 100644 --- a/nexus/types/src/external_api/params.rs +++ b/nexus/types/src/external_api/params.rs @@ -9,8 +9,8 @@ use crate::external_api::shared; use base64::Engine; use chrono::{DateTime, Utc}; use omicron_common::api::external::{ - AddressLotKind, AllowedSourceIps, BfdMode, BgpPeer, ByteCount, Hostname, - IdentityMetadataCreateParams, IdentityMetadataUpdateParams, + AddressLotKind, AllowedSourceIps, BfdMode, BgpPeerCombined, ByteCount, + Hostname, IdentityMetadataCreateParams, IdentityMetadataUpdateParams, InstanceCpuCount, LinkFec, LinkSpeed, Name, NameOrId, PaginationOrder, RouteDestination, RouteTarget, SemverVersion, UserId, }; @@ -1644,6 +1644,9 @@ pub struct RouteAddRemove { /// A prefix allowed to be imported or exported by a bgp peer #[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)] pub struct AllowedPrefixAddRemove { + /// An address identifying the target bgp peer + pub peer_address: IpAddr, + /// The interface the peer is configured on pub interface: Name, @@ -1654,6 +1657,9 @@ pub struct AllowedPrefixAddRemove { /// A community to be added to or removed from a bgp peer #[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)] pub struct BgpCommunityAddRemove { + /// An address identifying the target bgp peer + pub peer_address: IpAddr, + /// The interface the peer is configured on pub interface: Name, @@ -1677,7 +1683,7 @@ pub struct BgpConfigListSelector { #[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)] pub struct BgpPeerConfig { - pub peers: Vec, + pub peers: Vec, } /// Parameters for creating a named set of BGP announcements. @@ -1860,7 +1866,14 @@ pub struct SwitchPortSettingsBgpPeerInfoSelector { pub configuration: NameOrId, /// An address identifying a configured bgp peer. - pub bgp_peer: IpAddr, + pub peer_address: IpAddr, +} + +/// Select a Bgp Peer by address. +#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, PartialEq)] +pub struct BgpPeerQuerySelector { + /// An address identifying a configured bgp peer. + pub peer_address: IpAddr, } /// Select a link settings info object by port settings name and link name. diff --git a/openapi/nexus.json b/openapi/nexus.json index 38f70e8766..19d205ec17 100644 --- a/openapi/nexus.json +++ b/openapi/nexus.json @@ -7489,6 +7489,429 @@ } } }, + "/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/allow-export": { + "get": { + "tags": [ + "system/networking" + ], + "summary": "List prefixes allowed to be exported by a given bgp peer", + "operationId": "networking_switch_port_configuration_bgp_peer_allow_export_list", + "parameters": [ + { + "in": "path", + "name": "configuration", + "description": "A name or id to use when selecting a switch port configuration.", + "required": true, + "schema": { + "$ref": "#/components/schemas/NameOrId" + } + }, + { + "in": "query", + "name": "peer_address", + "description": "An address identifying a configured bgp peer.", + "required": true, + "schema": { + "type": "string", + "format": "ip" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Array_of_BgpAllowedPrefix", + "type": "array", + "items": { + "$ref": "#/components/schemas/BgpAllowedPrefix" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/allow-export/add": { + "post": { + "tags": [ + "system/networking" + ], + "summary": "Add prefix to bgp peer allowed export list", + "operationId": "networking_switch_port_configuration_bgp_peer_allow_export_add", + "parameters": [ + { + "in": "path", + "name": "configuration", + "description": "A name or id to use when selecting a switch port configuration.", + "required": true, + "schema": { + "$ref": "#/components/schemas/NameOrId" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AllowedPrefixAddRemove" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "successful creation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BgpAllowedPrefix" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/allow-export/remove": { + "post": { + "tags": [ + "system/networking" + ], + "summary": "Remove prefix from bgp peer allowed export list", + "operationId": "networking_switch_port_configuration_bgp_peer_allow_export_remove", + "parameters": [ + { + "in": "path", + "name": "configuration", + "description": "A name or id to use when selecting a switch port configuration.", + "required": true, + "schema": { + "$ref": "#/components/schemas/NameOrId" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AllowedPrefixAddRemove" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "successful deletion" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/allow-import": { + "get": { + "tags": [ + "system/networking" + ], + "summary": "List prefixes allowed to be imported by a given bgp peer", + "operationId": "networking_switch_port_configuration_bgp_peer_allow_import_list", + "parameters": [ + { + "in": "path", + "name": "configuration", + "description": "A name or id to use when selecting a switch port configuration.", + "required": true, + "schema": { + "$ref": "#/components/schemas/NameOrId" + } + }, + { + "in": "query", + "name": "peer_address", + "description": "An address identifying a configured bgp peer.", + "required": true, + "schema": { + "type": "string", + "format": "ip" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Array_of_BgpAllowedPrefix", + "type": "array", + "items": { + "$ref": "#/components/schemas/BgpAllowedPrefix" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/allow-import/add": { + "post": { + "tags": [ + "system/networking" + ], + "summary": "Add prefix to bgp peer allowed import list", + "operationId": "networking_switch_port_configuration_bgp_peer_allow_import_add", + "parameters": [ + { + "in": "path", + "name": "configuration", + "description": "A name or id to use when selecting a switch port configuration.", + "required": true, + "schema": { + "$ref": "#/components/schemas/NameOrId" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AllowedPrefixAddRemove" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "successful creation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BgpAllowedPrefix" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/allow-import/remove": { + "post": { + "tags": [ + "system/networking" + ], + "summary": "Remove prefix from bgp peer allowed import list", + "operationId": "networking_switch_port_configuration_bgp_peer_allow_import_remove", + "parameters": [ + { + "in": "path", + "name": "configuration", + "description": "A name or id to use when selecting a switch port configuration.", + "required": true, + "schema": { + "$ref": "#/components/schemas/NameOrId" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AllowedPrefixAddRemove" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "successful deletion" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/community": { + "get": { + "tags": [ + "system/networking" + ], + "summary": "List communities assigned to a bgp peer", + "operationId": "networking_switch_port_configuration_bgp_peer_community_list", + "parameters": [ + { + "in": "path", + "name": "configuration", + "description": "A name or id to use when selecting a switch port configuration.", + "required": true, + "schema": { + "$ref": "#/components/schemas/NameOrId" + } + }, + { + "in": "query", + "name": "peer_address", + "description": "An address identifying a configured bgp peer.", + "required": true, + "schema": { + "type": "string", + "format": "ip" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Array_of_BgpCommunity", + "type": "array", + "items": { + "$ref": "#/components/schemas/BgpCommunity" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/community/add": { + "post": { + "tags": [ + "system/networking" + ], + "summary": "Add community to bgp peer", + "operationId": "networking_switch_port_configuration_bgp_peer_community_add", + "parameters": [ + { + "in": "path", + "name": "configuration", + "description": "A name or id to use when selecting a switch port configuration.", + "required": true, + "schema": { + "$ref": "#/components/schemas/NameOrId" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BgpCommunityAddRemove" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "successful creation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BgpCommunity" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/community/remove": { + "post": { + "tags": [ + "system/networking" + ], + "summary": "Remove community from bgp peer", + "operationId": "networking_switch_port_configuration_bgp_peer_community_remove", + "parameters": [ + { + "in": "path", + "name": "configuration", + "description": "A name or id to use when selecting a switch port configuration.", + "required": true, + "schema": { + "$ref": "#/components/schemas/NameOrId" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BgpCommunityAddRemove" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "successful deletion" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, "/v1/system/networking/switch-port-configuration/{configuration}/bgp-peer/remove": { "post": { "tags": [ @@ -10735,6 +11158,38 @@ "allowed_ips" ] }, + "AllowedPrefixAddRemove": { + "description": "A prefix allowed to be imported or exported by a bgp peer", + "type": "object", + "properties": { + "interface": { + "description": "The interface the peer is configured on", + "allOf": [ + { + "$ref": "#/components/schemas/Name" + } + ] + }, + "peer_address": { + "description": "An address identifying the target bgp peer", + "type": "string", + "format": "ip" + }, + "prefix": { + "description": "The allowed prefix to add or remove", + "allOf": [ + { + "$ref": "#/components/schemas/IpNet" + } + ] + } + }, + "required": [ + "interface", + "peer_address", + "prefix" + ] + }, "AllowedSourceIps": { "description": "Description of source IPs allowed to reach rack services.", "oneOf": [ @@ -10988,6 +11443,43 @@ "switch" ] }, + "BgpAllowedPrefix": { + "description": "A BGP allowed prefix entry", + "type": "object", + "properties": { + "addr": { + "description": "Peer Address", + "allOf": [ + { + "$ref": "#/components/schemas/IpNet" + } + ] + }, + "interface_name": { + "description": "Interface peer is reachable on", + "type": "string" + }, + "port_settings_id": { + "description": "Parent switch port configuration", + "type": "string", + "format": "uuid" + }, + "prefix": { + "description": "Allowed Prefix", + "allOf": [ + { + "$ref": "#/components/schemas/IpNet" + } + ] + } + }, + "required": [ + "addr", + "interface_name", + "port_settings_id", + "prefix" + ] + }, "BgpAnnounceSet": { "description": "Represents a BGP announce set by id. The id can be used with other API calls to view and manage the announce set.", "type": "object", @@ -11107,6 +11599,71 @@ "network" ] }, + "BgpCommunity": { + "description": "A BGP community", + "type": "object", + "properties": { + "addr": { + "description": "Peer Address", + "allOf": [ + { + "$ref": "#/components/schemas/IpNet" + } + ] + }, + "community": { + "description": "Community", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "interface_name": { + "description": "Interface peer is reachable on", + "type": "string" + }, + "port_settings_id": { + "description": "Parent switch port configuration", + "type": "string", + "format": "uuid" + } + }, + "required": [ + "addr", + "community", + "interface_name", + "port_settings_id" + ] + }, + "BgpCommunityAddRemove": { + "description": "A community to be added to or removed from a bgp peer", + "type": "object", + "properties": { + "community": { + "description": "The community to add or remove", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "interface": { + "description": "The interface the peer is configured on", + "allOf": [ + { + "$ref": "#/components/schemas/Name" + } + ] + }, + "peer_address": { + "description": "An address identifying the target bgp peer", + "type": "string", + "format": "ip" + } + }, + "required": [ + "community", + "interface", + "peer_address" + ] + }, "BgpConfig": { "description": "A base BGP configuration.", "type": "object", @@ -11276,6 +11833,127 @@ }, "BgpMessageHistory": {}, "BgpPeer": { + "description": "The information required to configure a BGP peer.", + "type": "object", + "properties": { + "addr": { + "description": "The address of th e host to peer with.", + "allOf": [ + { + "$ref": "#/components/schemas/IpNet" + } + ] + }, + "allow_export_list_active": { + "description": "Enable export policies", + "type": "boolean" + }, + "allow_import_list_active": { + "description": "Enable import policies", + "type": "boolean" + }, + "bgp_config": { + "description": "The global BGP configuration used for establishing a session with this peer.", + "allOf": [ + { + "$ref": "#/components/schemas/NameOrId" + } + ] + }, + "connect_retry": { + "description": "How long to to wait between TCP connection retries (seconds).", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "delay_open": { + "description": "How long to delay sending an open request after establishing a TCP session (seconds).", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "enforce_first_as": { + "description": "Enforce that the first AS in paths received from this peer is the peer's AS.", + "type": "boolean" + }, + "hold_time": { + "description": "How long to hold peer connections between keepalives (seconds).", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "idle_hold_time": { + "description": "How long to hold a peer in idle before attempting a new session (seconds).", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "interface_name": { + "description": "The name of interface to peer on. This is relative to the port configuration this BGP peer configuration is a part of. For example this value could be phy0 to refer to a primary physical interface. Or it could be vlan47 to refer to a VLAN interface.", + "type": "string" + }, + "keepalive": { + "description": "How often to send keepalive requests (seconds).", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "local_pref": { + "nullable": true, + "description": "Apply a local preference to routes received from this peer.", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "md5_auth_key": { + "nullable": true, + "description": "Use the given key for TCP-MD5 authentication with the peer.", + "type": "string" + }, + "min_ttl": { + "nullable": true, + "description": "Require messages from a peer have a minimum IP time to live field.", + "type": "integer", + "format": "uint8", + "minimum": 0 + }, + "multi_exit_discriminator": { + "nullable": true, + "description": "Apply the provided multi-exit discriminator (MED) updates sent to the peer.", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "remote_asn": { + "nullable": true, + "description": "Require that a peer has a specified ASN.", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "vlan_id": { + "nullable": true, + "description": "Associate a VLAN ID with a peer.", + "type": "integer", + "format": "uint16", + "minimum": 0 + } + }, + "required": [ + "addr", + "allow_export_list_active", + "allow_import_list_active", + "bgp_config", + "connect_retry", + "delay_open", + "enforce_first_as", + "hold_time", + "idle_hold_time", + "interface_name", + "keepalive" + ] + }, + "BgpPeerCombined": { "description": "A BGP peer configuration for an interface. Includes the set of announcements that will be advertised to the peer identified by `addr`. The `bgp_config` parameter is a reference to global BGP parameters. The `interface_name` indicates what interface the peer should be contacted on.", "type": "object", "properties": { @@ -11417,7 +12095,7 @@ "peers": { "type": "array", "items": { - "$ref": "#/components/schemas/BgpPeer" + "$ref": "#/components/schemas/BgpPeerCombined" } } }, @@ -20499,7 +21177,7 @@ "description": "BGP peer settings.", "type": "array", "items": { - "$ref": "#/components/schemas/BgpPeer" + "$ref": "#/components/schemas/BgpPeerCombined" } }, "groups": {