Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ futures = "0.3.18"
http = "0.2.5"
hyper = "0.14"
ipnetwork = "0.18"
opteadm = { path = "../../opte/opteadm" }
macaddr = { version = "1.0.1", features = [ "serde_std" ] }
reqwest = { version = "0.11", default-features = false, features = ["rustls-tls"] }
ring = "0.16"
Expand Down
6 changes: 6 additions & 0 deletions common/src/api/external/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,12 @@ impl From<anyhow::Error> for crate::api::external::Error {
}
}

impl From<opteadm::Error> for Error {
fn from(err: opteadm::Error) -> Self {
Error::InternalError { internal_message: format!("{}", err) }
}
}

/**
* Like [`assert!`], except that instead of panicking, this function returns an
* `Err(Error::InternalError)` with an appropriate message if the given
Expand Down
15 changes: 12 additions & 3 deletions common/src/api/external/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1759,14 +1759,23 @@ impl JsonSchema for L4PortRange {
/// hardware devices on a network.
// NOTE: We're using the `macaddr` crate for the internal representation. But as with the `ipnet`,
// this crate does not implement `JsonSchema`.
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
#[derive(Clone, Copy, Debug, DeserializeFromStr, PartialEq, SerializeDisplay)]
pub struct MacAddr(pub macaddr::MacAddr6);

impl FromStr for MacAddr {
type Err = macaddr::ParseError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
s.parse().map(|addr| MacAddr(addr))
}
}

impl TryFrom<String> for MacAddr {
type Error = macaddr::ParseError;
type Error = <Self as FromStr>::Err;

fn try_from(s: String) -> Result<Self, Self::Error> {
s.parse().map(|addr| MacAddr(addr))
// s.parse().map(|addr| MacAddr(addr))
MacAddr::from_str(s.as_ref())
}
}

Expand Down
21 changes: 20 additions & 1 deletion nexus/src/nexus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::saga_interface::SagaContext;
use crate::sagas;
use anyhow::Context;
use async_trait::async_trait;
use chrono::Utc;
use futures::future::ready;
use futures::StreamExt;
use hex;
Expand Down Expand Up @@ -1095,14 +1096,32 @@ impl Nexus {
let runtime: nexus::InstanceRuntimeState =
instance.runtime().clone().into();

let rpz_nic = sled_agent_client::types::NetworkInterface {
identity: sled_agent_client::types::IdentityMetadata {
id: Uuid::new_v4(),
name: sled_agent_client::types::Name("rpz-nic".to_string()),
description: "test nic".to_string(),
time_created: Utc::now(),
time_modified: Utc::now(),
},
vpc_id: Uuid::new_v4(),
subnet_id: Uuid::new_v4(),
mac: sled_agent_client::types::MacAddr(
format!("02:08:20:BE:A0:F2")
),
ip: std::net::IpAddr::V4(
std::net::Ipv4Addr::new(10, 0, 0, 213)
).to_string(),
};

// TODO: Populate this with an appropriate NIC.
// See also: sic_create_instance_record in sagas.rs for a similar
// construction.
let instance_hardware = sled_agent_client::types::InstanceHardware {
runtime: sled_agent_client::types::InstanceRuntimeState::from(
runtime,
),
nics: vec![],
nics: vec![rpz_nic],
};

let new_runtime = sa
Expand Down
21 changes: 20 additions & 1 deletion nexus/src/sagas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@ use crate::external_api::params;
use crate::saga_interface::SagaContext;
use chrono::Utc;
use lazy_static::lazy_static;
use omicron_common::api::external;
use omicron_common::api::external::Generation;
use omicron_common::api::external::IdentityMetadata;
use omicron_common::api::external::InstanceState;
use omicron_common::api::external::NetworkInterface;
use omicron_common::api::internal::nexus::InstanceRuntimeState;
use omicron_common::api::internal::sled_agent::InstanceHardware;
use serde::Deserialize;
Expand Down Expand Up @@ -166,11 +169,27 @@ async fn sic_create_instance_record(
.await
.map_err(ActionError::action_failed)?;

let rpz_nic = NetworkInterface {
identity: IdentityMetadata {
id: Uuid::new_v4(),
name: "rpz-nic".parse().unwrap(),
description: "test nic".to_string(),
time_created: Utc::now(),
time_modified: Utc::now(),
},
vpc_id: Uuid::new_v4(),
subnet_id: Uuid::new_v4(),
mac: external::MacAddr(
macaddr::MacAddr6::from([0x02, 0x08, 0x20, 0xBE, 0xA0, 0xF2])
),
ip: std::net::IpAddr::V4(std::net::Ipv4Addr::new(10, 0, 0, 213)),
};

// TODO: Populate this with an appropriate NIC.
// See also: instance_set_runtime in nexus.rs for a similar construction.
Ok(InstanceHardware {
runtime: instance.runtime().clone().into(),
nics: vec![],
nics: vec![rpz_nic],
})
}

Expand Down
2 changes: 2 additions & 0 deletions sled-agent/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ futures = "0.3.18"
ipnetwork = "0.18"
nexus-client = { path = "../nexus-client" }
omicron-common = { path = "../common" }
opte-core = { path = "../../opte/opte-core" }
opteadm = { path = "../../opte/opteadm" }
p256 = "0.9.0"
percent-encoding = "2.1.0"
progenitor = { git = "https://github.com/oxidecomputer/progenitor" }
Expand Down
5 changes: 5 additions & 0 deletions sled-agent/src/illumos/dladm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ pub enum Error {

#[error("Failed to parse output: {0}")]
Parse(#[from] std::string::FromUtf8Error),

// TODO: This isn't the right place to put this, but I just want
// to get integration going.
#[error("OPTE error: {0}")]
OpteErr(#[from] opteadm::Error),
}

/// The name of a physical datalink.
Expand Down
1 change: 1 addition & 0 deletions sled-agent/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,7 @@ impl Instance {
&inner.nic_id_allocator,
&physical_dl,
Some(nic.mac),
nic.ip,
inner.vlan,
)
.map_err(|e| e.into())
Expand Down
22 changes: 22 additions & 0 deletions sled-agent/src/vnic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::illumos::dladm::{
PhysicalLink, VNIC_PREFIX_CONTROL, VNIC_PREFIX_GUEST,
};
use omicron_common::api::external::MacAddr;
use std::net::IpAddr;
use std::sync::{
atomic::{AtomicU64, Ordering},
Arc,
Expand Down Expand Up @@ -74,10 +75,29 @@ impl Vnic {
allocator: &IdAllocator,
physical_dl: &PhysicalLink,
mac: Option<MacAddr>,
ip: IpAddr,
vlan: Option<VlanID>,
) -> Result<Self, Error> {
let name = guest_vnic_name(allocator.next());
Dladm::create_vnic(physical_dl, &name, mac, vlan)?;
let ip4 = match ip {
IpAddr::V4(v) => v,

_ => {
todo!("OPTE supports IPv4 guests only at the moment");
}
};
let ip_cfg = opte_core::ioctl::IpConfig {
// NOTE: OPTE has it's own Ipv4Addr, thus the into().
private_ip: ip4.into(),
snat: None,
};
let req = opte_core::ioctl::AddPortReq {
link_name: name.clone(),
ip_cfg,
};
let hdl = opteadm::OpteAdm::open()?;
hdl.add_port(&req)?;
Ok(Vnic { name, deleted: false })
}

Expand All @@ -99,6 +119,8 @@ impl Vnic {
Ok(())
} else {
self.deleted = true;
let hdl = opteadm::OpteAdm::open()?;
hdl.delete_port(&self.name)?;
Dladm::delete_vnic(&self.name)
}
}
Expand Down