Skip to content

Commit d0864a0

Browse files
committed
[nexus] allow reconfiguring auto-restart policies
This commit extends the `instance-reconfigure` API endpoint added in #6585 to also allow setting instance auto-restart policies (as added in #6503). I've also added the actual auto-restart policy to the external API instance view, along with the boolean `auto_restart_enabled` added in #6503. This way, it's possible to change just the boot disk by providing the current auto-restart policy in an instance POST.
1 parent 5ef07cf commit d0864a0

File tree

7 files changed

+96
-12
lines changed

7 files changed

+96
-12
lines changed

common/src/api/external/mod.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,6 +1215,20 @@ pub struct InstanceAutoRestartStatus {
12151215
#[serde(rename = "auto_restart_enabled")]
12161216
pub enabled: bool,
12171217

1218+
/// The auto-restart policy configured for this instance, or `None` if no
1219+
/// explicit policy is configured.
1220+
///
1221+
/// If this is not present, then this instance uses the default auto-restart
1222+
/// policy, which may or may not allow it to be restarted. The
1223+
/// `auto_restart_enabled` field indicates whether the instance will be
1224+
/// automatically restarted.
1225+
//
1226+
// Rename this field, as the struct is `#[serde(flatten)]`ed into the
1227+
// `Instance` type, and we would like the field to be prefixed with
1228+
// `auto_restart`.
1229+
#[serde(rename = "auto_restart_policy")]
1230+
pub policy: Option<InstanceAutoRestartPolicy>,
1231+
12181232
/// The time at which the auto-restart cooldown period for this instance
12191233
/// completes, permitting it to be automatically restarted again. If the
12201234
/// instance enters the `Failed` state, it will not be restarted until after

nexus/db-queries/src/db/datastore/instance.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -223,16 +223,23 @@ impl From<InstanceAndActiveVmm> for external::Instance {
223223
},
224224
);
225225

226-
let policy = value
227-
.instance
228-
.auto_restart
229-
.policy
230-
.unwrap_or(InstanceAutoRestart::DEFAULT_POLICY);
231-
let enabled = match policy {
226+
let policy = value.instance.auto_restart.policy;
227+
// The active policy for this instance --- either its configured
228+
// policy or the default. We report the configured policy as the
229+
// instance's policy, but we must use this to determine whether it
230+
// will be auto-restarted, since it may have no configured policy.
231+
let active_policy =
232+
policy.unwrap_or(InstanceAutoRestart::DEFAULT_POLICY);
233+
234+
let enabled = match active_policy {
232235
InstanceAutoRestartPolicy::Never => false,
233236
InstanceAutoRestartPolicy::BestEffort => true,
234237
};
235-
external::InstanceAutoRestartStatus { enabled, cooldown_expiration }
238+
external::InstanceAutoRestartStatus {
239+
enabled,
240+
policy: policy.map(Into::into),
241+
cooldown_expiration,
242+
}
236243
};
237244

238245
Self {

nexus/src/app/instance.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,9 @@ impl super::Nexus {
330330
None => None,
331331
};
332332

333-
let update = InstanceUpdate { boot_disk_id };
333+
let auto_restart_policy = params.auto_restart_policy.map(Into::into);
334+
335+
let update = InstanceUpdate { boot_disk_id, auto_restart_policy };
334336
self.datastore()
335337
.instance_reconfigure(opctx, &authz_instance, update)
336338
.await

nexus/tests/integration_tests/endpoints.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,10 @@ pub static DEMO_INSTANCE_CREATE: Lazy<params::InstanceCreate> =
434434
auto_restart_policy: Default::default(),
435435
});
436436
pub static DEMO_INSTANCE_UPDATE: Lazy<params::InstanceUpdate> =
437-
Lazy::new(|| params::InstanceUpdate { boot_disk: None });
437+
Lazy::new(|| params::InstanceUpdate {
438+
boot_disk: None,
439+
auto_restart_policy: None,
440+
});
438441

439442
// The instance needs a network interface, too.
440443
pub static DEMO_INSTANCE_NIC_NAME: Lazy<Name> =

