Skip to content

Commit

Permalink
hook up probes to projects/vpcs/interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
rcgoodfellow committed Dec 12, 2023
1 parent d7bf507 commit a951832
Show file tree
Hide file tree
Showing 21 changed files with 332 additions and 112 deletions.
Empty file modified .github/buildomat/jobs/tuf-repo.sh
100644 → 100755
Empty file.
2 changes: 2 additions & 0 deletions clients/nexus-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ progenitor::generate_api!(
MacAddr = omicron_common::api::external::MacAddr,
Name = omicron_common::api::external::Name,
NewPasswordHash = omicron_passwords::NewPasswordHash,
NetworkInterface = omicron_common::api::internal::shared::NetworkInterface,
NetworkInterfaceKind = omicron_common::api::internal::shared::NetworkInterfaceKind,
}
);

Expand Down
37 changes: 2 additions & 35 deletions clients/sled-agent-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ progenitor::generate_api!(
IpNetwork = ipnetwork::IpNetwork,
PortFec = omicron_common::api::internal::shared::PortFec,
PortSpeed = omicron_common::api::internal::shared::PortSpeed,
NetworkInterface = omicron_common::api::internal::shared::NetworkInterface,
NetworkInterfaceKind = omicron_common::api::internal::shared::NetworkInterfaceKind,
}
);

Expand Down Expand Up @@ -455,41 +457,6 @@ impl From<omicron_common::api::external::VpcFirewallRuleProtocol>
}
}

impl From<omicron_common::api::internal::shared::NetworkInterfaceKind>
for types::NetworkInterfaceKind
{
fn from(
s: omicron_common::api::internal::shared::NetworkInterfaceKind,
) -> Self {
use omicron_common::api::internal::shared::NetworkInterfaceKind::*;
match s {
Instance { id } => Self::Instance(id),
Service { id } => Self::Service(id),
Probe { id } => Self::Probe(id),
}
}
}

impl From<omicron_common::api::internal::shared::NetworkInterface>
for types::NetworkInterface
{
fn from(
s: omicron_common::api::internal::shared::NetworkInterface,
) -> Self {
Self {
id: s.id,
kind: s.kind.into(),
name: (&s.name).into(),
ip: s.ip,
mac: s.mac.into(),
subnet: s.subnet.into(),
vni: s.vni.into(),
primary: s.primary,
slot: s.slot,
}
}
}

impl From<omicron_common::api::internal::shared::SourceNatConfig>
for types::SourceNatConfig
{
Expand Down
1 change: 1 addition & 0 deletions common/src/api/external/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,7 @@ pub enum ResourceType {
Vmm,
Ipv4NatEntry,
FloatingIp,
ProbeNetworkInterface,
}

// IDENTITY METADATA
Expand Down
28 changes: 28 additions & 0 deletions nexus/db-model/src/network_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ impl_enum_type! {

Instance => b"instance"
Service => b"service"
Probe => b"probe"
}

/// Generic Network Interface DB model.
Expand Down Expand Up @@ -56,6 +57,14 @@ pub struct NetworkInterface {
pub primary: bool,
}

impl Into<omicron_common::api::internal::shared::NetworkInterface>
for NetworkInterface
{
fn into(self) -> omicron_common::api::internal::shared::NetworkInterface {
todo!()
}
}

/// Instance Network Interface DB model.
///
/// The underlying "table" (`instance_network_interface`) is actually a view
Expand Down Expand Up @@ -287,6 +296,25 @@ impl IncompleteNetworkInterface {
mac,
)
}

pub fn new_probe(
interface_id: Uuid,
probe_id: Uuid,
subnet: VpcSubnet,
identity: external::IdentityMetadataCreateParams,
ip: Option<std::net::IpAddr>,
mac: Option<external::MacAddr>,
) -> Result<Self, external::Error> {
Self::new(
interface_id,
NetworkInterfaceKind::Probe,
probe_id,
subnet,
identity,
ip,
mac,
)
}
}

/// Describes a set of updates for the [`NetworkInterface`] model.
Expand Down
66 changes: 51 additions & 15 deletions nexus/db-queries/src/db/datastore/network_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ use omicron_common::api::external::http_pagination::PaginatedBy;
use omicron_common::api::external::DeleteResult;
use omicron_common::api::external::Error;
use omicron_common::api::external::ListResultVec;
use omicron_common::api::external::LookupResult;
use omicron_common::api::external::LookupType;
use omicron_common::api::external::ResourceType;
use omicron_common::api::external::UpdateResult;
use ref_cast::RefCast;
use sled_agent_client::types as sled_client_types;
use uuid::Uuid;

/// OPTE requires information that's currently split across the network
Expand All @@ -58,29 +58,34 @@ struct NicInfo {
slot: i16,
}

