mirror of
https://github.com/siderolabs/talos.git
synced 2025-10-01 10:41:30 +02:00
fix: order volume config by the requested size
This fixes an issue like that: * the system disk is say 10GiB * STATE is fixed 100 MiB always * EPHEMERAL is configured to be min 6 GiB, max 100 GiB As the EPHEMERAL/STATE provisioning order was not defined, EPHEMERAL might be created first, occupying whole disk and leaving no space left for STATE. Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
This commit is contained in:
parent
bc3039acdb
commit
61b1489a0f
3
.github/workflows/ci.yaml
vendored
3
.github/workflows/ci.yaml
vendored
@ -1,6 +1,6 @@
|
||||
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
|
||||
#
|
||||
# Generated on 2024-12-06T17:21:12Z by kres 1ebe796.
|
||||
# Generated on 2024-12-11T13:30:10Z by kres 8183c20.
|
||||
|
||||
name: default
|
||||
concurrency:
|
||||
@ -2074,6 +2074,7 @@ jobs:
|
||||
GITHUB_STEP_NAME: ${{ github.job}}-e2e-controlplane-port
|
||||
IMAGE_REGISTRY: registry.dev.siderolabs.io
|
||||
SHORT_INTEGRATION_TEST: "yes"
|
||||
WITH_CONFIG_PATCH: '@hack/test/patches/ephemeral-min-max.yaml'
|
||||
WITH_CONTROL_PLANE_PORT: "443"
|
||||
run: |
|
||||
sudo -E make e2e-qemu
|
||||
|
@ -1,6 +1,6 @@
|
||||
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
|
||||
#
|
||||
# Generated on 2024-11-28T13:53:18Z by kres 232fe63.
|
||||
# Generated on 2024-12-11T13:30:10Z by kres 8183c20.
|
||||
|
||||
name: integration-misc-0-cron
|
||||
concurrency:
|
||||
@ -99,6 +99,7 @@ jobs:
|
||||
GITHUB_STEP_NAME: ${{ github.job}}-e2e-controlplane-port
|
||||
IMAGE_REGISTRY: registry.dev.siderolabs.io
|
||||
SHORT_INTEGRATION_TEST: "yes"
|
||||
WITH_CONFIG_PATCH: '@hack/test/patches/ephemeral-min-max.yaml'
|
||||
WITH_CONTROL_PLANE_PORT: "443"
|
||||
run: |
|
||||
sudo -E make e2e-qemu
|
||||
|
@ -683,6 +683,7 @@ spec:
|
||||
SHORT_INTEGRATION_TEST: yes
|
||||
WITH_CONTROL_PLANE_PORT: 443
|
||||
IMAGE_REGISTRY: registry.dev.siderolabs.io
|
||||
WITH_CONFIG_PATCH: "@hack/test/patches/ephemeral-min-max.yaml"
|
||||
- name: save-talos-logs
|
||||
conditions:
|
||||
- always
|
||||
|
8
hack/test/patches/ephemeral-min-max.yaml
Normal file
8
hack/test/patches/ephemeral-min-max.yaml
Normal file
@ -0,0 +1,8 @@
|
||||
apiVersion: v1alpha1
|
||||
kind: VolumeConfig
|
||||
name: EPHEMERAL
|
||||
provisioning:
|
||||
diskSelector:
|
||||
match: system_disk
|
||||
minSize: 4GB
|
||||
maxSize: 100GB
|
@ -8,6 +8,7 @@ package volumes
|
||||
import (
|
||||
"cmp"
|
||||
"context"
|
||||
"math"
|
||||
|
||||
"github.com/siderolabs/gen/optional"
|
||||
|
||||
@ -18,11 +19,29 @@ import (
|
||||
|
||||
// CompareVolumeConfigs compares two volume configs in the proposed order of provisioning.
|
||||
func CompareVolumeConfigs(a, b *block.VolumeConfig) int {
|
||||
// first, sort by wave, smaller wave first
|
||||
if c := cmp.Compare(a.TypedSpec().Provisioning.Wave, b.TypedSpec().Provisioning.Wave); c != 0 {
|
||||
return c
|
||||
}
|
||||
|
||||
return cmpBool(a.TypedSpec().Provisioning.PartitionSpec.Grow, b.TypedSpec().Provisioning.PartitionSpec.Grow)
|
||||
// prefer partitions which do not grow, as growing partitions may consume space needed by other partitions
|
||||
if c := cmpBool(a.TypedSpec().Provisioning.PartitionSpec.Grow, b.TypedSpec().Provisioning.PartitionSpec.Grow); c != 0 {
|
||||
return c
|
||||
}
|
||||
|
||||
// prefer partitions with smaller sizes first
|
||||
// e.g.: for a disk of size 1GiB, and following config with min-max requested sizes:
|
||||
// 1. 100MiB - 200MiB
|
||||
// 2. 300MiB - 2GiB
|
||||
//
|
||||
// if the order is 2-1, the second partition will grow to full disk size and will leave no space for the first partition,
|
||||
// but if the order is 1-2, partition sizes will 200MiB and 800MiB respectively.
|
||||
//
|
||||
// we compare only max size, as it affects the resulting size of the partition
|
||||
desiredSizeA := cmp.Or(a.TypedSpec().Provisioning.PartitionSpec.MaxSize, math.MaxUint64)
|
||||
desiredSizeB := cmp.Or(b.TypedSpec().Provisioning.PartitionSpec.MaxSize, math.MaxUint64)
|
||||
|
||||
return cmp.Compare(desiredSizeA, desiredSizeB)
|
||||
}
|
||||
|
||||
func cmpBool(a, b bool) int {
|
||||
|
@ -0,0 +1,132 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package volumes_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/controllers/block/internal/volumes"
|
||||
"github.com/siderolabs/talos/pkg/machinery/resources/block"
|
||||
)
|
||||
|
||||
func TestCompareVolumeConfigs(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
|
||||
a *block.VolumeConfigSpec
|
||||
b *block.VolumeConfigSpec
|
||||
|
||||
expected int
|
||||
}{
|
||||
{
|
||||
name: "different wave",
|
||||
|
||||
a: &block.VolumeConfigSpec{
|
||||
Provisioning: block.ProvisioningSpec{
|
||||
Wave: block.WaveSystemDisk,
|
||||
},
|
||||
},
|
||||
b: &block.VolumeConfigSpec{
|
||||
Provisioning: block.ProvisioningSpec{
|
||||
Wave: block.WaveUserDisks,
|
||||
},
|
||||
},
|
||||
|
||||
expected: -1,
|
||||
},
|
||||
{
|
||||
name: "prefer grow",
|
||||
|
||||
a: &block.VolumeConfigSpec{
|
||||
Provisioning: block.ProvisioningSpec{
|
||||
Wave: block.WaveSystemDisk,
|
||||
PartitionSpec: block.PartitionSpec{
|
||||
Grow: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
b: &block.VolumeConfigSpec{
|
||||
Provisioning: block.ProvisioningSpec{
|
||||
Wave: block.WaveSystemDisk,
|
||||
PartitionSpec: block.PartitionSpec{
|
||||
Grow: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
expected: 1,
|
||||
},
|
||||
{
|
||||
name: "prefer smaller size",
|
||||
|
||||
a: &block.VolumeConfigSpec{
|
||||
Provisioning: block.ProvisioningSpec{
|
||||
Wave: block.WaveSystemDisk,
|
||||
PartitionSpec: block.PartitionSpec{
|
||||
Grow: false,
|
||||
MinSize: 100,
|
||||
MaxSize: 200,
|
||||
},
|
||||
},
|
||||
},
|
||||
b: &block.VolumeConfigSpec{
|
||||
Provisioning: block.ProvisioningSpec{
|
||||
Wave: block.WaveSystemDisk,
|
||||
PartitionSpec: block.PartitionSpec{
|
||||
Grow: false,
|
||||
MinSize: 150,
|
||||
MaxSize: 1000,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
expected: -1,
|
||||
},
|
||||
{
|
||||
name: "prefer max size",
|
||||
|
||||
a: &block.VolumeConfigSpec{
|
||||
Provisioning: block.ProvisioningSpec{
|
||||
Wave: block.WaveSystemDisk,
|
||||
PartitionSpec: block.PartitionSpec{
|
||||
Grow: false,
|
||||
MinSize: 100,
|
||||
MaxSize: 200,
|
||||
},
|
||||
},
|
||||
},
|
||||
b: &block.VolumeConfigSpec{
|
||||
Provisioning: block.ProvisioningSpec{
|
||||
Wave: block.WaveSystemDisk,
|
||||
PartitionSpec: block.PartitionSpec{
|
||||
Grow: false,
|
||||
MinSize: 50,
|
||||
MaxSize: 0, // no limit
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
expected: -1,
|
||||
},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
resA := block.NewVolumeConfig(block.NamespaceName, "A")
|
||||
*resA.TypedSpec() = *test.a
|
||||
|
||||
resB := block.NewVolumeConfig(block.NamespaceName, "B")
|
||||
*resB.TypedSpec() = *test.b
|
||||
|
||||
actual := volumes.CompareVolumeConfigs(resA, resB)
|
||||
|
||||
assert.Equal(t, test.expected, actual)
|
||||
})
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user