nexus/tests/integration_tests/instances.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4161,7 +4161,10 @@ async fn test_cannot_detach_boot_disk(cptestctx: &ControlPlaneTestContext) {
41614161

41624162
let builder =
41634163
RequestBuilder::new(client, http::Method::PUT, &url_instance_update)
4164-
.body(Some(&params::InstanceUpdate { boot_disk: None }))
4164+
.body(Some(&params::InstanceUpdate {
4165+
boot_disk: None,
4166+
auto_restart_policy: None,
4167+
}))
41654168
.expect_status(Some(http::StatusCode::OK));
41664169
let response = NexusRequest::new(builder)
41674170
.authn_as(AuthnMode::PrivilegedUser)
@@ -4238,7 +4241,10 @@ async fn test_updating_running_instance_is_conflict(
42384241

42394242
let builder =
42404243
RequestBuilder::new(client, http::Method::PUT, &url_instance_update)
4241-
.body(Some(&params::InstanceUpdate { boot_disk: None }))
4244+
.body(Some(&params::InstanceUpdate {
4245+
boot_disk: None,
4246+
auto_restart_policy: None,
4247+
}))
42424248
.expect_status(Some(http::StatusCode::CONFLICT));
42434249

42444250
let response = NexusRequest::new(builder)
@@ -4264,7 +4270,10 @@ async fn test_updating_missing_instance_is_not_found(
42644270

42654271
let builder =
42664272
RequestBuilder::new(client, http::Method::PUT, &url_instance_update)
4267-
.body(Some(&params::InstanceUpdate { boot_disk: None }))
4273+
.body(Some(&params::InstanceUpdate {
4274+
boot_disk: None,
4275+
auto_restart_policy: None,
4276+
}))
42684277
.expect_status(Some(http::StatusCode::NOT_FOUND));
42694278

42704279
let response = NexusRequest::new(builder)
@@ -4353,6 +4362,7 @@ async fn test_boot_disk_can_be_changed(cptestctx: &ControlPlaneTestContext) {
43534362
RequestBuilder::new(client, http::Method::PUT, &url_instance_update)
43544363
.body(Some(&params::InstanceUpdate {
43554364
boot_disk: Some(disks[1].identity.id.into()),
4365+
auto_restart_policy: None,
43564366
}))
43574367
.expect_status(Some(http::StatusCode::OK));
43584368

@@ -4424,6 +4434,7 @@ async fn test_boot_disk_must_be_attached(cptestctx: &ControlPlaneTestContext) {
44244434
RequestBuilder::new(client, http::Method::PUT, &url_instance_update)
44254435
.body(Some(&params::InstanceUpdate {
44264436
boot_disk: Some(disks[0].identity.id.into()),
4437+
auto_restart_policy: None,
44274438
}))
44284439
.expect_status(Some(http::StatusCode::CONFLICT));
44294440
let response = NexusRequest::new(builder)
@@ -4459,6 +4470,7 @@ async fn test_boot_disk_must_be_attached(cptestctx: &ControlPlaneTestContext) {
44594470
RequestBuilder::new(client, http::Method::PUT, &url_instance_update)
44604471
.body(Some(&params::InstanceUpdate {
44614472
boot_disk: Some(disks[0].identity.id.into()),
4473+
auto_restart_policy: None,
44624474
}))
44634475
.expect_status(Some(http::StatusCode::OK));
44644476
let response = NexusRequest::new(builder)

openapi/nexus-internal.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3382,6 +3382,15 @@
33823382
"description": "`true` if this instance's auto-restart policy will permit the control plane to automatically restart it if it enters the `Failed` state.",
33833383
"type": "boolean"
33843384
},
3385+
"auto_restart_policy": {
3386+
"nullable": true,
3387+
"description": "The auto-restart policy configured for this instance, or `None` if no explicit policy is configured.\n\nIf this is not present, then this instance uses the default auto-restart policy, which may or may not allow it to be restarted. The `auto_restart_enabled` field indicates whether the instance will be automatically restarted.",
3388+
"allOf": [
3389+
{
3390+
"$ref": "#/components/schemas/InstanceAutoRestartPolicy"
3391+
}
3392+
]
3393+
},
33853394
"boot_disk_id": {
33863395
"nullable": true,
33873396
"description": "the ID of the disk used to boot this Instance, if a specific one is assigned.",
@@ -3469,6 +3478,25 @@
34693478
"time_run_state_updated"
34703479
]
34713480
},
3481+
"InstanceAutoRestartPolicy": {
3482+
"description": "A policy determining when an instance should be automatically restarted by the control plane.",
3483+
"oneOf": [
3484+
{
3485+
"description": "The instance should not be automatically restarted by the control plane if it fails.",
3486+
"type": "string",
3487+
"enum": [
3488+
"never"
3489+
]
3490+
},
3491+
{
3492+
"description": "If this instance is running and unexpectedly fails (e.g. due to a host software crash or unexpected host reboot), the control plane will make a best-effort attempt to restart it. The control plane may choose not to restart the instance to preserve the overall availability of the system.",
3493+
"type": "string",
3494+
"enum": [
3495+
"best_effort"
3496+
]
3497+
}
3498+
]
3499+
},
34723500
"InstanceCpuCount": {
34733501
"description": "The number of CPUs in an Instance",
34743502
"type": "integer",

openapi/nexus.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15156,6 +15156,15 @@
1515615156
"description": "`true` if this instance's auto-restart policy will permit the control plane to automatically restart it if it enters the `Failed` state.",
1515715157
"type": "boolean"
1515815158
},
15159+
"auto_restart_policy": {
15160+
"nullable": true,
15161+
"description": "The auto-restart policy configured for this instance, or `None` if no explicit policy is configured.\n\nIf this is not present, then this instance uses the default auto-restart policy, which may or may not allow it to be restarted. The `auto_restart_enabled` field indicates whether the instance will be automatically restarted.",
15162+
"allOf": [
15163+
{
15164+
"$ref": "#/components/schemas/InstanceAutoRestartPolicy"
15165+
}
15166+
]
15167+
},
1515915168
"boot_disk_id": {
1516015169
"nullable": true,
1516115170
"description": "the ID of the disk used to boot this Instance, if a specific one is assigned.",
@@ -15807,6 +15816,15 @@
1580715816
"description": "Parameters of an `Instance` that can be reconfigured after creation.",
1580815817
"type": "object",
1580915818
"properties": {
15819+
"auto_restart_policy": {
15820+
"nullable": true,
15821+
"description": "The auto-restart policy for this instance.\n\nIf not provided, unset the instance's auto-restart policy.",
15822+
"allOf": [
15823+
{
15824+
"$ref": "#/components/schemas/InstanceAutoRestartPolicy"
15825+
}
15826+
]
15827+
},
1581015828
"boot_disk": {
1581115829
"nullable": true,
1581215830
"description": "Name or ID of the disk the instance should be instructed to boot from.\n\nIf not provided, unset the instance's boot disk.",

0 commit comments

Comments
 (0)