Compare commits

..

1 Commits

Author SHA1 Message Date
Ben Duncan 56a9b51c3e fix(ec2): relaunch a direct-boot system guest without demanding a root volume 2026-11-04 08:04:21 +10:00
3 changed files with 32 additions and 7 deletions
@@ -18,7 +18,9 @@ import (
// reconcileStartVolumes drops the data volumes a claimed instance can no longer
// have, and fails the start when its boot volume is gone.
func (s *InstanceServiceImpl) reconcileStartVolumes(ctx context.Context, instance *vm.VM) error {
if s.metadata == nil {
// A direct-boot system guest boots from a kernel, not a root volume, and its
// one data volume, if any, is its own store rather than a customer's.
if s.metadata == nil || instance.DirectBoot {
return nil
}
@@ -123,3 +123,20 @@ func TestReconcileStartVolumes_ReattachesStillAvailableUnattachedVolume(t *testi
assert.Equal(t, []string{"vol-root", "vol-released"}, requestedNames(inst))
assert.Equal(t, []string{"vol-root", "vol-released"}, mappedNames(inst))
}
// ALB and SQS guests boot from a kernel with no root volume, so a start or a
// recovery must not demand one; an SQS store's data volume stays named.
func TestReconcileStartVolumes_DirectBootNeedsNoRootVolume(t *testing.T) {
t.Parallel()
svc := startVolumesService(t)
alb := &vm.VM{ID: "i-alb", AccountID: startVolumesAccount, Status: vm.StateStopped, DirectBoot: true,
Instance: &ec2.Instance{InstanceId: aws.String("i-alb")}}
require.NoError(t, svc.reconcileStartVolumes(context.Background(), alb))
sqs := &vm.VM{ID: "i-sqs", AccountID: startVolumesAccount, Status: vm.StateStopped, DirectBoot: true,
Instance: &ec2.Instance{InstanceId: aws.String("i-sqs")}}
sqs.EBSRequests.Requests = []viperblocklegacyv1.EBSRequest{{Name: "vol-store-gone", DeviceName: "/dev/vdb"}}
require.NoError(t, svc.reconcileStartVolumes(context.Background(), sqs))
assert.Equal(t, []string{"vol-store-gone"}, requestedNames(sqs), "a system store volume is never pruned")
}
+12 -6
View File
@@ -2302,8 +2302,8 @@ packages:
bowser@2.14.1:
resolution: {integrity: sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==}
brace-expansion@5.0.12:
resolution: {integrity: sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==}
brace-expansion@5.0.9:
resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==}
engines: {node: 20 || >=22}
braces@3.0.3:
@@ -3453,6 +3453,10 @@ packages:
resolution: {integrity: sha512-SO/3iYL5S3W57LLEniscOGPZgOqZUPCx6d3dB+52B80yJ0XstzsC/eV8gnA4tM3MHDrKz+OCFSLNjswdSC+/bA==}
engines: {node: '>=22'}
source-map-js@1.2.1:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
source-map-js@1.2.2:
resolution: {integrity: sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==}
engines: {node: '>=0.10.0'}
@@ -4982,7 +4986,7 @@ snapshots:
jiti: 2.7.0
lightningcss: 1.32.0
magic-string: 0.30.21
source-map-js: 1.2.2
source-map-js: 1.2.1
tailwindcss: 4.3.3
'@tailwindcss/oxide-android-arm64@4.3.3':
@@ -5562,7 +5566,7 @@ snapshots:
bowser@2.14.1: {}
brace-expansion@5.0.12:
brace-expansion@5.0.9:
dependencies:
balanced-match: 4.0.4
@@ -6185,7 +6189,7 @@ snapshots:
dependencies:
'@babel/parser': 7.29.8
'@babel/types': 7.29.8
source-map-js: 1.2.2
source-map-js: 1.2.1
markdown-table@3.0.4: {}
@@ -6546,7 +6550,7 @@ snapshots:
minimatch@10.2.6:
dependencies:
brace-expansion: 5.0.12
brace-expansion: 5.0.9
mlly@1.8.2:
dependencies:
@@ -6942,6 +6946,8 @@ snapshots:
ansi-styles: 6.2.3
is-fullwidth-code-point: 5.1.0
source-map-js@1.2.1: {}
source-map-js@1.2.2: {}
space-separated-tokens@2.0.2: {}