From 1e87f9e7f1cfd45c4fff7635643721ab4ef0c93e Mon Sep 17 00:00:00 2001 From: "oxide-renovate[bot]" <146848827+oxide-renovate[bot]@users.noreply.github.com> Date: Fri, 3 Nov 2023 19:34:07 -0700 Subject: [PATCH 01/13] chore(deps): update rust crate httptest to 0.15.5 (#4424) --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cf46fbb148..5b72c85906 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3150,9 +3150,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "httptest" -version = "0.15.4" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f25cfb6def593d43fae1ead24861f217e93bc70768a45cc149a69b5f049df4" +checksum = "c8b44a11846bda8c9fe9194f9924db7132c34635c7ce020f180f6c5d46d2308f" dependencies = [ "bstr 0.2.17", "bytes", diff --git a/Cargo.toml b/Cargo.toml index d0fac037e8..d521d5cae1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -206,7 +206,7 @@ hex-literal = "0.4.1" highway = "1.1.0" hkdf = "0.12.3" http = "0.2.9" -httptest = "0.15.4" +httptest = "0.15.5" hubtools = { git = "https://github.com/oxidecomputer/hubtools.git", branch = "main" } humantime = "2.1.0" hyper = "0.14" From a9ba11fcd74dba41a15ae8040e3250a46d647acc Mon Sep 17 00:00:00 2001 From: "oxide-renovate[bot]" <146848827+oxide-renovate[bot]@users.noreply.github.com> Date: Fri, 3 Nov 2023 20:08:56 -0700 Subject: [PATCH 02/13] chore(deps): update rust crate parse-display to 0.8.2 (#4382) --- Cargo.lock | 41 ++++++++++++++++++++++++++++++++------- Cargo.toml | 2 +- workspace-hack/Cargo.toml | 5 +++-- 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5b72c85906..5664ebe44f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4345,7 +4345,7 @@ dependencies = [ "omicron-passwords 0.1.0", "omicron-rpaths", "omicron-workspace-hack", - "parse-display", + "parse-display 0.8.2", "pq-sys", "rand 0.8.5", "ref-cast", @@ -4519,7 +4519,7 @@ dependencies = [ "oximeter-client", "oximeter-collector", "oximeter-producer 0.1.0", - "parse-display", + "parse-display 0.8.2", "serde", "serde_json", "serde_urlencoded", @@ -4558,7 +4558,7 @@ dependencies = [ "openssl", "openssl-probe", "openssl-sys", - "parse-display", + "parse-display 0.8.2", "schemars", "serde", "serde_json", @@ -4890,7 +4890,7 @@ dependencies = [ "libc", "macaddr", "omicron-workspace-hack", - "parse-display", + "parse-display 0.8.2", "progenitor", "proptest", "rand 0.8.5", @@ -4934,7 +4934,7 @@ dependencies = [ "ipnetwork", "lazy_static", "macaddr", - "parse-display", + "parse-display 0.7.0", "progenitor", "rand 0.8.5", "reqwest", @@ -5120,7 +5120,7 @@ dependencies = [ "oximeter-db", "oximeter-instruments", "oximeter-producer 0.1.0", - "parse-display", + "parse-display 0.8.2", "paste", "pem 1.1.1", "petgraph", @@ -5466,6 +5466,7 @@ dependencies = [ "rand_chacha 0.3.1", "regex", "regex-automata 0.4.3", + "regex-syntax 0.6.29", "regex-syntax 0.8.2", "reqwest", "ring 0.16.20", @@ -6013,7 +6014,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac6b32f6c8212838b74c0f5ba412194e88897923020810d9bec72d3594c2588d" dependencies = [ "once_cell", - "parse-display-derive", + "parse-display-derive 0.7.0", + "regex", +] + +[[package]] +name = "parse-display" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6509d08722b53e8dafe97f2027b22ccbe3a5db83cb352931e9716b0aa44bc5c" +dependencies = [ + "once_cell", + "parse-display-derive 0.8.2", "regex", ] @@ -6032,6 +6044,21 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "parse-display-derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68517892c8daf78da08c0db777fcc17e07f2f63ef70041718f8a7630ad84f341" +dependencies = [ + "once_cell", + "proc-macro2", + "quote", + "regex", + "regex-syntax 0.7.5", + "structmeta 0.2.0", + "syn 2.0.32", +] + [[package]] name = "partial-io" version = "0.5.4" diff --git a/Cargo.toml b/Cargo.toml index d521d5cae1..1727aea463 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -274,7 +274,7 @@ oximeter-instruments = { path = "oximeter/instruments" } oximeter-macro-impl = { path = "oximeter/oximeter-macro-impl" } oximeter-producer = { path = "oximeter/producer" } p256 = "0.13" -parse-display = "0.7.0" +parse-display = "0.8.2" partial-io = { version = "0.5.4", features = ["proptest1", "tokio1"] } paste = "1.0.14" percent-encoding = "2.3.0" diff --git a/workspace-hack/Cargo.toml b/workspace-hack/Cargo.toml index 06ee709440..a58015685b 100644 --- a/workspace-hack/Cargo.toml +++ b/workspace-hack/Cargo.toml @@ -73,7 +73,7 @@ rand = { version = "0.8.5", features = ["min_const_gen", "small_rng"] } rand_chacha = { version = "0.3.1" } regex = { version = "1.10.2" } regex-automata = { version = "0.4.3", default-features = false, features = ["dfa-onepass", "hybrid", "meta", "nfa-backtrack", "perf-inline", "perf-literal", "unicode"] } -regex-syntax = { version = "0.8.2" } +regex-syntax-c38e5c1d305a1b54 = { package = "regex-syntax", version = "0.8.2" } reqwest = { version = "0.11.20", features = ["blocking", "json", "rustls-tls", "stream"] } ring = { version = "0.16.20", features = ["std"] } schemars = { version = "0.8.13", features = ["bytes", "chrono", "uuid1"] } @@ -165,7 +165,8 @@ rand = { version = "0.8.5", features = ["min_const_gen", "small_rng"] } rand_chacha = { version = "0.3.1" } regex = { version = "1.10.2" } regex-automata = { version = "0.4.3", default-features = false, features = ["dfa-onepass", "hybrid", "meta", "nfa-backtrack", "perf-inline", "perf-literal", "unicode"] } -regex-syntax = { version = "0.8.2" } +regex-syntax-3b31131e45eafb45 = { package = "regex-syntax", version = "0.6.29" } +regex-syntax-c38e5c1d305a1b54 = { package = "regex-syntax", version = "0.8.2" } reqwest = { version = "0.11.20", features = ["blocking", "json", "rustls-tls", "stream"] } ring = { version = "0.16.20", features = ["std"] } schemars = { version = "0.8.13", features = ["bytes", "chrono", "uuid1"] } From bfde52469459d2deab05783331e2044a5dccdf55 Mon Sep 17 00:00:00 2001 From: "oxide-renovate[bot]" <146848827+oxide-renovate[bot]@users.noreply.github.com> Date: Sat, 4 Nov 2023 04:22:33 +0000 Subject: [PATCH 03/13] chore(deps): update rust crate indexmap to 2.1.0 (#4248) --- Cargo.lock | 38 +++++++++++++++++++------------------- Cargo.toml | 2 +- workspace-hack/Cargo.toml | 8 ++++---- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5664ebe44f..5557774074 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1709,7 +1709,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edd72493923899c6f10c641bdbdeddc7183d6396641d99c1a0d1597f37f92e28" dependencies = [ "cfg-if 1.0.0", - "hashbrown 0.14.0", + "hashbrown 0.14.2", "lock_api", "once_cell", "parking_lot_core 0.9.8", @@ -2146,7 +2146,7 @@ dependencies = [ "hostname", "http", "hyper", - "indexmap 2.0.0", + "indexmap 2.1.0", "multer", "openapiv3", "paste", @@ -2965,9 +2965,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" dependencies = [ "ahash", "allocator-api2", @@ -2979,7 +2979,7 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "312f66718a2d7789ffef4f4b7b213138ed9f1eb3aa1d0d82fc99f88fb3ffd26f" dependencies = [ - "hashbrown 0.14.0", + "hashbrown 0.14.2", ] [[package]] @@ -3429,12 +3429,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", - "hashbrown 0.14.0", + "hashbrown 0.14.2", "serde", ] @@ -5437,11 +5437,11 @@ dependencies = [ "generic-array", "getrandom 0.2.10", "hashbrown 0.13.2", - "hashbrown 0.14.0", + "hashbrown 0.14.2", "hex", "hyper", "hyper-rustls", - "indexmap 2.0.0", + "indexmap 2.1.0", "inout", "ipnetwork", "itertools 0.10.5", @@ -5552,7 +5552,7 @@ version = "0.4.0" source = "git+https://github.com/oxidecomputer/openapi-lint?branch=main#bb69a3a4a184d966bac2a0df2be5c9038d9867d0" dependencies = [ "heck 0.4.1", - "indexmap 2.0.0", + "indexmap 2.1.0", "lazy_static", "openapiv3", "regex", @@ -5564,7 +5564,7 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75e56d5c441965b6425165b7e3223cc933ca469834f4a8b4786817a1f9dc4f13" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.1.0", "serde", "serde_json", ] @@ -6235,7 +6235,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap 2.0.0", + "indexmap 2.1.0", "serde", "serde_derive", ] @@ -6627,7 +6627,7 @@ dependencies = [ "getopts", "heck 0.4.1", "http", - "indexmap 2.0.0", + "indexmap 2.1.0", "openapiv3", "proc-macro2", "quote", @@ -8005,7 +8005,7 @@ version = "0.9.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.1.0", "itoa", "ryu", "serde", @@ -9244,7 +9244,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.1.0", "serde", "serde_spanned", "toml_datetime", @@ -9257,7 +9257,7 @@ version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.1.0", "serde", "serde_spanned", "toml_datetime", @@ -9730,7 +9730,7 @@ dependencies = [ "derive-where", "either", "futures", - "indexmap 2.0.0", + "indexmap 2.1.0", "indicatif", "linear-map", "omicron-test-utils", @@ -10106,7 +10106,7 @@ dependencies = [ "futures", "hex", "humantime", - "indexmap 2.0.0", + "indexmap 2.1.0", "indicatif", "itertools 0.11.0", "omicron-common 0.1.0", diff --git a/Cargo.toml b/Cargo.toml index 1727aea463..74a4bb6b58 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -213,7 +213,7 @@ hyper = "0.14" hyper-rustls = "0.24.2" hyper-staticfile = "0.9.5" illumos-utils = { path = "illumos-utils" } -indexmap = "2.0.0" +indexmap = "2.1.0" indicatif = { version = "0.17.7", features = ["rayon"] } installinator = { path = "installinator" } installinator-artifactd = { path = "installinator-artifactd" } diff --git a/workspace-hack/Cargo.toml b/workspace-hack/Cargo.toml index a58015685b..49077eac77 100644 --- a/workspace-hack/Cargo.toml +++ b/workspace-hack/Cargo.toml @@ -46,11 +46,11 @@ futures-util = { version = "0.3.29", features = ["channel", "io", "sink"] } gateway-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "2739c18e80697aa6bc235c935176d14b4d757ee9", features = ["std"] } generic-array = { version = "0.14.7", default-features = false, features = ["more_lengths", "zeroize"] } getrandom = { version = "0.2.10", default-features = false, features = ["js", "rdrand", "std"] } -hashbrown-582f2526e08bb6a0 = { package = "hashbrown", version = "0.14.0", features = ["raw"] } +hashbrown-582f2526e08bb6a0 = { package = "hashbrown", version = "0.14.2", features = ["raw"] } hashbrown-594e8ee84c453af0 = { package = "hashbrown", version = "0.13.2" } hex = { version = "0.4.3", features = ["serde"] } hyper = { version = "0.14.27", features = ["full"] } -indexmap = { version = "2.0.0", features = ["serde"] } +indexmap = { version = "2.1.0", features = ["serde"] } inout = { version = "0.1.3", default-features = false, features = ["std"] } ipnetwork = { version = "0.20.0", features = ["schemars"] } itertools = { version = "0.10.5" } @@ -138,11 +138,11 @@ futures-util = { version = "0.3.29", features = ["channel", "io", "sink"] } gateway-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "2739c18e80697aa6bc235c935176d14b4d757ee9", features = ["std"] } generic-array = { version = "0.14.7", default-features = false, features = ["more_lengths", "zeroize"] } getrandom = { version = "0.2.10", default-features = false, features = ["js", "rdrand", "std"] } -hashbrown-582f2526e08bb6a0 = { package = "hashbrown", version = "0.14.0", features = ["raw"] } +hashbrown-582f2526e08bb6a0 = { package = "hashbrown", version = "0.14.2", features = ["raw"] } hashbrown-594e8ee84c453af0 = { package = "hashbrown", version = "0.13.2" } hex = { version = "0.4.3", features = ["serde"] } hyper = { version = "0.14.27", features = ["full"] } -indexmap = { version = "2.0.0", features = ["serde"] } +indexmap = { version = "2.1.0", features = ["serde"] } inout = { version = "0.1.3", default-features = false, features = ["std"] } ipnetwork = { version = "0.20.0", features = ["schemars"] } itertools = { version = "0.10.5" } From 649a9fbab70175cc15ad4f65e6c66c2e8812dd89 Mon Sep 17 00:00:00 2001 From: "oxide-renovate[bot]" <146848827+oxide-renovate[bot]@users.noreply.github.com> Date: Sat, 4 Nov 2023 04:27:45 +0000 Subject: [PATCH 04/13] chore(deps): update rust crate toml_edit to 0.20.7 (#4431) --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5557774074..a7aa3aa153 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10131,7 +10131,7 @@ dependencies = [ "tokio", "tokio-util", "toml 0.8.6", - "toml_edit 0.19.15", + "toml_edit 0.20.7", "tui-tree-widget", "unicode-width", "update-engine", diff --git a/Cargo.toml b/Cargo.toml index 74a4bb6b58..8aaae347d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -363,7 +363,7 @@ tokio-stream = "0.1.14" tokio-tungstenite = "0.18" tokio-util = "0.7.10" toml = "0.8.6" -toml_edit = "0.19.15" +toml_edit = "0.20.7" topological-sort = "0.2.2" tough = { version = "0.12", features = [ "http" ] } trust-dns-client = "0.22" From ea4da471c4abdb71edc7afca255e0c441cab5529 Mon Sep 17 00:00:00 2001 From: Ryan Goodfellow Date: Sat, 4 Nov 2023 09:38:48 -0700 Subject: [PATCH 05/13] Support for propolis-based softnpu device, fix multi-switch uplink updates. (#4390) --- common/src/lib.rs | 2 + illumos-utils/src/running_zone.rs | 8 +- illumos-utils/src/svc.rs | 32 ++++++- nexus/src/app/sagas/mod.rs | 2 +- .../app/sagas/switch_port_settings_apply.rs | 93 ++++++++++++------- .../app/sagas/switch_port_settings_clear.rs | 12 ++- nexus/tests/integration_tests/switch_port.rs | 4 + package-manifest.toml | 20 ++-- sled-agent/Cargo.toml | 1 + sled-agent/src/bootstrap/early_networking.rs | 25 +++-- sled-agent/src/bootstrap/pre_server.rs | 13 ++- sled-agent/src/config.rs | 3 +- sled-agent/src/instance.rs | 2 +- sled-agent/src/params.rs | 1 + sled-agent/src/services.rs | 82 ++++++++++++---- sled-hardware/src/illumos/mod.rs | 51 +++++----- sled-hardware/src/lib.rs | 7 +- smf/sled-agent/non-gimlet/config.toml | 2 +- tools/create_virtual_hardware.sh | 10 +- tools/dendrite_openapi_version | 4 +- tools/dendrite_stub_checksums | 6 +- tools/maghemite_ddm_openapi_version | 2 +- tools/maghemite_mg_openapi_version | 4 +- tools/maghemite_mgd_checksums | 4 +- wicketd/src/preflight_check/uplink.rs | 11 ++- 25 files changed, 273 insertions(+), 128 deletions(-) diff --git a/common/src/lib.rs b/common/src/lib.rs index ced10abb1a..1d2ed0afdb 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -75,3 +75,5 @@ impl slog::KV for FileKv { ) } } + +pub const OMICRON_DPD_TAG: &str = "omicron"; diff --git a/illumos-utils/src/running_zone.rs b/illumos-utils/src/running_zone.rs index 805419cb5d..bdf7ed0cbf 100644 --- a/illumos-utils/src/running_zone.rs +++ b/illumos-utils/src/running_zone.rs @@ -517,12 +517,12 @@ impl RunningZone { // services are up, so future requests to create network addresses // or manipulate services will work. let fmri = "svc:/milestone/single-user:default"; - wait_for_service(Some(&zone.name), fmri).await.map_err(|_| { - BootError::Timeout { + wait_for_service(Some(&zone.name), fmri, zone.log.clone()) + .await + .map_err(|_| BootError::Timeout { service: fmri.to_string(), zone: zone.name.to_string(), - } - })?; + })?; // If the zone is self-assembling, then SMF service(s) inside the zone // will be creating the listen address for the zone's service(s), diff --git a/illumos-utils/src/svc.rs b/illumos-utils/src/svc.rs index b08679b720..a16795771c 100644 --- a/illumos-utils/src/svc.rs +++ b/illumos-utils/src/svc.rs @@ -12,6 +12,7 @@ use omicron_common::backoff; #[cfg_attr(any(test, feature = "testing"), mockall::automock, allow(dead_code))] mod inner { use super::*; + use slog::{warn, Logger}; // TODO(https://www.illumos.org/issues/13837): This is a hack; // remove me when when fixed. Ideally, the ".synchronous()" argument @@ -27,10 +28,19 @@ mod inner { pub async fn wait_for_service<'a, 'b>( zone: Option<&'a str>, fmri: &'b str, + log: Logger, ) -> Result<(), Error> { let name = smf::PropertyName::new("restarter", "state").unwrap(); - let log_notification_failure = |_error, _delay| {}; + let log_notification_failure = |error, delay| { + warn!( + log, + "wait for service {:?} failed: {}. retry in {:?}", + zone, + error, + delay + ); + }; backoff::retry_notify( backoff::retry_policy_local(), || async { @@ -47,6 +57,26 @@ mod inner { == &smf::PropertyValue::Astring("online".to_string()) { return Ok(()); + } else { + // This is helpful in virtual environments where + // services take a few tries to come up. To enable, + // compile with RUSTFLAGS="--cfg svcadm_autoclear" + #[cfg(svcadm_autoclear)] + if let Some(zname) = zone { + if let Err(out) = + tokio::process::Command::new(crate::PFEXEC) + .env_clear() + .arg("svcadm") + .arg("-z") + .arg(zname) + .arg("clear") + .arg("*") + .output() + .await + { + warn!(log, "clearing service maintenance failed: {out}"); + }; + } } } return Err(backoff::BackoffError::transient( diff --git a/nexus/src/app/sagas/mod.rs b/nexus/src/app/sagas/mod.rs index 83e0e9b8b4..5b1843be3d 100644 --- a/nexus/src/app/sagas/mod.rs +++ b/nexus/src/app/sagas/mod.rs @@ -313,7 +313,7 @@ macro_rules! declare_saga_actions { }; } -pub(crate) const NEXUS_DPD_TAG: &str = "nexus"; +use omicron_common::OMICRON_DPD_TAG as NEXUS_DPD_TAG; pub(crate) use __action_name; pub(crate) use __emit_action; diff --git a/nexus/src/app/sagas/switch_port_settings_apply.rs b/nexus/src/app/sagas/switch_port_settings_apply.rs index fb06dc5fc0..830792826e 100644 --- a/nexus/src/app/sagas/switch_port_settings_apply.rs +++ b/nexus/src/app/sagas/switch_port_settings_apply.rs @@ -3,6 +3,7 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. use super::{NexusActionContext, NEXUS_DPD_TAG}; +use crate::app::map_switch_zone_addrs; use crate::app::sagas::retry_until_known_result; use crate::app::sagas::{ declare_saga_actions, ActionRegistry, NexusSaga, SagaInitError, @@ -15,15 +16,17 @@ use dpd_client::types::{ RouteSettingsV4, RouteSettingsV6, }; use dpd_client::{Ipv4Cidr, Ipv6Cidr}; +use internal_dns::ServiceName; use ipnetwork::IpNetwork; use mg_admin_client::types::Prefix4; -use mg_admin_client::types::{ApplyRequest, BgpPeerConfig, BgpRoute}; +use mg_admin_client::types::{ApplyRequest, BgpPeerConfig}; use nexus_db_model::{SwitchLinkFec, SwitchLinkSpeed, NETWORK_KEY}; use nexus_db_queries::context::OpContext; use nexus_db_queries::db::datastore::UpdatePrecondition; use nexus_db_queries::{authn, db}; use nexus_types::external_api::params; -use omicron_common::api::external::{self, DataPageParams, NameOrId}; +use omicron_common::address::SLED_AGENT_PORT; +use omicron_common::api::external::{self, NameOrId}; use omicron_common::api::internal::shared::{ ParseSwitchLocationError, SwitchLocation, }; @@ -35,8 +38,8 @@ use sled_agent_client::types::{ BgpPeerConfig as OmicronBgpPeerConfig, HostPortConfig, }; use std::collections::HashMap; -use std::net::IpAddr; use std::net::SocketAddrV6; +use std::net::{IpAddr, Ipv6Addr}; use std::str::FromStr; use std::sync::Arc; use steno::ActionError; @@ -177,7 +180,6 @@ pub(crate) fn api_to_dpd_port_settings( settings: &SwitchPortSettingsCombinedResult, ) -> Result { let mut dpd_port_settings = PortSettings { - tag: NEXUS_DPD_TAG.into(), links: HashMap::new(), v4_routes: HashMap::new(), v6_routes: HashMap::new(), @@ -192,6 +194,7 @@ pub(crate) fn api_to_dpd_port_settings( LinkSettings { params: LinkCreate { autoneg: false, + lane: Some(LinkId(0)), kr: false, fec: match l.fec { SwitchLinkFec::Firecode => PortFec::Firecode, @@ -283,7 +286,13 @@ async fn spa_ensure_switch_port_settings( })?; retry_until_known_result(log, || async { - dpd_client.port_settings_apply(&port_id, &dpd_port_settings).await + dpd_client + .port_settings_apply( + &port_id, + Some(NEXUS_DPD_TAG), + &dpd_port_settings, + ) + .await }) .await .map_err(|e| match e { @@ -331,7 +340,9 @@ async fn spa_undo_ensure_switch_port_settings( Some(id) => id, None => { retry_until_known_result(log, || async { - dpd_client.port_settings_clear(&port_id).await + dpd_client + .port_settings_clear(&port_id, Some(NEXUS_DPD_TAG)) + .await }) .await .map_err(|e| external::Error::internal_error(&e.to_string()))?; @@ -355,7 +366,13 @@ async fn spa_undo_ensure_switch_port_settings( })?; retry_until_known_result(log, || async { - dpd_client.port_settings_apply(&port_id, &dpd_port_settings).await + dpd_client + .port_settings_apply( + &port_id, + Some(NEXUS_DPD_TAG), + &dpd_port_settings, + ) + .await }) .await .map_err(|e| external::Error::internal_error(&e.to_string()))?; @@ -418,22 +435,6 @@ pub(crate) async fn ensure_switch_port_bgp_settings( )) })?; - // TODO picking the first configured address by default, but this needs - // to be something that can be specified in the API. - let nexthop = match settings.addresses.get(0) { - Some(switch_port_addr) => Ok(switch_port_addr.address.ip()), - None => Err(ActionError::action_failed( - "at least one address required for bgp peering".to_string(), - )), - }?; - - let nexthop = match nexthop { - IpAddr::V4(nexthop) => Ok(nexthop), - IpAddr::V6(_) => Err(ActionError::action_failed( - "IPv6 nexthop not yet supported".to_string(), - )), - }?; - let mut prefixes = Vec::new(); for a in &announcements { let value = match a.network.ip() { @@ -455,7 +456,7 @@ pub(crate) async fn ensure_switch_port_bgp_settings( connect_retry: peer.connect_retry.0.into(), keepalive: peer.keepalive.0.into(), resolution: BGP_SESSION_RESOLUTION, - routes: vec![BgpRoute { nexthop, prefixes }], + originate: prefixes, }; bgp_peer_configs.push(bpc); @@ -809,7 +810,7 @@ pub(crate) async fn select_mg_client( } pub(crate) async fn get_scrimlet_address( - _location: SwitchLocation, + location: SwitchLocation, nexus: &Arc, ) -> Result { /* TODO this depends on DNS entries only coming from RSS, it's broken @@ -826,21 +827,41 @@ pub(crate) async fn get_scrimlet_address( )) }) */ - let opctx = &nexus.opctx_for_internal_api(); - Ok(nexus - .sled_list(opctx, &DataPageParams::max_page()) + let result = nexus + .resolver() + .await + .lookup_all_ipv6(ServiceName::Dendrite) .await .map_err(|e| { ActionError::action_failed(format!( - "get_scrimlet_address: failed to list sleds: {e}" + "scrimlet dns lookup failed {e}", )) - })? - .into_iter() - .find(|x| x.is_scrimlet()) - .ok_or(ActionError::action_failed( - "get_scrimlet_address: no scrimlets found".to_string(), - ))? - .address()) + }); + + let mappings = match result { + Ok(addrs) => map_switch_zone_addrs(&nexus.log, addrs).await, + Err(e) => { + warn!(nexus.log, "Failed to lookup Dendrite address: {e}"); + return Err(ActionError::action_failed(format!( + "switch mapping failed {e}", + ))); + } + }; + + let addr = match mappings.get(&location) { + Some(addr) => addr, + None => { + return Err(ActionError::action_failed(format!( + "address for switch at location: {location} not found", + ))); + } + }; + + let mut segments = addr.segments(); + segments[7] = 1; + let addr = Ipv6Addr::from(segments); + + Ok(SocketAddrV6::new(addr, SLED_AGENT_PORT, 0, 0)) } #[derive(Clone, Debug)] diff --git a/nexus/src/app/sagas/switch_port_settings_clear.rs b/nexus/src/app/sagas/switch_port_settings_clear.rs index 14544b0f55..1ab2f6be0c 100644 --- a/nexus/src/app/sagas/switch_port_settings_clear.rs +++ b/nexus/src/app/sagas/switch_port_settings_clear.rs @@ -3,7 +3,7 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. use super::switch_port_settings_apply::select_dendrite_client; -use super::NexusActionContext; +use super::{NexusActionContext, NEXUS_DPD_TAG}; use crate::app::sagas::retry_until_known_result; use crate::app::sagas::switch_port_settings_apply::{ api_to_dpd_port_settings, apply_bootstore_update, bootstore_update, @@ -154,7 +154,7 @@ async fn spa_clear_switch_port_settings( let dpd_client = select_dendrite_client(&sagactx).await?; retry_until_known_result(log, || async { - dpd_client.port_settings_clear(&port_id).await + dpd_client.port_settings_clear(&port_id, Some(NEXUS_DPD_TAG)).await }) .await .map_err(|e| ActionError::action_failed(e.to_string()))?; @@ -197,7 +197,13 @@ async fn spa_undo_clear_switch_port_settings( .map_err(ActionError::action_failed)?; retry_until_known_result(log, || async { - dpd_client.port_settings_apply(&port_id, &dpd_port_settings).await + dpd_client + .port_settings_apply( + &port_id, + Some(NEXUS_DPD_TAG), + &dpd_port_settings, + ) + .await }) .await .map_err(|e| external::Error::internal_error(&e.to_string()))?; diff --git a/nexus/tests/integration_tests/switch_port.rs b/nexus/tests/integration_tests/switch_port.rs index fada45694d..ccd0b50fbe 100644 --- a/nexus/tests/integration_tests/switch_port.rs +++ b/nexus/tests/integration_tests/switch_port.rs @@ -24,6 +24,10 @@ use omicron_common::api::external::{ type ControlPlaneTestContext = nexus_test_utils::ControlPlaneTestContext; +// TODO: unfortunately this test can no longer be run in the integration test +// suite because it depends on communicating with MGS which is not part +// of the infrastructure available in the integration test context. +#[ignore] #[nexus_test] async fn test_port_settings_basic_crud(ctx: &ControlPlaneTestContext) { let client = &ctx.external_client; diff --git a/package-manifest.toml b/package-manifest.toml index b8ffb2756a..c6949e4437 100644 --- a/package-manifest.toml +++ b/package-manifest.toml @@ -422,7 +422,7 @@ source.repo = "maghemite" # `tools/maghemite_openapi_version`. Failing to do so will cause a failure when # building `ddm-admin-client` (which will instruct you to update # `tools/maghemite_openapi_version`). -source.commit = "d7169a61fd8833b3a1e6f46d897ca3295b2a28b6" +source.commit = "82aa17646265449ee0ede9410208e510fa4a5877" # The SHA256 digest is automatically posted to: # https://buildomat.eng.oxide.computer/public/file/oxidecomputer/maghemite/image//maghemite.sha256.txt source.sha256 = "d871406ed926571efebdab248de08d4f1ca6c31d4f9a691ce47b186474165c57" @@ -438,7 +438,7 @@ source.repo = "maghemite" # `tools/maghemite_openapi_version`. Failing to do so will cause a failure when # building `ddm-admin-client` (which will instruct you to update # `tools/maghemite_openapi_version`). -source.commit = "d7169a61fd8833b3a1e6f46d897ca3295b2a28b6" +source.commit = "82aa17646265449ee0ede9410208e510fa4a5877" # The SHA256 digest is automatically posted to: # https://buildomat.eng.oxide.computer/public/file/oxidecomputer/maghemite/image//mg-ddm.sha256.txt source.sha256 = "85ec05a8726989b5cb0a567de6b0855f6f84b6f3409ac99ccaf372be5821e45d" @@ -453,10 +453,10 @@ source.repo = "maghemite" # `tools/maghemite_openapi_version`. Failing to do so will cause a failure when # building `ddm-admin-client` (which will instruct you to update # `tools/maghemite_openapi_version`). -source.commit = "d7169a61fd8833b3a1e6f46d897ca3295b2a28b6" +source.commit = "82aa17646265449ee0ede9410208e510fa4a5877" # The SHA256 digest is automatically posted to: # https://buildomat.eng.oxide.computer/public/file/oxidecomputer/maghemite/image//mg-ddm.sha256.txt -source.sha256 = "452dfb3491e1b6d4df6be1cb689921f59623aed082e47606a78c0f44d918f66a" +source.sha256 = "1badd6adfece0a1b661f7efb9a2ca65e471f45cf9c8ecbd72b228ca174311e31" output.type = "zone" output.intermediate_only = true @@ -473,8 +473,8 @@ only_for_targets.image = "standard" # 2. Copy dendrite.tar.gz from dendrite/out to omicron/out source.type = "prebuilt" source.repo = "dendrite" -source.commit = "343e3a572cc02efe3f8b68f9affd008623a33966" -source.sha256 = "0808f331741e02d55e199847579dfd01f3658b21c7122cef8c3f9279f43dbab0" +source.commit = "559fad2f379900a05ced410944353c1d19100390" +source.sha256 = "ce14c1f0481b13ce47a25386a3b1e49d9570f4c1c31cad3f13c14f75b130dafa" output.type = "zone" output.intermediate_only = true @@ -498,8 +498,8 @@ only_for_targets.image = "standard" # 2. Copy the output zone image from dendrite/out to omicron/out source.type = "prebuilt" source.repo = "dendrite" -source.commit = "343e3a572cc02efe3f8b68f9affd008623a33966" -source.sha256 = "c359de1be5073a484d86d4c58e8656a36002ce1dc38506f97b730e21615ccae1" +source.commit = "559fad2f379900a05ced410944353c1d19100390" +source.sha256 = "1a1246e2e596f36182eb6a5e402c272d0cd91aab351c5289cc4a29cb822c8888" output.type = "zone" output.intermediate_only = true @@ -516,8 +516,8 @@ only_for_targets.image = "standard" # 2. Copy dendrite.tar.gz from dendrite/out to omicron/out/dendrite-softnpu.tar.gz source.type = "prebuilt" source.repo = "dendrite" -source.commit = "343e3a572cc02efe3f8b68f9affd008623a33966" -source.sha256 = "110bfbfb2cf3d3471f3e3a64d26129c7a02f6c5857f9623ebb99690728c3b2ff" +source.commit = "559fad2f379900a05ced410944353c1d19100390" +source.sha256 = "b9ff0f7f9e6193f4fa0aff77f7ec80f726f431ce1024a88021f207beb9079793" output.type = "zone" output.intermediate_only = true diff --git a/sled-agent/Cargo.toml b/sled-agent/Cargo.toml index ff9644773a..3889be5eff 100644 --- a/sled-agent/Cargo.toml +++ b/sled-agent/Cargo.toml @@ -119,5 +119,6 @@ machine-non-gimlet = [] switch-asic = [] switch-stub = [] switch-softnpu = [] +switch-hypersoftnpu = [] rack-topology-single-sled = [] rack-topology-multi-sled = [] diff --git a/sled-agent/src/bootstrap/early_networking.rs b/sled-agent/src/bootstrap/early_networking.rs index 9adfa47d9b..a8aa978f9d 100644 --- a/sled-agent/src/bootstrap/early_networking.rs +++ b/sled-agent/src/bootstrap/early_networking.rs @@ -27,6 +27,7 @@ use omicron_common::backoff::{ retry_notify, retry_policy_local, BackoffError, ExponentialBackoff, ExponentialBackoffBuilder, }; +use omicron_common::OMICRON_DPD_TAG; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use slog::Logger; @@ -403,7 +404,7 @@ impl<'a> EarlyNetworkSetup<'a> { let dpd = DpdClient::new( &format!("http://[{}]:{}", switch_zone_underlay_ip, DENDRITE_PORT), dpd_client::ClientState { - tag: "early_networking".to_string(), + tag: OMICRON_DPD_TAG.into(), log: self.log.new(o!("component" => "DpdClient")), }, ); @@ -432,13 +433,17 @@ impl<'a> EarlyNetworkSetup<'a> { "Configuring default uplink on switch"; "config" => #?dpd_port_settings ); - dpd.port_settings_apply(&port_id, &dpd_port_settings) - .await - .map_err(|e| { - EarlyNetworkSetupError::Dendrite(format!( - "unable to apply uplink port configuration: {e}" - )) - })?; + dpd.port_settings_apply( + &port_id, + Some(OMICRON_DPD_TAG), + &dpd_port_settings, + ) + .await + .map_err(|e| { + EarlyNetworkSetupError::Dendrite(format!( + "unable to apply uplink port configuration: {e}" + )) + })?; info!(self.log, "advertising boundary services loopback address"); @@ -462,10 +467,9 @@ impl<'a> EarlyNetworkSetup<'a> { "failed to parse `BOUNDARY_SERVICES_ADDR` as `Ipv6Addr`: {e}" )) })?, - tag: "rss".into(), + tag: OMICRON_DPD_TAG.into(), }; let mut dpd_port_settings = PortSettings { - tag: "rss".into(), links: HashMap::new(), v4_routes: HashMap::new(), v6_routes: HashMap::new(), @@ -488,6 +492,7 @@ impl<'a> EarlyNetworkSetup<'a> { kr: false, fec: convert_fec(&port_config.uplink_port_fec), speed: convert_speed(&port_config.uplink_port_speed), + lane: Some(LinkId(0)), }, //addrs: vec![addr], addrs, diff --git a/sled-agent/src/bootstrap/pre_server.rs b/sled-agent/src/bootstrap/pre_server.rs index 0c19c30865..05493f5aa3 100644 --- a/sled-agent/src/bootstrap/pre_server.rs +++ b/sled-agent/src/bootstrap/pre_server.rs @@ -14,6 +14,7 @@ use super::maghemite; use super::secret_retriever::LrtqOrHardcodedSecretRetriever; use super::server::StartError; use crate::config::Config; +use crate::config::SidecarRevision; use crate::services::ServiceManager; use crate::sled_agent::SledAgent; use crate::storage_manager::StorageManager; @@ -339,6 +340,7 @@ async fn cleanup_all_old_global_state(log: &Logger) -> Result<(), StartError> { } fn enable_mg_ddm(config: &Config, log: &Logger) -> Result<(), StartError> { + info!(log, "finding links {:?}", config.data_links); let mg_addr_objs = underlay::find_nics(&config.data_links) .map_err(StartError::FindMaghemiteAddrObjs)?; if mg_addr_objs.is_empty() { @@ -423,7 +425,16 @@ fn sled_mode_from_config(config: &Config) -> Result { } else if cfg!(feature = "switch-stub") { DendriteAsic::TofinoStub } else if cfg!(feature = "switch-softnpu") { - DendriteAsic::SoftNpu + match config.sidecar_revision { + SidecarRevision::SoftZone(_) => DendriteAsic::SoftNpuZone, + SidecarRevision::SoftPropolis(_) => { + DendriteAsic::SoftNpuPropolisDevice + } + _ => return Err(StartError::IncorrectBuildPackaging( + "sled-agent configured to run on softnpu zone but dosen't \ + have a softnpu sidecar revision", + )), + } } else { return Err(StartError::IncorrectBuildPackaging( "sled-agent configured to run on scrimlet but wasn't \ diff --git a/sled-agent/src/config.rs b/sled-agent/src/config.rs index 2473c14566..fad4b2e94b 100644 --- a/sled-agent/src/config.rs +++ b/sled-agent/src/config.rs @@ -28,7 +28,8 @@ pub enum SledMode { #[serde(rename_all = "snake_case")] pub enum SidecarRevision { Physical(String), - Soft(SoftPortConfig), + SoftZone(SoftPortConfig), + SoftPropolis(SoftPortConfig), } #[derive(Debug, Clone, Deserialize)] diff --git a/sled-agent/src/instance.rs b/sled-agent/src/instance.rs index 94614c2363..5c61993293 100644 --- a/sled-agent/src/instance.rs +++ b/sled-agent/src/instance.rs @@ -984,7 +984,7 @@ impl Instance { // but it helps distinguish "online in SMF" from "responding to HTTP // requests". let fmri = fmri_name(); - wait_for_service(Some(&zname), &fmri) + wait_for_service(Some(&zname), &fmri, inner.log.clone()) .await .map_err(|_| Error::Timeout(fmri.to_string()))?; info!(inner.log, "Propolis SMF service is online"); diff --git a/sled-agent/src/params.rs b/sled-agent/src/params.rs index 5fda3c1ae6..cd84c9acd4 100644 --- a/sled-agent/src/params.rs +++ b/sled-agent/src/params.rs @@ -347,6 +347,7 @@ pub enum ServiceType { #[serde(skip)] Tfport { pkt_source: String, + asic: DendriteAsic, }, #[serde(skip)] Uplink, diff --git a/sled-agent/src/services.rs b/sled-agent/src/services.rs index a9be0e7c4a..d1d8dbfff0 100644 --- a/sled-agent/src/services.rs +++ b/sled-agent/src/services.rs @@ -676,6 +676,11 @@ impl ServiceManager { device: "tofino".to_string(), }); } + ServiceType::Dendrite { + asic: DendriteAsic::SoftNpuPropolisDevice, + } => { + devices.push("/dev/tty03".into()); + } _ => (), } } @@ -741,7 +746,7 @@ impl ServiceManager { for svc in &req.services { match &svc.details { - ServiceType::Tfport { pkt_source } => { + ServiceType::Tfport { pkt_source, asic: _ } => { // The tfport service requires a MAC device to/from which sidecar // packets may be multiplexed. If the link isn't present, don't // bother trying to start the zone. @@ -772,9 +777,13 @@ impl ServiceManager { } Err(_) => { - return Err(Error::MissingDevice { - device: link.to_string(), - }); + if let SidecarRevision::SoftZone(_) = + self.inner.sidecar_revision + { + return Err(Error::MissingDevice { + device: link.to_string(), + }); + } } } } @@ -1815,14 +1824,21 @@ impl ServiceManager { "config/port_config", "/opt/oxide/dendrite/misc/model_config.toml", )?, - DendriteAsic::SoftNpu => { - smfh.setprop("config/mgmt", "uds")?; - smfh.setprop( - "config/uds_path", - "/opt/softnpu/stuff", - )?; + asic @ (DendriteAsic::SoftNpuZone + | DendriteAsic::SoftNpuPropolisDevice) => { + if asic == &DendriteAsic::SoftNpuZone { + smfh.setprop("config/mgmt", "uds")?; + smfh.setprop( + "config/uds_path", + "/opt/softnpu/stuff", + )?; + } + if asic == &DendriteAsic::SoftNpuPropolisDevice { + smfh.setprop("config/mgmt", "uart")?; + } let s = match self.inner.sidecar_revision { - SidecarRevision::Soft(ref s) => s, + SidecarRevision::SoftZone(ref s) => s, + SidecarRevision::SoftPropolis(ref s) => s, _ => { return Err(Error::SidecarRevision( anyhow::anyhow!( @@ -1847,7 +1863,7 @@ impl ServiceManager { }; smfh.refresh()?; } - ServiceType::Tfport { pkt_source } => { + ServiceType::Tfport { pkt_source, asic } => { info!(self.inner.log, "Setting up tfport service"); let is_gimlet = is_gimlet().map_err(|e| { @@ -1882,6 +1898,12 @@ impl ServiceManager { } smfh.setprop("config/pkt_source", pkt_source)?; } + if asic == &DendriteAsic::SoftNpuZone { + smfh.setprop("config/flags", "--sync-only")?; + } + if asic == &DendriteAsic::SoftNpuPropolisDevice { + smfh.setprop("config/pkt_source", pkt_source)?; + } smfh.setprop( "config/host", &format!("[{}]", Ipv6Addr::LOCALHOST), @@ -2509,19 +2531,42 @@ impl ServiceManager { vec![ ServiceType::Dendrite { asic: DendriteAsic::TofinoAsic }, ServiceType::ManagementGatewayService, - ServiceType::Tfport { pkt_source: "tfpkt0".to_string() }, + ServiceType::Tfport { + pkt_source: "tfpkt0".to_string(), + asic: DendriteAsic::TofinoAsic, + }, + ServiceType::Uplink, + ServiceType::Wicketd { baseboard }, + ServiceType::Mgd, + ServiceType::MgDdm { mode: "transit".to_string() }, + ] + } + + SledMode::Scrimlet { + asic: asic @ DendriteAsic::SoftNpuPropolisDevice, + } => { + data_links = vec!["vioif0".to_owned()]; + vec![ + ServiceType::Dendrite { asic }, + ServiceType::ManagementGatewayService, ServiceType::Uplink, ServiceType::Wicketd { baseboard }, ServiceType::Mgd, ServiceType::MgDdm { mode: "transit".to_string() }, + ServiceType::Tfport { + pkt_source: "vioif0".to_string(), + asic, + }, + ServiceType::SpSim, ] } // Sled is a scrimlet but is not running the real tofino driver. SledMode::Scrimlet { - asic: asic @ (DendriteAsic::TofinoStub | DendriteAsic::SoftNpu), + asic: + asic @ (DendriteAsic::TofinoStub | DendriteAsic::SoftNpuZone), } => { - if let DendriteAsic::SoftNpu = asic { + if let DendriteAsic::SoftNpuZone = asic { let softnpu_filesystem = zone::Fs { ty: "lofs".to_string(), dir: "/opt/softnpu/stuff".to_string(), @@ -2538,7 +2583,10 @@ impl ServiceManager { ServiceType::Wicketd { baseboard }, ServiceType::Mgd, ServiceType::MgDdm { mode: "transit".to_string() }, - ServiceType::Tfport { pkt_source: "tfpkt0".to_string() }, + ServiceType::Tfport { + pkt_source: "tfpkt0".to_string(), + asic, + }, ServiceType::SpSim, ] } @@ -3070,7 +3118,7 @@ mod test { // Wait for the networking service. let wait_ctx = svc::wait_for_service_context(); - wait_ctx.expect().return_once(|_, _| Ok(())); + wait_ctx.expect().return_once(|_, _, _| Ok(())); // Import the manifest, enable the service let execute_ctx = illumos_utils::execute_context(); diff --git a/sled-hardware/src/illumos/mod.rs b/sled-hardware/src/illumos/mod.rs index 0364c98f14..c0145b75e8 100644 --- a/sled-hardware/src/illumos/mod.rs +++ b/sled-hardware/src/illumos/mod.rs @@ -611,34 +611,37 @@ impl HardwareManager { // receiver will receive a tokio::sync::broadcast::error::RecvError::Lagged // error, indicating they should re-scan the hardware themselves. let (tx, _) = broadcast::channel(1024); - let hw = match sled_mode { - // Treat as a possible scrimlet and setup to scan for real Tofino device. - SledMode::Auto - | SledMode::Scrimlet { asic: DendriteAsic::TofinoAsic } => { - HardwareView::new() - } + let hw = + match sled_mode { + // Treat as a possible scrimlet and setup to scan for real Tofino device. + SledMode::Auto + | SledMode::Scrimlet { asic: DendriteAsic::TofinoAsic } => { + HardwareView::new() + } - // Treat sled as gimlet and ignore any attached Tofino device. - SledMode::Gimlet => HardwareView::new_stub_tofino( - // active= - false, - ), + // Treat sled as gimlet and ignore any attached Tofino device. + SledMode::Gimlet => HardwareView::new_stub_tofino( + // active= + false, + ), - // Treat as scrimlet and use the stub Tofino device. - SledMode::Scrimlet { asic: DendriteAsic::TofinoStub } => { - HardwareView::new_stub_tofino(true) - } + // Treat as scrimlet and use the stub Tofino device. + SledMode::Scrimlet { asic: DendriteAsic::TofinoStub } => { + HardwareView::new_stub_tofino(true) + } - // Treat as scrimlet (w/ SoftNPU) and use the stub Tofino device. - // TODO-correctness: - // I'm not sure whether or not we should be treating softnpu - // as a stub or treating it as a different HardwareView variant, - // so this might change. - SledMode::Scrimlet { asic: DendriteAsic::SoftNpu } => { - HardwareView::new_stub_tofino(true) + // Treat as scrimlet (w/ SoftNPU) and use the stub Tofino device. + // TODO-correctness: + // I'm not sure whether or not we should be treating softnpu + // as a stub or treating it as a different HardwareView variant, + // so this might change. + SledMode::Scrimlet { + asic: + DendriteAsic::SoftNpuZone + | DendriteAsic::SoftNpuPropolisDevice, + } => HardwareView::new_stub_tofino(true), } - } - .map_err(|e| e.to_string())?; + .map_err(|e| e.to_string())?; let inner = Arc::new(Mutex::new(hw)); // Force the device tree to be polled at least once before returning. diff --git a/sled-hardware/src/lib.rs b/sled-hardware/src/lib.rs index c81bcddbfb..654dfd59d9 100644 --- a/sled-hardware/src/lib.rs +++ b/sled-hardware/src/lib.rs @@ -44,7 +44,8 @@ pub enum HardwareUpdate { pub enum DendriteAsic { TofinoAsic, TofinoStub, - SoftNpu, + SoftNpuZone, + SoftNpuPropolisDevice, } impl std::fmt::Display for DendriteAsic { @@ -55,7 +56,9 @@ impl std::fmt::Display for DendriteAsic { match self { DendriteAsic::TofinoAsic => "tofino_asic", DendriteAsic::TofinoStub => "tofino_stub", - DendriteAsic::SoftNpu => "soft_npu", + DendriteAsic::SoftNpuZone => "soft_npu_zone", + DendriteAsic::SoftNpuPropolisDevice => + "soft_npu_propolis_device", } ) } diff --git a/smf/sled-agent/non-gimlet/config.toml b/smf/sled-agent/non-gimlet/config.toml index b4cb7e6cff..684c0f8589 100644 --- a/smf/sled-agent/non-gimlet/config.toml +++ b/smf/sled-agent/non-gimlet/config.toml @@ -12,7 +12,7 @@ sled_mode = "scrimlet" # Identifies the revision of the sidecar that is attached, if one is attached. # TODO: This field should be removed once Gimlets have the ability to auto-detect # this information. -sidecar_revision.soft = { front_port_count = 1, rear_port_count = 1 } +sidecar_revision.soft_zone = { front_port_count = 1, rear_port_count = 1 } # Setting this to true causes sled-agent to always report that its time is # in-sync, rather than querying its NTP zone. diff --git a/tools/create_virtual_hardware.sh b/tools/create_virtual_hardware.sh index 908cb752e9..1db40208f7 100755 --- a/tools/create_virtual_hardware.sh +++ b/tools/create_virtual_hardware.sh @@ -16,6 +16,7 @@ set -x SOURCE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" OMICRON_TOP="$SOURCE_DIR/.." +SOFTNPU_MODE=${SOFTNPU_MODE:-zone}; . "$SOURCE_DIR/virtual_hardware.sh" @@ -83,6 +84,9 @@ in the SoftNPU zone later to add those entries." ensure_run_as_root ensure_zpools -ensure_simulated_links "$PHYSICAL_LINK" -warn_if_no_proxy_arp -ensure_softnpu_zone + +if [[ "$SOFTNPU_MODE" == "zone" ]]; then + ensure_simulated_links "$PHYSICAL_LINK" + warn_if_no_proxy_arp + ensure_softnpu_zone +fi diff --git a/tools/dendrite_openapi_version b/tools/dendrite_openapi_version index c91d1c2e98..55d2adfc46 100644 --- a/tools/dendrite_openapi_version +++ b/tools/dendrite_openapi_version @@ -1,2 +1,2 @@ -COMMIT="343e3a572cc02efe3f8b68f9affd008623a33966" -SHA2="544ab42ccc7942d8ece9cdc80cd85d002bcf9d5646a291322bf2f79087ab6df0" +COMMIT="559fad2f379900a05ced410944353c1d19100390" +SHA2="82437c74afd4894aa5b9ea800d5777793e8777fe87471321dd22ad1a1c9c9ef3" diff --git a/tools/dendrite_stub_checksums b/tools/dendrite_stub_checksums index 8fa98114fb..456084adee 100644 --- a/tools/dendrite_stub_checksums +++ b/tools/dendrite_stub_checksums @@ -1,3 +1,3 @@ -CIDL_SHA256_ILLUMOS="0808f331741e02d55e199847579dfd01f3658b21c7122cef8c3f9279f43dbab0" -CIDL_SHA256_LINUX_DPD="3e276dd553dd7cdb75c8ad023c2cd29b91485fafb94f27097a745b2b7ef5ecea" -CIDL_SHA256_LINUX_SWADM="645faf8a93bcae9814b2f116bccd66a54763332b56220e93b66316c853ce13d2" +CIDL_SHA256_ILLUMOS="ce14c1f0481b13ce47a25386a3b1e49d9570f4c1c31cad3f13c14f75b130dafa" +CIDL_SHA256_LINUX_DPD="d7da0aaed4e824a8e98b1a39e9ee41ad934ce38b0faa140ab4e7e2ca8c194e4e" +CIDL_SHA256_LINUX_SWADM="0449383a57468aec3b5a4ad26962cfc9e9a121bd13e777329e8a70767e6d9aae" diff --git a/tools/maghemite_ddm_openapi_version b/tools/maghemite_ddm_openapi_version index 89c3e46164..3f6b566cda 100644 --- a/tools/maghemite_ddm_openapi_version +++ b/tools/maghemite_ddm_openapi_version @@ -1,2 +1,2 @@ -COMMIT="d7169a61fd8833b3a1e6f46d897ca3295b2a28b6" +COMMIT="82aa17646265449ee0ede9410208e510fa4a5877" SHA2="9737906555a60911636532f00f1dc2866dc7cd6553beb106e9e57beabad41cdf" diff --git a/tools/maghemite_mg_openapi_version b/tools/maghemite_mg_openapi_version index a7e18285ae..3de723fca6 100644 --- a/tools/maghemite_mg_openapi_version +++ b/tools/maghemite_mg_openapi_version @@ -1,2 +1,2 @@ -COMMIT="d7169a61fd8833b3a1e6f46d897ca3295b2a28b6" -SHA2="d0f7611e5ecd049b0f83bcfa843942401f155a0be36d9a2dfd73b8341d5f816e" +COMMIT="82aa17646265449ee0ede9410208e510fa4a5877" +SHA2="b3f55fe24e54530fdf96c22a033f9edc0bad9c0a5e3344763a23e52b251d5113" diff --git a/tools/maghemite_mgd_checksums b/tools/maghemite_mgd_checksums index e65e1fc0a2..a4dd82aaca 100644 --- a/tools/maghemite_mgd_checksums +++ b/tools/maghemite_mgd_checksums @@ -1,2 +1,2 @@ -CIDL_SHA256="452dfb3491e1b6d4df6be1cb689921f59623aed082e47606a78c0f44d918f66a" -MGD_LINUX_SHA256="d4c48eb6374c0cc7812b7af2c0ac92acdcbc91b7718a9ce64d069da00ae5ae73" +CIDL_SHA256="1badd6adfece0a1b661f7efb9a2ca65e471f45cf9c8ecbd72b228ca174311e31" +MGD_LINUX_SHA256="92463e3266f5a702af28504349526189aa0ebb23adb166ec2603182acf6cdb8c" diff --git a/wicketd/src/preflight_check/uplink.rs b/wicketd/src/preflight_check/uplink.rs index 4d199d28b8..d94baf1995 100644 --- a/wicketd/src/preflight_check/uplink.rs +++ b/wicketd/src/preflight_check/uplink.rs @@ -24,6 +24,7 @@ use omicron_common::api::internal::shared::PortFec as OmicronPortFec; use omicron_common::api::internal::shared::PortSpeed as OmicronPortSpeed; use omicron_common::api::internal::shared::RackNetworkConfig; use omicron_common::api::internal::shared::SwitchLocation; +use omicron_common::OMICRON_DPD_TAG; use schemars::JsonSchema; use serde::Deserialize; use serde::Serialize; @@ -185,7 +186,11 @@ fn add_steps_for_single_local_uplink_preflight_check<'a>( // Create and configure the link. match dpd_client - .port_settings_apply(&port_id, &port_settings) + .port_settings_apply( + &port_id, + Some(OMICRON_DPD_TAG), + &port_settings, + ) .await { Ok(_response) => { @@ -714,8 +719,8 @@ fn add_steps_for_single_local_uplink_preflight_check<'a>( dpd_client .port_settings_apply( &port_id, + Some(OMICRON_DPD_TAG), &PortSettings { - tag: WICKETD_TAG.to_string(), links: HashMap::new(), v4_routes: HashMap::new(), v6_routes: HashMap::new(), @@ -758,7 +763,6 @@ fn build_port_settings( }; let mut port_settings = PortSettings { - tag: WICKETD_TAG.to_string(), links: HashMap::new(), v4_routes: HashMap::new(), v6_routes: HashMap::new(), @@ -777,6 +781,7 @@ fn build_port_settings( kr: false, fec, speed, + lane: Some(LinkId(0)), }, }, ); From cede9b3a78f30ccd8520f89984d874d40f3ea9f3 Mon Sep 17 00:00:00 2001 From: David Crespo Date: Sat, 4 Nov 2023 16:09:54 -0500 Subject: [PATCH 06/13] Bump web console (minor fixes) (#4438) ### User-facing fixes * [57cc1892](https://github.com/oxidecomputer/console/commit/57cc1892) oxidecomputer/console#1802 * [47d76dbf](https://github.com/oxidecomputer/console/commit/47d76dbf) oxidecomputer/console#1806 * [60c2285e](https://github.com/oxidecomputer/console/commit/60c2285e) oxidecomputer/console#1804 ### Full summary https://github.com/oxidecomputer/console/compare/bd65b9da...ae8218df * [ae8218df](https://github.com/oxidecomputer/console/commit/ae8218df) bump msw to 2.0.3 for the real safari fix * [9a3f95a9](https://github.com/oxidecomputer/console/commit/9a3f95a9) reduce dev console noise about local assets not served by MSW * [a61ecf24](https://github.com/oxidecomputer/console/commit/a61ecf24) oxidecomputer/console#1809 * [50f3a5b2](https://github.com/oxidecomputer/console/commit/50f3a5b2) bump recharts and react query * [1a2b5656](https://github.com/oxidecomputer/console/commit/1a2b5656) oxidecomputer/console#1808 * [4c01cd68](https://github.com/oxidecomputer/console/commit/4c01cd68) oxidecomputer/console#1800 * [57cc1892](https://github.com/oxidecomputer/console/commit/57cc1892) oxidecomputer/console#1802 * [47d76dbf](https://github.com/oxidecomputer/console/commit/47d76dbf) oxidecomputer/console#1806 * [eee0eb2e](https://github.com/oxidecomputer/console/commit/eee0eb2e) oxidecomputer/console#1805 * [60c2285e](https://github.com/oxidecomputer/console/commit/60c2285e) oxidecomputer/console#1804 * [d9cf1ef1](https://github.com/oxidecomputer/console/commit/d9cf1ef1) bump sort imports plugin for vuln * [ba3a383e](https://github.com/oxidecomputer/console/commit/ba3a383e) bump playwright to 1.39 (fix issue with z-index test) --- tools/console_version | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/console_version b/tools/console_version index 7e8d352efd..811620e9e7 100644 --- a/tools/console_version +++ b/tools/console_version @@ -1,2 +1,2 @@ -COMMIT="bd65b9da7019ad812dd056e7fc182df2cf4ec128" -SHA2="e4d4f33996a6e89b972fac61737acb7f1dbd21943d1f6bef776d4ee9bcccd2b0" +COMMIT="ae8218df707360a902133f4a96b48a3b5a62a09e" +SHA2="ae35b991d3ff835a59b59126298790cb7431a282b25ba4add4e7fb6ea6b98989" From 5d146dd235c43c0cbff8de96a91737301556e3ee Mon Sep 17 00:00:00 2001 From: Rain Date: Mon, 6 Nov 2023 09:39:12 -0800 Subject: [PATCH 07/13] [wicket] move cli-related code to its own directory (#4429) This code lives next to the "ui" and "state" directories. --- wicket/src/cli/command.rs | 55 +++++++++++++++++++ wicket/src/cli/mod.rs | 18 ++++++ wicket/src/{ => cli}/preflight.rs | 0 wicket/src/{ => cli}/rack_setup.rs | 0 .../{ => cli}/rack_setup/config_template.toml | 0 .../src/{ => cli}/rack_setup/config_toml.rs | 0 wicket/src/{ => cli}/upload.rs | 0 wicket/src/dispatch.rs | 40 +------------- wicket/src/lib.rs | 4 +- 9 files changed, 76 insertions(+), 41 deletions(-) create mode 100644 wicket/src/cli/command.rs create mode 100644 wicket/src/cli/mod.rs rename wicket/src/{ => cli}/preflight.rs (100%) rename wicket/src/{ => cli}/rack_setup.rs (100%) rename wicket/src/{ => cli}/rack_setup/config_template.toml (100%) rename wicket/src/{ => cli}/rack_setup/config_toml.rs (100%) rename wicket/src/{ => cli}/upload.rs (100%) diff --git a/wicket/src/cli/command.rs b/wicket/src/cli/command.rs new file mode 100644 index 0000000000..34f041b203 --- /dev/null +++ b/wicket/src/cli/command.rs @@ -0,0 +1,55 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +//! Code that manages command dispatch from a shell for wicket. + +use std::net::SocketAddrV6; + +use anyhow::{Context, Result}; +use clap::Parser; + +use super::{ + preflight::PreflightArgs, rack_setup::SetupArgs, upload::UploadArgs, +}; + +pub fn exec( + log: slog::Logger, + args: &str, + wicketd_addr: SocketAddrV6, +) -> Result<()> { + // The argument is in a quoted form, so split it using Unix shell semantics. + let args = shell_words::split(&args).with_context(|| { + format!("could not parse shell arguments from input {args}") + })?; + + // parse_from uses the the first argument as the command name. Insert "wicket" as + // the command name. + let args = ShellCommand::parse_from( + std::iter::once("wicket".to_owned()).chain(args), + ); + match args { + ShellCommand::UploadRepo(args) => args.exec(log, wicketd_addr), + ShellCommand::Setup(args) => args.exec(log, wicketd_addr), + ShellCommand::Preflight(args) => args.exec(log, wicketd_addr), + } +} + +/// Arguments passed to wicket. +/// +/// Wicket is designed to be used as a captive shell, set up via sshd +/// ForceCommand. If no arguments are specified, wicket behaves like a TUI. +/// However, if arguments are specified via SSH_ORIGINAL_COMMAND, wicketd +/// accepts an upload command. +#[derive(Debug, Parser)] +enum ShellCommand { + /// Upload a TUF repository to wicketd. + #[command(visible_alias = "upload")] + UploadRepo(UploadArgs), + /// Interact with rack setup configuration. + #[command(subcommand)] + Setup(SetupArgs), + /// Run checks prior to setting up the rack. + #[command(subcommand)] + Preflight(PreflightArgs), +} diff --git a/wicket/src/cli/mod.rs b/wicket/src/cli/mod.rs new file mode 100644 index 0000000000..7e8f6540ea --- /dev/null +++ b/wicket/src/cli/mod.rs @@ -0,0 +1,18 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +// Copyright 2023 Oxide Computer Company + +//! Command-line interface to wicket. +//! +//! By default, the main interface to wicket is via a TUI. However, some +//! commands and use cases must be done via the CLI, and this module contains +//! support for that. + +mod command; +mod preflight; +mod rack_setup; +mod upload; + +pub use command::exec; diff --git a/wicket/src/preflight.rs b/wicket/src/cli/preflight.rs similarity index 100% rename from wicket/src/preflight.rs rename to wicket/src/cli/preflight.rs diff --git a/wicket/src/rack_setup.rs b/wicket/src/cli/rack_setup.rs similarity index 100% rename from wicket/src/rack_setup.rs rename to wicket/src/cli/rack_setup.rs diff --git a/wicket/src/rack_setup/config_template.toml b/wicket/src/cli/rack_setup/config_template.toml similarity index 100% rename from wicket/src/rack_setup/config_template.toml rename to wicket/src/cli/rack_setup/config_template.toml diff --git a/wicket/src/rack_setup/config_toml.rs b/wicket/src/cli/rack_setup/config_toml.rs similarity index 100% rename from wicket/src/rack_setup/config_toml.rs rename to wicket/src/cli/rack_setup/config_toml.rs diff --git a/wicket/src/upload.rs b/wicket/src/cli/upload.rs similarity index 100% rename from wicket/src/upload.rs rename to wicket/src/cli/upload.rs diff --git a/wicket/src/dispatch.rs b/wicket/src/dispatch.rs index e8191f59cb..3ef04ee302 100644 --- a/wicket/src/dispatch.rs +++ b/wicket/src/dispatch.rs @@ -8,13 +8,10 @@ use std::net::{Ipv6Addr, SocketAddrV6}; use anyhow::{bail, Context, Result}; use camino::{Utf8Path, Utf8PathBuf}; -use clap::Parser; use omicron_common::{address::WICKETD_PORT, FileKv}; use slog::Drain; -use crate::{ - preflight::PreflightArgs, rack_setup::SetupArgs, upload::UploadArgs, Runner, -}; +use crate::Runner; pub fn exec() -> Result<()> { let wicketd_addr = @@ -22,22 +19,8 @@ pub fn exec() -> Result<()> { // SSH_ORIGINAL_COMMAND contains additional arguments, if any. if let Ok(ssh_args) = std::env::var("SSH_ORIGINAL_COMMAND") { - // The argument is in a quoted form, so split it using Unix shell semantics. - let args = shell_words::split(&ssh_args).with_context(|| { - format!("could not parse shell arguments from input {ssh_args}") - })?; - let log = setup_log(&log_path()?, WithStderr::Yes)?; - // parse_from uses the the first argument as the command name. Insert "wicket" as - // the command name. - let args = ShellCommand::parse_from( - std::iter::once("wicket".to_owned()).chain(args), - ); - match args { - ShellCommand::UploadRepo(args) => args.exec(log, wicketd_addr), - ShellCommand::Setup(args) => args.exec(log, wicketd_addr), - ShellCommand::Preflight(args) => args.exec(log, wicketd_addr), - } + crate::cli::exec(log, &ssh_args, wicketd_addr) } else { // Do not expose log messages via standard error since they'll show up // on top of the TUI. @@ -46,25 +29,6 @@ pub fn exec() -> Result<()> { } } -/// Arguments passed to wicket. -/// -/// Wicket is designed to be used as a captive shell, set up via sshd -/// ForceCommand. If no arguments are specified, wicket behaves like a TUI. -/// However, if arguments are specified via SSH_ORIGINAL_COMMAND, wicketd -/// accepts an upload command. -#[derive(Debug, Parser)] -enum ShellCommand { - /// Upload a TUF repository to wicketd. - #[command(visible_alias = "upload")] - UploadRepo(UploadArgs), - /// Interact with rack setup configuration. - #[command(subcommand)] - Setup(SetupArgs), - /// Run checks prior to setting up the rack. - #[command(subcommand)] - Preflight(PreflightArgs), -} - fn setup_log( path: &Utf8Path, with_stderr: WithStderr, diff --git a/wicket/src/lib.rs b/wicket/src/lib.rs index a16ef2a3e1..6e760968f8 100644 --- a/wicket/src/lib.rs +++ b/wicket/src/lib.rs @@ -7,15 +7,13 @@ use std::time::Duration; +mod cli; mod dispatch; mod events; mod keymap; -mod preflight; -mod rack_setup; mod runner; mod state; mod ui; -mod upload; mod wicketd; pub const TICK_INTERVAL: Duration = Duration::from_millis(30); From ba730f909999a990572c4138b9f0fc39ebc11556 Mon Sep 17 00:00:00 2001 From: "oxide-renovate[bot]" <146848827+oxide-renovate[bot]@users.noreply.github.com> Date: Mon, 6 Nov 2023 09:41:11 -0800 Subject: [PATCH 08/13] chore(deps): update rust crate zone to 0.3 (#4442) --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a7aa3aa153..65e8ada79c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10600,9 +10600,9 @@ dependencies = [ [[package]] name = "zone" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0545a42fbd7a81245726d54a0146cb4fd93882ebb6da50d60acf2e37394f198" +checksum = "a62a428a79ea2224ce8ab05d6d8a21bdd7b4b68a8dbc1230511677a56e72ef22" dependencies = [ "itertools 0.10.5", "thiserror", @@ -10612,9 +10612,9 @@ dependencies = [ [[package]] name = "zone_cfg_derive" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef224b009d070d3b1adb9e375fcf8ec2f1948a412c3bbf8755c0ef4e3f91ef94" +checksum = "d5c4f01d3785e222d5aca11c9813e9c46b69abfe258756c99c9b628683626cc8" dependencies = [ "heck 0.4.1", "proc-macro-error", diff --git a/Cargo.toml b/Cargo.toml index 8aaae347d5..afdebad6fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -383,7 +383,7 @@ wicket-common = { path = "wicket-common" } wicketd-client = { path = "clients/wicketd-client" } zeroize = { version = "1.6.0", features = ["zeroize_derive", "std"] } zip = { version = "0.6.6", default-features = false, features = ["deflate","bzip2"] } -zone = { version = "0.2", default-features = false, features = ["async"] } +zone = { version = "0.3", default-features = false, features = ["async"] } [profile.dev] panic = "abort" From a74dcc0643c71b339cec949ad2708f3d392ac969 Mon Sep 17 00:00:00 2001 From: "oxide-renovate[bot]" <146848827+oxide-renovate[bot]@users.noreply.github.com> Date: Mon, 6 Nov 2023 09:41:55 -0800 Subject: [PATCH 09/13] chore(deps): update rust crate tough to 0.14 (#4432) --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 65e8ada79c..cee23682de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9285,9 +9285,9 @@ checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d" [[package]] name = "tough" -version = "0.12.5" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc636dd1ee889a366af6731f1b63b60baf19528b46df5a7c2d4b3bf8b60bca2d" +checksum = "eda3efa9005cf9c1966984c3b9a44c3f37b7ed2c95ba338d6ad51bba70e989a0" dependencies = [ "chrono", "dyn-clone", diff --git a/Cargo.toml b/Cargo.toml index afdebad6fb..cfb17ac29d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -365,7 +365,7 @@ tokio-util = "0.7.10" toml = "0.8.6" toml_edit = "0.20.7" topological-sort = "0.2.2" -tough = { version = "0.12", features = [ "http" ] } +tough = { version = "0.14", features = [ "http" ] } trust-dns-client = "0.22" trust-dns-proto = "0.22" trust-dns-resolver = "0.22" From 3148150023268f2b69af135a0e36287e1074fd9b Mon Sep 17 00:00:00 2001 From: "oxide-renovate[bot]" <146848827+oxide-renovate[bot]@users.noreply.github.com> Date: Mon, 6 Nov 2023 09:42:36 -0800 Subject: [PATCH 10/13] chore(deps): update rust crate uuid to 1.5.0 (#4441) --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- workspace-hack/Cargo.toml | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cee23682de..32bda8c185 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9833,9 +9833,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" dependencies = [ "getrandom 0.2.10", "serde", diff --git a/Cargo.toml b/Cargo.toml index cfb17ac29d..585ed9e37c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -376,7 +376,7 @@ tufaceous-lib = { path = "tufaceous-lib" } unicode-width = "0.1.11" update-engine = { path = "update-engine" } usdt = "0.3" -uuid = { version = "1.4.1", features = ["serde", "v4"] } +uuid = { version = "1.5.0", features = ["serde", "v4"] } walkdir = "2.4" wicket = { path = "wicket" } wicket-common = { path = "wicket-common" } diff --git a/workspace-hack/Cargo.toml b/workspace-hack/Cargo.toml index 49077eac77..b83eecf168 100644 --- a/workspace-hack/Cargo.toml +++ b/workspace-hack/Cargo.toml @@ -99,7 +99,7 @@ trust-dns-proto = { version = "0.22.0" } unicode-bidi = { version = "0.3.13" } unicode-normalization = { version = "0.1.22" } usdt = { version = "0.3.5" } -uuid = { version = "1.4.1", features = ["serde", "v4"] } +uuid = { version = "1.5.0", features = ["serde", "v4"] } yasna = { version = "0.5.2", features = ["bit-vec", "num-bigint", "std", "time"] } zeroize = { version = "1.6.0", features = ["std", "zeroize_derive"] } zip = { version = "0.6.6", default-features = false, features = ["bzip2", "deflate"] } @@ -194,7 +194,7 @@ unicode-bidi = { version = "0.3.13" } unicode-normalization = { version = "0.1.22" } unicode-xid = { version = "0.2.4" } usdt = { version = "0.3.5" } -uuid = { version = "1.4.1", features = ["serde", "v4"] } +uuid = { version = "1.5.0", features = ["serde", "v4"] } yasna = { version = "0.5.2", features = ["bit-vec", "num-bigint", "std", "time"] } zeroize = { version = "1.6.0", features = ["std", "zeroize_derive"] } zip = { version = "0.6.6", default-features = false, features = ["bzip2", "deflate"] } From 5b5077736c8439e6184bc191b0033f07c1bb68e1 Mon Sep 17 00:00:00 2001 From: "oxide-renovate[bot]" <146848827+oxide-renovate[bot]@users.noreply.github.com> Date: Mon, 6 Nov 2023 10:15:36 -0800 Subject: [PATCH 11/13] chore(deps): update rust crate libc to 0.2.150 (#4440) --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- workspace-hack/Cargo.toml | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 32bda8c185..7c0e956378 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3843,9 +3843,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.149" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "libdlpi-sys" diff --git a/Cargo.toml b/Cargo.toml index 585ed9e37c..03a0288297 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -225,7 +225,7 @@ ipnetwork = { version = "0.20", features = ["schemars"] } itertools = "0.11.0" key-manager = { path = "key-manager" } lazy_static = "1.4.0" -libc = "0.2.149" +libc = "0.2.150" linear-map = "1.2.0" macaddr = { version = "1.0.1", features = ["serde_std"] } mime_guess = "2.0.4" diff --git a/workspace-hack/Cargo.toml b/workspace-hack/Cargo.toml index b83eecf168..43276ef15b 100644 --- a/workspace-hack/Cargo.toml +++ b/workspace-hack/Cargo.toml @@ -56,7 +56,7 @@ ipnetwork = { version = "0.20.0", features = ["schemars"] } itertools = { version = "0.10.5" } lalrpop-util = { version = "0.19.12" } lazy_static = { version = "1.4.0", default-features = false, features = ["spin_no_std"] } -libc = { version = "0.2.149", features = ["extra_traits"] } +libc = { version = "0.2.150", features = ["extra_traits"] } log = { version = "0.4.20", default-features = false, features = ["std"] } managed = { version = "0.8.0", default-features = false, features = ["alloc", "map"] } memchr = { version = "2.6.3" } @@ -148,7 +148,7 @@ ipnetwork = { version = "0.20.0", features = ["schemars"] } itertools = { version = "0.10.5" } lalrpop-util = { version = "0.19.12" } lazy_static = { version = "1.4.0", default-features = false, features = ["spin_no_std"] } -libc = { version = "0.2.149", features = ["extra_traits"] } +libc = { version = "0.2.150", features = ["extra_traits"] } log = { version = "0.4.20", default-features = false, features = ["std"] } managed = { version = "0.8.0", default-features = false, features = ["alloc", "map"] } memchr = { version = "2.6.3" } From 522945943f9fa180af755b00be44c9a150873444 Mon Sep 17 00:00:00 2001 From: "oxide-renovate[bot]" <146848827+oxide-renovate[bot]@users.noreply.github.com> Date: Mon, 6 Nov 2023 21:41:21 +0000 Subject: [PATCH 12/13] chore(deps): update rust to v1.73.0 (#4443) Co-authored-by: Rain --- Cargo.lock | 7 +++++++ Cargo.toml | 1 + bootstore/src/schemes/v0/peer_networking.rs | 3 +++ nexus/db-queries/src/db/datastore/inventory.rs | 2 +- package/Cargo.toml | 1 + package/src/bin/omicron-package.rs | 12 ++++++------ rust-toolchain.toml | 2 +- sled-agent/src/sled_agent.rs | 4 ++-- sled-agent/src/zone_bundle.rs | 2 +- 9 files changed, 23 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7c0e956378..cc10947083 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5234,6 +5234,7 @@ dependencies = [ "slog-term", "smf", "strum", + "swrite", "tar", "tempfile", "thiserror", @@ -8713,6 +8714,12 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +[[package]] +name = "swrite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f3fece30b2dc06d65ecbca97b602db15bf75f932711d60cc604534f1f8b7a03" + [[package]] name = "syn" version = "1.0.109" diff --git a/Cargo.toml b/Cargo.toml index 03a0288297..63b18a9f9a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -345,6 +345,7 @@ static_assertions = "1.1.0" steno = "0.4.0" strum = { version = "0.25", features = [ "derive" ] } subprocess = "0.2.9" +swrite = "0.1.0" libsw = { version = "3.3.0", features = ["tokio"] } syn = { version = "2.0" } tabled = "0.14" diff --git a/bootstore/src/schemes/v0/peer_networking.rs b/bootstore/src/schemes/v0/peer_networking.rs index acde14d085..33673cdab8 100644 --- a/bootstore/src/schemes/v0/peer_networking.rs +++ b/bootstore/src/schemes/v0/peer_networking.rs @@ -643,6 +643,9 @@ async fn perform_handshake( let end = INITIAL_READ + identify_len; + // Clippy for Rust 1.73 warns on this but there doesn't seem to be a + // better way to write it? + #[allow(clippy::unnecessary_unwrap)] if identify.is_some() && !out_cursor.has_remaining() { return Ok((read_sock, write_sock, identify.unwrap())); } diff --git a/nexus/db-queries/src/db/datastore/inventory.rs b/nexus/db-queries/src/db/datastore/inventory.rs index 6b7d97754a..114b9dbe31 100644 --- a/nexus/db-queries/src/db/datastore/inventory.rs +++ b/nexus/db-queries/src/db/datastore/inventory.rs @@ -685,7 +685,7 @@ impl DataStore { .rev() .find(|(_i, (_collection_id, nerrors))| *nerrors == 0); let candidate = match last_completed_idx { - Some((i, _)) if i == 0 => candidates.iter().skip(1).next(), + Some((0, _)) => candidates.iter().skip(1).next(), _ => candidates.iter().next(), } .map(|(collection_id, _nerrors)| *collection_id); diff --git a/package/Cargo.toml b/package/Cargo.toml index b840938db0..9bf0b37a23 100644 --- a/package/Cargo.toml +++ b/package/Cargo.toml @@ -27,6 +27,7 @@ slog-async.workspace = true slog-term.workspace = true smf.workspace = true strum.workspace = true +swrite.workspace = true tar.workspace = true tempfile.workspace = true thiserror.workspace = true diff --git a/package/src/bin/omicron-package.rs b/package/src/bin/omicron-package.rs index bc07b61234..357a217fe5 100644 --- a/package/src/bin/omicron-package.rs +++ b/package/src/bin/omicron-package.rs @@ -29,6 +29,7 @@ use std::io::Write; use std::path::{Path, PathBuf}; use std::str::FromStr; use std::sync::Arc; +use swrite::{swrite, SWrite}; use tokio::io::{AsyncReadExt, AsyncWriteExt, BufReader}; use tokio::process::Command; @@ -153,12 +154,11 @@ async fn do_for_all_rust_packages( }) .partition(|(_, release)| *release); - let features = config - .target - .0 - .iter() - .map(|(name, value)| format!("{}-{} ", name, value)) - .collect::(); + let features = + config.target.0.iter().fold(String::new(), |mut acc, (name, value)| { + swrite!(acc, "{}-{} ", name, value); + acc + }); // Execute all the release / debug packages at the same time. if !release_pkgs.is_empty() { diff --git a/rust-toolchain.toml b/rust-toolchain.toml index eacfef491b..804ff08cce 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -4,5 +4,5 @@ # # We choose a specific toolchain (rather than "stable") for repeatability. The # intent is to keep this up-to-date with recently-released stable Rust. -channel = "1.72.1" +channel = "1.73.0" profile = "default" diff --git a/sled-agent/src/sled_agent.rs b/sled-agent/src/sled_agent.rs index 52513f081d..6655a732a0 100644 --- a/sled-agent/src/sled_agent.rs +++ b/sled-agent/src/sled_agent.rs @@ -299,7 +299,7 @@ impl SledAgent { sz, )?; } - Some(sz) if sz == 0 => { + Some(0) => { panic!("Invalid requested swap device size of 0 GiB"); } None | Some(_) => { @@ -375,7 +375,7 @@ impl SledAgent { e })?; } - Some(sz) if sz == 0 => { + Some(0) => { warn!(log, "Not using VMM reservoir (size 0 bytes requested)"); } None => { diff --git a/sled-agent/src/zone_bundle.rs b/sled-agent/src/zone_bundle.rs index 55661371c3..91cb850df4 100644 --- a/sled-agent/src/zone_bundle.rs +++ b/sled-agent/src/zone_bundle.rs @@ -904,7 +904,7 @@ async fn find_service_log_files( if path != current_log_file && path_ref.starts_with(current_log_file_ref) { - log_files.push(path.clone().into()); + log_files.push(path.into()); } } From ebb25ebbb27892cbfe8bb2d00f6cf7b8de563a29 Mon Sep 17 00:00:00 2001 From: Rain Date: Mon, 6 Nov 2023 13:58:57 -0800 Subject: [PATCH 13/13] [wicketd] make clear_update_state take multiple SPs (#4430) This ensures atomicity and will be used for a new CLI interface. --- openapi/wicketd.json | 85 +++++++++++++++++++++++---------- wicket/src/wicketd.rs | 22 +++++---- wicketd/src/http_entrypoints.rs | 42 ++++++++++++---- wicketd/src/update_tracker.rs | 54 ++++++++++++++------- 4 files changed, 143 insertions(+), 60 deletions(-) diff --git a/openapi/wicketd.json b/openapi/wicketd.json index a75c965ad8..e0b37f1ba2 100644 --- a/openapi/wicketd.json +++ b/openapi/wicketd.json @@ -131,44 +131,31 @@ } } }, - "/clear-update-state/{type}/{slot}": { + "/clear-update-state": { "post": { "summary": "Resets update state for a sled.", "description": "Use this to clear update state after a failed update.", "operationId": "post_clear_update_state", - "parameters": [ - { - "in": "path", - "name": "slot", - "required": true, - "schema": { - "type": "integer", - "format": "uint32", - "minimum": 0 - } - }, - { - "in": "path", - "name": "type", - "required": true, - "schema": { - "$ref": "#/components/schemas/SpType" - } - } - ], "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ClearUpdateStateOptions" + "$ref": "#/components/schemas/ClearUpdateStateParams" } } }, "required": true }, "responses": { - "204": { - "description": "resource updated" + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ClearUpdateStateResponse" + } + } + } }, "4XX": { "$ref": "#/components/responses/Error" @@ -1014,6 +1001,56 @@ } } }, + "ClearUpdateStateParams": { + "type": "object", + "properties": { + "options": { + "description": "Options for clearing update state", + "allOf": [ + { + "$ref": "#/components/schemas/ClearUpdateStateOptions" + } + ] + }, + "targets": { + "description": "The SP identifiers to clear the update state for. Must be non-empty.", + "type": "array", + "items": { + "$ref": "#/components/schemas/SpIdentifier" + }, + "uniqueItems": true + } + }, + "required": [ + "options", + "targets" + ] + }, + "ClearUpdateStateResponse": { + "type": "object", + "properties": { + "cleared": { + "description": "The SPs for which update data was cleared.", + "type": "array", + "items": { + "$ref": "#/components/schemas/SpIdentifier" + }, + "uniqueItems": true + }, + "no_update_data": { + "description": "The SPs that had no update state to clear.", + "type": "array", + "items": { + "$ref": "#/components/schemas/SpIdentifier" + }, + "uniqueItems": true + } + }, + "required": [ + "cleared", + "no_update_data" + ] + }, "CurrentRssUserConfig": { "type": "object", "properties": { diff --git a/wicket/src/wicketd.rs b/wicket/src/wicketd.rs index 2411542429..33c80410d8 100644 --- a/wicket/src/wicketd.rs +++ b/wicket/src/wicketd.rs @@ -10,9 +10,10 @@ use std::net::SocketAddrV6; use tokio::sync::mpsc::{self, Sender, UnboundedSender}; use tokio::time::{interval, Duration, MissedTickBehavior}; use wicketd_client::types::{ - AbortUpdateOptions, ClearUpdateStateOptions, GetInventoryParams, - GetInventoryResponse, GetLocationResponse, IgnitionCommand, SpIdentifier, - SpType, StartUpdateOptions, StartUpdateParams, + AbortUpdateOptions, ClearUpdateStateOptions, ClearUpdateStateParams, + GetInventoryParams, GetInventoryResponse, GetLocationResponse, + IgnitionCommand, SpIdentifier, SpType, StartUpdateOptions, + StartUpdateParams, }; use crate::events::EventReportMap; @@ -229,14 +230,15 @@ impl WicketdManager { tokio::spawn(async move { let update_client = create_wicketd_client(&log, addr, WICKETD_TIMEOUT); - let sp: SpIdentifier = component_id.into(); - let response = match update_client - .post_clear_update_state(sp.type_, sp.slot, &options) - .await - { - Ok(_) => Ok(()), - Err(error) => Err(error.to_string()), + let params = ClearUpdateStateParams { + targets: vec![component_id.into()], + options, }; + let response = + match update_client.post_clear_update_state(¶ms).await { + Ok(_) => Ok(()), + Err(error) => Err(error.to_string()), + }; slog::info!( log, diff --git a/wicketd/src/http_entrypoints.rs b/wicketd/src/http_entrypoints.rs index be0f681601..d6cb6ebd6d 100644 --- a/wicketd/src/http_entrypoints.rs +++ b/wicketd/src/http_entrypoints.rs @@ -708,6 +708,15 @@ pub(crate) enum UpdateSimulatedResult { Failure, } +#[derive(Clone, Debug, JsonSchema, Deserialize)] +pub(crate) struct ClearUpdateStateParams { + /// The SP identifiers to clear the update state for. Must be non-empty. + pub(crate) targets: BTreeSet, + + /// Options for clearing update state + pub(crate) options: ClearUpdateStateOptions, +} + #[derive(Clone, Debug, JsonSchema, Deserialize)] pub(crate) struct ClearUpdateStateOptions { /// If passed in, fails the clear update state operation with a simulated @@ -715,6 +724,15 @@ pub(crate) struct ClearUpdateStateOptions { pub(crate) test_error: Option, } +#[derive(Clone, Debug, Default, JsonSchema, Serialize)] +pub(crate) struct ClearUpdateStateResponse { + /// The SPs for which update data was cleared. + pub(crate) cleared: BTreeSet, + + /// The SPs that had no update state to clear. + pub(crate) no_update_data: BTreeSet, +} + #[derive(Clone, Debug, JsonSchema, Deserialize)] pub(crate) struct AbortUpdateOptions { /// The message to abort the update with. @@ -1080,25 +1098,31 @@ async fn post_abort_update( /// Use this to clear update state after a failed update. #[endpoint { method = POST, - path = "/clear-update-state/{type}/{slot}", + path = "/clear-update-state", }] async fn post_clear_update_state( rqctx: RequestContext, - target: Path, - opts: TypedBody, -) -> Result { + params: TypedBody, +) -> Result, HttpError> { let log = &rqctx.log; - let target = target.into_inner(); + let rqctx = rqctx.context(); + let params = params.into_inner(); - let opts = opts.into_inner(); - if let Some(test_error) = opts.test_error { + if params.targets.is_empty() { + return Err(HttpError::for_bad_request( + None, + "No targets specified".into(), + )); + } + + if let Some(test_error) = params.options.test_error { return Err(test_error .into_http_error(log, "clearing update state") .await); } - match rqctx.context().update_tracker.clear_update_state(target).await { - Ok(()) => Ok(HttpResponseUpdatedNoContent {}), + match rqctx.update_tracker.clear_update_state(params.targets).await { + Ok(response) => Ok(HttpResponseOk(response)), Err(err) => Err(err.to_http_error()), } } diff --git a/wicketd/src/update_tracker.rs b/wicketd/src/update_tracker.rs index bd8e187fe9..368579fd55 100644 --- a/wicketd/src/update_tracker.rs +++ b/wicketd/src/update_tracker.rs @@ -8,6 +8,7 @@ use crate::artifacts::ArtifactIdData; use crate::artifacts::UpdatePlan; use crate::artifacts::WicketdArtifactStore; use crate::helpers::sps_to_string; +use crate::http_entrypoints::ClearUpdateStateResponse; use crate::http_entrypoints::GetArtifactsAndEventReportsResponse; use crate::http_entrypoints::StartUpdateOptions; use crate::http_entrypoints::UpdateSimulatedResult; @@ -184,10 +185,10 @@ impl UpdateTracker { pub(crate) async fn clear_update_state( &self, - sp: SpIdentifier, - ) -> Result<(), ClearUpdateStateError> { + sps: BTreeSet, + ) -> Result { let mut update_data = self.sp_update_data.lock().await; - update_data.clear_update_state(sp) + update_data.clear_update_state(&sps) } pub(crate) async fn abort_update( @@ -609,19 +610,38 @@ impl UpdateTrackerData { fn clear_update_state( &mut self, - sp: SpIdentifier, - ) -> Result<(), ClearUpdateStateError> { - // Is an update currently running? If so, then reject the request. - let is_running = self - .sp_update_data - .get(&sp) - .map_or(false, |update_data| !update_data.task.is_finished()); - if is_running { - return Err(ClearUpdateStateError::UpdateInProgress); + sps: &BTreeSet, + ) -> Result { + // Are any updates currently running? If so, then reject the request. + let in_progress_updates = sps + .iter() + .filter_map(|sp| { + self.sp_update_data + .get(sp) + .map_or(false, |update_data| { + !update_data.task.is_finished() + }) + .then(|| *sp) + }) + .collect::>(); + + if !in_progress_updates.is_empty() { + return Err(ClearUpdateStateError::UpdateInProgress( + in_progress_updates, + )); } - self.sp_update_data.remove(&sp); - Ok(()) + let mut resp = ClearUpdateStateResponse::default(); + + for sp in sps { + if self.sp_update_data.remove(sp).is_some() { + resp.cleared.insert(*sp); + } else { + resp.no_update_data.insert(*sp); + } + } + + Ok(resp) } async fn abort_update( @@ -695,8 +715,8 @@ pub enum StartUpdateError { #[derive(Debug, Clone, Error, Eq, PartialEq)] pub enum ClearUpdateStateError { - #[error("target is currently being updated")] - UpdateInProgress, + #[error("targets are currently being updated: {}", sps_to_string(.0))] + UpdateInProgress(Vec), } impl ClearUpdateStateError { @@ -704,7 +724,7 @@ impl ClearUpdateStateError { let message = DisplayErrorChain::new(self).to_string(); match self { - ClearUpdateStateError::UpdateInProgress => { + ClearUpdateStateError::UpdateInProgress(_) => { HttpError::for_bad_request(None, message) } }