Skip to content

Commit feff3c5

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 c90f617 commit feff3c5

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
@@ -4133,7 +4133,10 @@ async fn test_cannot_detach_boot_disk(cptestctx: &ControlPlaneTestContext) {
41334133

41344134
let builder =
41354135
RequestBuilder::new(client, http::Method::PUT, &url_instance_update)
4136-
.body(Some(&params::InstanceUpdate { boot_disk: None }))
4136+
.body(Some(&params::InstanceUpdate {
4137+
boot_disk: None,
4138+
auto_restart_policy: None,
4139+
}))
41374140
.expect_status(Some(http::StatusCode::OK));
41384141
let response = NexusRequest::new(builder)
41394142
.authn_as(AuthnMode::PrivilegedUser)
@@ -4210,7 +4213,10 @@ async fn test_updating_running_instance_is_conflict(
42104213

42114214
let builder =
42124215
RequestBuilder::new(client, http::Method::PUT, &url_instance_update)
4213-
.body(Some(&params::InstanceUpdate { boot_disk: None }))
4216+
.body(Some(&params::InstanceUpdate {
4217+
boot_disk: None,
4218+
auto_restart_policy: None,
4219+
}))
42144220
.expect_status(Some(http::StatusCode::CONFLICT));
42154221

42164222
let response = NexusRequest::new(builder)
@@ -4236,7 +4242,10 @@ async fn test_updating_missing_instance_is_not_found(
42364242

42374243
let builder =
42384244
RequestBuilder::new(client, http::Method::PUT, &url_instance_update)
4239-
.body(Some(&params::InstanceUpdate { boot_disk: None }))
4245+
.body(Some(&params::InstanceUpdate {
4246+
boot_disk: None,
4247+
auto_restart_policy: None,
4248+
}))
42404249
.expect_status(Some(http::StatusCode::NOT_FOUND));
42414250

42424251
let response = NexusRequest::new(builder)
@@ -4325,6 +4334,7 @@ async fn test_boot_disk_can_be_changed(cptestctx: &ControlPlaneTestContext) {
43254334
RequestBuilder::new(client, http::Method::PUT, &url_instance_update)
43264335
.body(Some(&params::InstanceUpdate {
43274336
boot_disk: Some(disks[1].identity.id.into()),
4337+
auto_restart_policy: None,
43284338
}))
43294339
.expect_status(Some(http::StatusCode::OK));
43304340

@@ -4396,6 +4406,7 @@ async fn test_boot_disk_must_be_attached(cptestctx: &ControlPlaneTestContext) {
43964406
RequestBuilder::new(client, http::Method::PUT, &url_instance_update)
43974407
.body(Some(&params::InstanceUpdate {
43984408
boot_disk: Some(disks[0].identity.id.into()),
4409+
auto_restart_policy: None,
43994410
}))
44004411
.expect_status(Some(http::StatusCode::CONFLICT));
44014412
let response = NexusRequest::new(builder)
@@ -4431,6 +4442,7 @@ async fn test_boot_disk_must_be_attached(cptestctx: &ControlPlaneTestContext) {
44314442
RequestBuilder::new(client, http::Method::PUT, &url_instance_update)
44324443
.body(Some(&params::InstanceUpdate {
44334444
boot_disk: Some(disks[0].identity.id.into()),
4445+
auto_restart_policy: None,
44344446
}))
44354447
.expect_status(Some(http::StatusCode::OK));
44364448
let response = NexusRequest::new(builder)

openapi/nexus-internal.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3305,6 +3305,15 @@
33053305
"description": "`true` if this instance's auto-restart policy will permit the control plane to automatically restart it if it enters the `Failed` state.",
33063306
"type": "boolean"
33073307
},
3308+
"auto_restart_policy": {
3309+
"nullable": true,
3310+
"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.",
3311+
"allOf": [
3312+
{
3313+
"$ref": "#/components/schemas/InstanceAutoRestartPolicy"
3314+
}
3315+
]
3316+
},
33083317
"boot_disk_id": {
33093318
"nullable": true,
33103319
"description": "the ID of the disk used to boot this Instance, if a specific one is assigned.",
@@ -3392,6 +3401,25 @@
33923401
"time_run_state_updated"
33933402
]
33943403
},
3404+
"InstanceAutoRestartPolicy": {
3405+
"description": "A policy determining when an instance should be automatically restarted by the control plane.",
3406+
"oneOf": [
3407+
{
3408+
"description": "The instance should not be automatically restarted by the control plane if it fails.",
3409+
"type": "string",
3410+
"enum": [
3411+
"never"
3412+
]
3413+
},
3414+
{
3415+
"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.",
3416+
"type": "string",
3417+
"enum": [
3418+
"best_effort"
3419+
]
3420+
}
3421+
]
3422+
},
33953423
"InstanceCpuCount": {
33963424
"description": "The number of CPUs in an Instance",
33973425
"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.",
@@ -15792,6 +15801,15 @@
1579215801
"description": "Parameters of an `Instance` that can be reconfigured after creation.",
1579315802
"type": "object",
1579415803
"properties": {
15804+
"auto_restart_policy": {
15805+
"nullable": true,
15806+
"description": "The auto-restart policy for this instance.\n\nIf not provided, unset the instance's auto-restart policy.",
15807+
"allOf": [
15808+
{
15809+
"$ref": "#/components/schemas/InstanceAutoRestartPolicy"
15810+
}
15811+
]
15812+
},
1579515813
"boot_disk": {
1579615814
"nullable": true,
1579715815
"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)