impl From<NicInfo> for sled_client_types::NetworkInterface {
fn from(nic: NicInfo) -> sled_client_types::NetworkInterface {
impl From<NicInfo> for omicron_common::api::internal::shared::NetworkInterface {
fn from(
nic: NicInfo,
) -> omicron_common::api::internal::shared::NetworkInterface {
let ip_subnet = if nic.ip.is_ipv4() {
external::IpNet::V4(nic.ipv4_block.0)
} else {
external::IpNet::V6(nic.ipv6_block.0)
};
let kind = match nic.kind {
NetworkInterfaceKind::Instance => {
sled_client_types::NetworkInterfaceKind::Instance(nic.parent_id)
omicron_common::api::internal::shared::NetworkInterfaceKind::Instance{ id: nic.parent_id }
}
NetworkInterfaceKind::Service => {
sled_client_types::NetworkInterfaceKind::Service(nic.parent_id)
omicron_common::api::internal::shared::NetworkInterfaceKind::Service{ id: nic.parent_id }
}
NetworkInterfaceKind::Probe => {
omicron_common::api::internal::shared::NetworkInterfaceKind::Probe{ id: nic.parent_id }
}
};
sled_client_types::NetworkInterface {
omicron_common::api::internal::shared::NetworkInterface {
id: nic.id,
kind,
name: sled_client_types::Name::from(&nic.name.0),
name: nic.name.into(),
ip: nic.ip.ip(),
mac: sled_client_types::MacAddr::from(nic.mac.0),
subnet: sled_client_types::IpNet::from(ip_subnet),
vni: sled_client_types::Vni::from(nic.vni.0),
mac: nic.mac.into(),
subnet: ip_subnet,
vni: nic.vni.0,
primary: nic.primary,
slot: u8::try_from(nic.slot).unwrap(),
}
Expand All @@ -107,6 +112,14 @@ impl DataStore {
self.instance_create_network_interface_raw(&opctx, interface).await
}

pub async fn probe_create_network_interface(
&self,
opctx: &OpContext,
interface: IncompleteNetworkInterface,
) -> Result<NetworkInterface, network_interface::InsertError> {
self.create_network_interface_raw(&opctx, interface).await
}

pub(crate) async fn instance_create_network_interface_raw(
&self,
opctx: &OpContext,
Expand Down Expand Up @@ -258,7 +271,8 @@ impl DataStore {
&self,
opctx: &OpContext,
partial_query: BoxedQuery<db::schema::network_interface::table>,
) -> ListResultVec<sled_client_types::NetworkInterface> {
) -> ListResultVec<omicron_common::api::internal::shared::NetworkInterface>
{
use db::schema::network_interface;
use db::schema::vpc;
use db::schema::vpc_subnet;
Expand Down Expand Up @@ -294,7 +308,7 @@ impl DataStore {
.map_err(|e| public_error_from_diesel(e, ErrorHandler::Server))?;
Ok(rows
.into_iter()
.map(sled_client_types::NetworkInterface::from)
.map(omicron_common::api::internal::shared::NetworkInterface::from)
.collect())
}

Expand All @@ -304,7 +318,8 @@ impl DataStore {
&self,
opctx: &OpContext,
authz_instance: &authz::Instance,
) -> ListResultVec<sled_client_types::NetworkInterface> {
) -> ListResultVec<omicron_common::api::internal::shared::NetworkInterface>
{
opctx.authorize(authz::Action::ListChildren, authz_instance).await?;

use db::schema::network_interface;
Expand All @@ -326,7 +341,8 @@ impl DataStore {
&self,
opctx: &OpContext,
authz_vpc: &authz::Vpc,
) -> ListResultVec<sled_client_types::NetworkInterface> {
) -> ListResultVec<omicron_common::api::internal::shared::NetworkInterface>
{
opctx.authorize(authz::Action::ListChildren, authz_vpc).await?;

use db::schema::network_interface;
Expand All @@ -345,7 +361,8 @@ impl DataStore {
&self,
opctx: &OpContext,
authz_subnet: &authz::VpcSubnet,
) -> ListResultVec<sled_client_types::NetworkInterface> {
) -> ListResultVec<omicron_common::api::internal::shared::NetworkInterface>
{
opctx.authorize(authz::Action::ListChildren, authz_subnet).await?;

use db::schema::network_interface;
Expand Down Expand Up @@ -388,6 +405,25 @@ impl DataStore {
.map_err(|e| public_error_from_diesel(e, ErrorHandler::Server))
}

/// Get network interface associated with a given probe.
pub async fn probe_get_network_interface(
&self,
opctx: &OpContext,
probe_id: Uuid,
) -> LookupResult<NetworkInterface> {
use db::schema::network_interface::dsl;

dsl::network_interface
.filter(dsl::time_deleted.is_null())
.filter(dsl::parent_id.eq(probe_id))
.select(NetworkInterface::as_select())
.first_async::<NetworkInterface>(
&*self.pool_connection_authorized(opctx).await?,
)
.await
.map_err(|e| public_error_from_diesel(e, ErrorHandler::Server))
}

/// Update a network interface associated with a given instance.
pub async fn instance_update_network_interface(
&self,
Expand Down
49 changes: 48 additions & 1 deletion nexus/db-queries/src/db/datastore/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,25 @@ use crate::context::OpContext;
use crate::db;
use crate::db::error::public_error_from_diesel;
use crate::db::error::ErrorHandler;
use crate::db::lookup::LookupPath;
use crate::db::model::Name;
use crate::db::pagination::paginated;
use async_bb8_diesel::AsyncRunQueryDsl;
use chrono::Utc;
use diesel::{ExpressionMethods, QueryDsl, SelectableHelper};
//use nexus_db_model::ExternalIp;
use nexus_db_model::IncompleteNetworkInterface;
use nexus_db_model::Probe;
use nexus_types::external_api::params;
use nexus_types::identity::Resource;
use omicron_common::api::external::http_pagination::PaginatedBy;
use omicron_common::api::external::CreateResult;
use omicron_common::api::external::DataPageParams;
use omicron_common::api::external::DeleteResult;
use omicron_common::api::external::IdentityMetadataCreateParams;
use omicron_common::api::external::ListResultVec;
use omicron_common::api::external::LookupResult;
use omicron_common::api::external::NameOrId;
use omicron_common::api::internal::shared::NetworkInterface;
use ref_cast::RefCast;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
Expand All @@ -31,6 +34,7 @@ pub struct ProbeInfo {
pub name: Name,
sled: Uuid,
pub external_ips: Vec<ExternalIp>,
pub interface: NetworkInterface,
}

#[derive(Debug, Clone, JsonSchema, Serialize, Deserialize)]
Expand Down Expand Up @@ -125,10 +129,14 @@ impl super::DataStore {
.map(Into::into)
.collect();

let interface =
self.probe_get_network_interface(opctx, probe.id()).await?;

result.push(ProbeInfo {
id: probe.id(),
name: probe.name().clone().into(),
sled: probe.sled,
interface: interface.into(),
external_ips,
})
}
Expand Down Expand Up @@ -188,6 +196,45 @@ impl super::DataStore {
)
.await?;

let default_name = omicron_common::api::external::Name::try_from(
"default".to_string(),
)
.unwrap();
let internal_default_name = db::model::Name::from(default_name.clone());

let (.., db_subnet) = LookupPath::new(opctx, self)
.project_name(&new_probe.project.clone().into())
.vpc_name(&internal_default_name)
.vpc_subnet_name(&internal_default_name)
.fetch()
.await?;

let incomplete = IncompleteNetworkInterface::new_probe(
Uuid::new_v4(),
probe.id(),
db_subnet, //todo!(), //VpcSubnet
IdentityMetadataCreateParams {
name: probe.name().clone(),
description: format!(
"default primary interface for {}",
probe.name(),
),
},
None, //Request IP address assignment
None, //Request MAC address assignment
)?;

let _ifx = self
.probe_create_network_interface(opctx, incomplete)
.await
.map_err(|e| {
omicron_common::api::external::Error::InternalError {
internal_message: format!(
"create network interface: {e:?}"
),
}
})?;

let result = diesel::insert_into(dsl::probe)
.values(probe.clone())
.returning(Probe::as_returning())
Expand Down
9 changes: 8 additions & 1 deletion nexus/db-queries/src/db/queries/network_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ impl InsertError {
InsertError::InterfaceAlreadyExists(_name, NetworkInterfaceKind::Service) => {
unimplemented!("service network interface")
}
InsertError::InterfaceAlreadyExists(_name, NetworkInterfaceKind::Probe) => {
unimplemented!("probe network interface")
}
InsertError::NoAvailableIpAddresses => {
external::Error::invalid_request(
"No available IP addresses for interface",
Expand Down Expand Up @@ -396,6 +399,9 @@ fn decode_database_error(
NetworkInterfaceKind::Service => {
external::ResourceType::ServiceNetworkInterface
}
NetworkInterfaceKind::Probe => {
external::ResourceType::ProbeNetworkInterface
}
};
InsertError::External(error::public_error_from_diesel(
err,
Expand Down Expand Up @@ -605,7 +611,7 @@ impl NextMacAddress {
let min_shift = x - MacAddr::MIN_GUEST_ADDR;
(base.into(), max_shift, min_shift)
}
NetworkInterfaceKind::Service => {
NetworkInterfaceKind::Service | NetworkInterfaceKind::Probe => {
let base = MacAddr::random_system();
let x = base.to_i64();
let max_shift = MacAddr::MAX_SYSTEM_ADDR - x;
Expand Down Expand Up @@ -2538,6 +2544,7 @@ mod tests {
NetworkInterfaceKind::Service => {
(inserted.mac.is_system(), "system")
}
NetworkInterfaceKind::Probe => (inserted.mac.is_system(), "probe"),
};
assert!(
mac_in_range,
Expand Down
Loading

0 comments on commit a951832

Please sign in to comment.