Skip to content

Commit 3424aeb

Browse files
authored
supply real volume data to propolis (#771)
Instance creation now can specify that existing disks be attached to the instance (disk creation during instance creation is not yet implemented). There's a few important changes here. Nexus will instruct the sled agent to send volume construction requests when it ensures the instance, and therefore has to build these requests. This is done in sdc_regions_ensure as regions are allocated. sic_create_instance_record no longer returns the runtime of an instance, but the instance's name. Importantly, the instance creation saga now calls Nexus' instance_set_runtime instead of duplicating the logic to call instance_put. Nexus' instance_set_runtime will populate the InstanceHardware with NICs and disks. Nexus' disk_set_runtime now *optionally* calls the sled agent's disk_put if the instance is running already, otherwise the disk will be attached as part of the instance ensure by specifying volume requests. request_body_max_bytes had to be increased to 1M because the volume requests could be arbitrarily large (and eventually, the cloud init bytes will add to the body size too). Note: spawning an instance with this *will not work* unless the propolis zone has a valid static IPv6 address. This PR has grown enough that I think that work should be separate. This PR also sets the maximum number of disks that can be attached to an instance at 8.
1 parent 9a50adb commit 3424aeb

File tree

23 files changed

+1501
-126
lines changed

23 files changed

+1501
-126
lines changed

Cargo.lock

Lines changed: 258 additions & 31 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

common/src/api/external/error.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,12 @@ impl<T: ClientError> From<progenitor::progenitor_client::Error<T>> for Error {
296296
}
297297
}
298298

299+
impl From<serde_json::Error> for Error {
300+
fn from(e: serde_json::Error) -> Self {
301+
Error::internal_error(&e.to_string())
302+
}
303+
}
304+
299305
/// Like [`assert!`], except that instead of panicking, this function returns an
300306
/// `Err(Error::InternalError)` with an appropriate message if the given
301307
/// condition is not true.

nexus/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ path = "../rpaths"
1111
anyhow = "1.0"
1212
async-bb8-diesel = { git = "https://github.com/oxidecomputer/async-bb8-diesel", rev = "c849b717be" }
1313
async-trait = "0.1.51"
14+
base64 = "0.13.0"
1415
bb8 = "0.7.1"
1516
cookie = "0.16"
16-
crucible-agent-client = { git = "https://github.com/oxidecomputer/crucible", rev = "3e7e49eeb88fa8ad74375b0642aabd4224b1f2cb" }
17+
crucible-agent-client = { git = "https://github.com/oxidecomputer/crucible", rev = "945daedb88cefa790f1d994b3a038b8fa9ac514a" }
1718
# Tracking pending 2.0 version.
1819
diesel = { git = "https://github.com/diesel-rs/diesel", rev = "ce77c382", features = ["postgres", "r2d2", "chrono", "serde_json", "network-address", "uuid"] }
1920
futures = "0.3.21"

nexus/src/db/model.rs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,11 @@ impl Sled {
646646

647647
pub fn address(&self) -> SocketAddr {
648648
// TODO: avoid this unwrap
649-
SocketAddr::new(self.ip.ip(), u16::try_from(self.port).unwrap())
649+
self.address_with_port(u16::try_from(self.port).unwrap())
650+
}
651+
652+
pub fn address_with_port(&self, port: u16) -> SocketAddr {
653+
SocketAddr::new(self.ip.ip(), port)
650654
}
651655
}
652656

@@ -787,7 +791,11 @@ impl Dataset {
787791

788792
pub fn address(&self) -> SocketAddr {
789793
// TODO: avoid this unwrap
790-
SocketAddr::new(self.ip.ip(), u16::try_from(self.port).unwrap())
794+
self.address_with_port(u16::try_from(self.port).unwrap())
795+
}
796+
797+
pub fn address_with_port(&self, port: u16) -> SocketAddr {
798+
SocketAddr::new(self.ip.ip(), port)
791799
}
792800
}
793801

@@ -905,6 +913,10 @@ impl Volume {
905913
data,
906914
}
907915
}
916+
917+
pub fn data(&self) -> &str {
918+
&self.data
919+
}
908920
}
909921

910922
/// Describes an organization within the database.
@@ -1266,6 +1278,10 @@ impl Disk {
12661278
pub fn runtime(&self) -> DiskRuntimeState {
12671279
self.runtime_state.clone()
12681280
}
1281+
1282+
pub fn id(&self) -> Uuid {
1283+
self.identity.id
1284+
}
12691285
}
12701286

12711287
/// Conversion to the external API type.
@@ -1319,6 +1335,17 @@ impl DiskRuntimeState {
13191335
}
13201336
}
13211337

1338+
pub fn attach(self, instance_id: Uuid) -> Self {
1339+
Self {
1340+
disk_state: external::DiskState::Attached(instance_id)
1341+
.label()
1342+
.to_string(),
1343+
attach_instance_id: Some(instance_id),
1344+
gen: self.gen.next().into(),
1345+
time_updated: Utc::now(),
1346+
}
1347+
}
1348+
13221349
pub fn detach(self) -> Self {
13231350
Self {
13241351
disk_state: external::DiskState::Detached.label().to_string(),
@@ -1339,6 +1366,15 @@ impl DiskRuntimeState {
13391366
.unwrap(),
13401367
)
13411368
}
1369+
1370+
pub fn faulted(self) -> Self {
1371+
Self {
1372+
disk_state: external::DiskState::Faulted.label().to_string(),
1373+
attach_instance_id: None,
1374+
gen: self.gen.next().into(),
1375+
time_updated: Utc::now(),
1376+
}
1377+
}
13421378
}
13431379

13441380
/// Conversion from the internal API type.

nexus/src/external_api/params.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,23 @@ impl Default for InstanceNetworkInterfaceAttachment {
105105
}
106106
}
107107

108+
/// Describe the instance's disks at creation time
109+
#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)]
110+
#[serde(tag = "type", rename_all = "snake_case")]
111+
pub enum InstanceDiskAttachment {
112+
/// During instance creation, create and attach disks
113+
Create(DiskCreate),
114+
115+
/// During instance creation, attach this disk
116+
Attach(InstanceDiskAttach),
117+
}
118+
119+
#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)]
120+
pub struct InstanceDiskAttach {
121+
/// A disk name to attach
122+
pub disk: Name,
123+
}
124+
108125
/// Create-time parameters for an [`Instance`](omicron_common::api::external::Instance)
109126
#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)]
110127
pub struct InstanceCreate {
@@ -117,6 +134,10 @@ pub struct InstanceCreate {
117134
/// The network interfaces to be created for this instance.
118135
#[serde(default)]
119136
pub network_interfaces: InstanceNetworkInterfaceAttachment,
137+
138+
/// The disks to be created or attached for this instance.
139+
#[serde(default)]
140+
pub disks: Vec<InstanceDiskAttachment>,
120141
}
121142

122143
/// Migration parameters for an [`Instance`](omicron_common::api::external::Instance)

nexus/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// This Source Code Form is subject to the terms of the Mozilla Public
22
// License, v. 2.0. If a copy of the MPL was not distributed with this
33
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
#![feature(async_closure)]
45

56
//! Library interface to the Nexus, the heart of the control plane
67

0 commit comments

Comments
 (0)