-
Notifications
You must be signed in to change notification settings - Fork 62
[sled-agent][nexus][RSS] Implement RFD 278: RSS to Nexus Handoff #1954
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b68b90a
bf9fe66
c12f2a8
37a4457
809ac64
4ffa1bd
cfa9573
82dd525
b10db8f
ac5e9f6
b9ddc9e
cf6a07b
f3c6a34
0782327
cfeb88f
8d899c5
d223fb9
c53a0bf
362f7e1
e916dba
4ec1e28
a659390
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -100,16 +100,7 @@ pub fn nexus_addr() -> SocketAddr { | |
| .join("../smf/sled-agent/config-rss.toml"); | ||
| if rss_config_path.exists() { | ||
| if let Ok(config) = SetupServiceConfig::from_file(rss_config_path) { | ||
| for request in config.requests { | ||
| for zone in request.service_zones { | ||
| for service in zone.services { | ||
| if let ServiceType::Nexus { external_ip, .. } = service | ||
| { | ||
| return (external_ip, 80).into(); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return (config.nexus_external_address, 80).into(); | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We no longer list the "ServiceZoneRequest" for nexus in |
||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,11 +4,14 @@ | |
|
|
||
| use super::{DatasetKind, Generation, Region, SqlU16}; | ||
| use crate::collection::DatastoreCollectionConfig; | ||
| use crate::ipv6; | ||
| use crate::schema::{dataset, region}; | ||
| use chrono::{DateTime, Utc}; | ||
| use db_macros::Asset; | ||
| use internal_dns_client::names::{BackendName, ServiceName, AAAA, SRV}; | ||
| use nexus_types::identity::Asset; | ||
| use serde::{Deserialize, Serialize}; | ||
| use std::net::SocketAddr; | ||
| use std::net::{Ipv6Addr, SocketAddrV6}; | ||
| use uuid::Uuid; | ||
|
|
||
| /// Database representation of a Dataset. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool. The changes here make sense. This is unrelated to this PR but I find it a little unintuitive that we call this a
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a fair point, it's basically tightly coupling the concept of the "dataset" with "the service which manages the dataset". This has been implemented because it fits our current "dataset-managing services", including:
Though it's a fair point, it definitely won't apply to all "datasets", and it makes it awkward to describe datasets which aren't managed by an explicit service (such as a dump device, dataset for logs, etc). Filed #2000 |
||
|
|
@@ -35,18 +38,18 @@ pub struct Dataset { | |
|
|
||
| pub pool_id: Uuid, | ||
|
|
||
| ip: ipnetwork::IpNetwork, | ||
| ip: ipv6::Ipv6Addr, | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a single IP address on the underlay, not a whole network, so this feels a little more accurate. |
||
| port: SqlU16, | ||
|
|
||
| kind: DatasetKind, | ||
| pub kind: DatasetKind, | ||
| pub size_used: Option<i64>, | ||
| } | ||
|
|
||
| impl Dataset { | ||
| pub fn new( | ||
| id: Uuid, | ||
| pool_id: Uuid, | ||
| addr: SocketAddr, | ||
| addr: SocketAddrV6, | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here and elsewhere in the PR, we use This should be accurate for the underlay, where we expect everything to be IPv6, and prevents some impossible-to-hit variant matching errors. |
||
| kind: DatasetKind, | ||
| ) -> Self { | ||
| let size_used = match kind { | ||
|
|
@@ -65,12 +68,26 @@ impl Dataset { | |
| } | ||
| } | ||
|
|
||
| pub fn address(&self) -> SocketAddr { | ||
| pub fn address(&self) -> SocketAddrV6 { | ||
| self.address_with_port(self.port.into()) | ||
| } | ||
|
|
||
| pub fn address_with_port(&self, port: u16) -> SocketAddr { | ||
| SocketAddr::new(self.ip.ip(), port) | ||
| pub fn address_with_port(&self, port: u16) -> SocketAddrV6 { | ||
| SocketAddrV6::new(Ipv6Addr::from(self.ip), port, 0, 0) | ||
| } | ||
|
|
||
| pub fn aaaa(&self) -> AAAA { | ||
| AAAA::Zone(self.id()) | ||
| } | ||
|
|
||
| pub fn srv(&self) -> SRV { | ||
| match self.kind { | ||
| DatasetKind::Crucible => { | ||
| SRV::Backend(BackendName::Crucible, self.id()) | ||
| } | ||
| DatasetKind::Clickhouse => SRV::Service(ServiceName::Clickhouse), | ||
| DatasetKind::Cockroach => SRV::Service(ServiceName::Cockroach), | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,7 +8,7 @@ use crate::authz; | |
| use crate::context::OpContext; | ||
| use crate::db; | ||
| use crate::db::lookup::LookupPath; | ||
| use crate::internal_api::params::ServicePutRequest; | ||
| use crate::internal_api::params::RackInitializationRequest; | ||
| use omicron_common::api::external::DataPageParams; | ||
| use omicron_common::api::external::Error; | ||
| use omicron_common::api::external::ListResultVec; | ||
|
|
@@ -57,12 +57,13 @@ impl super::Nexus { | |
| &self, | ||
| opctx: &OpContext, | ||
| rack_id: Uuid, | ||
| services: Vec<ServicePutRequest>, | ||
| request: RackInitializationRequest, | ||
| ) -> Result<(), Error> { | ||
| opctx.authorize(authz::Action::Modify, &authz::FLEET).await?; | ||
|
|
||
| // Convert from parameter -> DB type. | ||
| let services: Vec<_> = services | ||
| let services: Vec<_> = request | ||
| .services | ||
| .into_iter() | ||
| .map(|svc| { | ||
| db::model::Service::new( | ||
|
|
@@ -74,10 +75,55 @@ impl super::Nexus { | |
| }) | ||
| .collect(); | ||
|
|
||
| // TODO(https://github.com/oxidecomputer/omicron/issues/1958): If nexus, add a pool? | ||
|
|
||
| let datasets: Vec<_> = request | ||
| .datasets | ||
| .into_iter() | ||
| .map(|dataset| { | ||
| db::model::Dataset::new( | ||
| dataset.dataset_id, | ||
| dataset.zpool_id, | ||
| dataset.request.address, | ||
| dataset.request.kind.into(), | ||
| ) | ||
| }) | ||
| .collect(); | ||
|
|
||
| self.db_datastore | ||
| .rack_set_initialized(opctx, rack_id, services) | ||
| .rack_set_initialized(opctx, rack_id, services, datasets) | ||
| .await?; | ||
|
|
||
| Ok(()) | ||
| } | ||
|
|
||
| /// Awaits the initialization of the rack. | ||
| /// | ||
| /// This will occur by either: | ||
| /// 1. RSS invoking the internal API, handing off responsibility, or | ||
| /// 2. Re-reading a value from the DB, if the rack has already been | ||
| /// initialized. | ||
| /// | ||
| /// See RFD 278 for additional context. | ||
| pub async fn await_rack_initialization(&self, opctx: &OpContext) { | ||
| loop { | ||
| let result = self.rack_lookup(&opctx, &self.rack_id).await; | ||
| match result { | ||
| Ok(rack) => { | ||
| if rack.initialized { | ||
| info!(self.log, "Rack initialized"); | ||
| return; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: might be worth logging something here at "info" level
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added in 4ec1e28 |
||
| } | ||
| info!( | ||
| self.log, | ||
| "Still waiting for rack initialization: {:?}", rack | ||
| ); | ||
| } | ||
| Err(e) => { | ||
| warn!(self.log, "Cannot look up rack: {}", e); | ||
| } | ||
| } | ||
| tokio::time::sleep(std::time::Duration::from_secs(2)).await; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: this seems like a hand-rolled version of
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would need to pull |
||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The format of
config-rss.tomlchanged, so this needed to change too.This only wants to update the gateway address; this modification makes it correct once more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Too bad there's not a CLI tool available here to structurally modify the toml instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that
config-rss.tomlhas been shrinking, it may actually make sense to just have totally a distinct copy for the lab?FYI to @andrewjstone , I do think when we get to the point where wicket actually talks to RSS to "let the operator dynamically set a profile (including Nexus IP info, the subnet, etc)", it'll be a great time to revisit "how we pass this info into RSS".
I think the gateway stuff won't be necessary at that point, since it's only needed for the OPTE hack?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Totally!