Skip to content

Commit 777ee64

Browse files
committed
sic_create_disk_requests
1 parent 549f8ce commit 777ee64

File tree

5 files changed

+78
-12
lines changed

5 files changed

+78
-12
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

nexus/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ thiserror = "1.0"
5151
toml = "0.5.6"
5252
tough = { version = "0.12", features = [ "http" ] }
5353
usdt = "0.3.1"
54+
propolis-client = { git = "https://github.com/oxidecomputer/propolis", rev = "832a86afce308d3210685af987ace1ba74c2ecd6" }
5455

5556
[dependencies.api_identity]
5657
path = "../api_identity"

nexus/src/external_api/params.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,10 @@ pub enum InstanceDiskAttachment {
136136
Attach(InstanceDiskAttach),
137137
}
138138

139-
#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, Default)]
139+
#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)]
140140
pub struct InstanceDiskAttach {
141-
disks: Vec<Uuid>,
141+
/// A disk name to attach
142+
pub disk: Name,
142143
}
143144

144145
/**

nexus/src/sagas.rs

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,12 @@ pub fn saga_instance_create() -> SagaTemplate<SagaInstanceCreate> {
188188
new_action_noop_undo(sic_create_network_interfaces),
189189
);
190190

191+
template_builder.append(
192+
"disk_requests",
193+
"CreateDiskRequests",
194+
new_action_noop_undo(sic_create_disk_requests),
195+
);
196+
191197
template_builder.append(
192198
"initial_runtime",
193199
"CreateInstanceRecord",
@@ -455,6 +461,55 @@ async fn sic_create_network_interfaces_undo(
455461
Ok(())
456462
}
457463

464+
async fn sic_create_disk_requests(
465+
sagactx: ActionContext<SagaInstanceCreate>,
466+
) -> Result<Vec<sled_agent_client::types::DiskRequest>, ActionError> {
467+
let osagactx = sagactx.user_data();
468+
let datastore = osagactx.datastore();
469+
let saga_params = sagactx.saga_params();
470+
let opctx = OpContext::for_saga_action(&sagactx, &saga_params.serialized_authn);
471+
472+
let authz_project = datastore
473+
.project_lookup_by_id(saga_params.project_id)
474+
.await
475+
.map_err(ActionError::action_failed)?;
476+
477+
let saga_disks = &sagactx.saga_params().create_params.disks;
478+
479+
let mut reqs = Vec::with_capacity(saga_disks.len());
480+
481+
for (i, disk) in saga_disks.iter().enumerate() {
482+
match disk {
483+
params::InstanceDiskAttachment::Create(_) => {
484+
// TODO attach disk created in a previous step
485+
todo!();
486+
},
487+
params::InstanceDiskAttachment::Attach(instance_disk_attach) => {
488+
let disk_name = &instance_disk_attach.disk;
489+
let (_, disk) = datastore.disk_fetch(&opctx, &authz_project, &db::model::Name::from(disk_name.clone()))
490+
.await
491+
.map_err(ActionError::action_failed)?;
492+
493+
let volume = datastore.volume_get(disk.id()).await.map_err(ActionError::action_failed)?;
494+
495+
reqs.push(sled_agent_client::types::DiskRequest {
496+
name: disk.name().to_string(),
497+
slot: sled_agent_client::types::Slot(i as u8),
498+
// TODO offer ability to attach read-only?
499+
read_only: false,
500+
device: "nvme".to_string(),
501+
// TODO Nexus has to send the highest gen of the volume + 1
502+
gen: 0,
503+
volume_construction_request: serde_json::from_str(&volume.data())
504+
.map_err(|e| e.to_string()).map_err(ActionError::action_failed)?,
505+
});
506+
}
507+
}
508+
}
509+
510+
Ok(reqs)
511+
}
512+
458513
async fn sic_create_instance_record(
459514
sagactx: ActionContext<SagaInstanceCreate>,
460515
) -> Result<InstanceHardware, ActionError> {
@@ -466,6 +521,8 @@ async fn sic_create_instance_record(
466521
let nics = sagactx
467522
.lookup::<Option<Vec<NetworkInterface>>>("network_interfaces")?
468523
.unwrap_or_default();
524+
let disks = sagactx
525+
.lookup::<Vec<sled_agent_client::types::DiskRequest>>("disk_requests")?;
469526

470527
let runtime = InstanceRuntimeState {
471528
run_state: InstanceState::Creating,
@@ -498,9 +555,14 @@ async fn sic_create_instance_record(
498555
Ok(InstanceHardware {
499556
runtime: instance.runtime().clone().into(),
500557
nics,
501-
// TODO disks are currently only attached in instance_set_runtime, but
502-
// InstanceCreate could grow to request disks too.
503-
disks: vec![],
558+
disks: disks.iter().map(|x| propolis_client::api::DiskRequest {
559+
name: x.name.clone(),
560+
slot: propolis_client::api::Slot(x.slot.0),
561+
read_only: x.read_only,
562+
device: x.device.clone(),
563+
gen: x.gen,
564+
volume_construction_request: serde_json::from_str(&serde_json::to_string(&x.volume_construction_request).unwrap()).unwrap(),
565+
}).collect(),
504566
})
505567
}
506568

openapi/nexus.json

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4414,12 +4414,13 @@
44144414
"description": "During instance creation, attach this disk",
44154415
"type": "object",
44164416
"properties": {
4417-
"disks": {
4418-
"type": "array",
4419-
"items": {
4420-
"type": "string",
4421-
"format": "uuid"
4422-
}
4417+
"disk": {
4418+
"description": "A disk name to attach",
4419+
"allOf": [
4420+
{
4421+
"$ref": "#/components/schemas/Name"
4422+
}
4423+
]
44234424
},
44244425
"type": {
44254426
"type": "string",
@@ -4429,7 +4430,7 @@
44294430
}
44304431
},
44314432
"required": [
4432-
"disks",
4433+
"disk",
44334434
"type"
44344435
]
44354436
}

0 commit comments

Comments
 (0)