Skip to content

Commit 4f24ac7

Browse files
reederc42jwebster7
andauthored
Adds fixed overhead for LUKS volumes
--------- Co-authored-by: joe webster <[email protected]>
1 parent 2bf1d51 commit 4f24ac7

File tree

8 files changed

+199
-10
lines changed

8 files changed

+199
-10
lines changed

frontend/csi/controller_helpers/kubernetes/import.go

+7
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/netapp/trident/frontend/csi"
2020
. "github.com/netapp/trident/logging"
2121
"github.com/netapp/trident/storage"
22+
"github.com/netapp/trident/utils"
2223
"github.com/netapp/trident/utils/errors"
2324
)
2425

@@ -111,6 +112,12 @@ func (h *helper) ImportVolume(
111112

112113
dataSize := h.getDataSizeFromTotalSize(ctx, totalSize, snapshotReserve)
113114

115+
if luksAnnotation, ok := claim.GetObjectMeta().GetAnnotations()[AnnLUKSEncryption]; ok {
116+
if utils.ParseBool(luksAnnotation) {
117+
dataSize -= utils.LUKSMetadataSize
118+
}
119+
}
120+
114121
if claim.Spec.Resources.Requests == nil {
115122
claim.Spec.Resources.Requests = v1.ResourceList{}
116123
}

frontend/csi/utils_test.go

+27
Original file line numberDiff line numberDiff line change
@@ -465,3 +465,30 @@ func TestEnsureLUKSVolumePassphrase_NoCorrectPassphraseProvided(t *testing.T) {
465465
assert.Error(t, err)
466466
mockCtrl.Finish()
467467
}
468+
469+
func TestParseBool(t *testing.T) {
470+
tests := []struct {
471+
b string
472+
expected bool
473+
}{
474+
{
475+
b: "true",
476+
expected: true,
477+
},
478+
{
479+
b: "false",
480+
expected: false,
481+
},
482+
{
483+
b: "not a value",
484+
expected: false,
485+
},
486+
}
487+
488+
for _, test := range tests {
489+
t.Run(test.b, func(t *testing.T) {
490+
actual := utils.ParseBool(test.b)
491+
assert.Equal(t, test.expected, actual)
492+
})
493+
}
494+
}

storage_drivers/ontap/ontap_common.go

+45
Original file line numberDiff line numberDiff line change
@@ -3473,6 +3473,51 @@ func ConstructPoolForLabels(nameTemplate string, labels map[string]string) *stor
34733473
return pool
34743474
}
34753475

3476+
func subtractUintFromSizeString(size string, val uint64) (string, error) {
3477+
sizeBytesString, _ := utils.ConvertSizeToBytes(size)
3478+
sizeBytes, err := strconv.ParseUint(sizeBytesString, 10, 64)
3479+
if err != nil {
3480+
return "", fmt.Errorf("invalid size string: %v", err)
3481+
}
3482+
if val > sizeBytes {
3483+
return "", fmt.Errorf("right-hand term too large")
3484+
}
3485+
return strconv.FormatUint(sizeBytes-val, 10), nil
3486+
}
3487+
3488+
// adds LUKS overhead iff luksEncryption is a true boolean string. Logs an error if the luksEncryption string is not a boolean.
3489+
func incrementWithLUKSMetadataIfLUKSEnabled(ctx context.Context, size uint64, luksEncryption string) uint64 {
3490+
isLUKS, err := strconv.ParseBool(luksEncryption)
3491+
if err != nil && luksEncryption != "" {
3492+
Logc(ctx).WithError(err).Debug("Could not parse luksEncryption string.")
3493+
}
3494+
3495+
if isLUKS {
3496+
return size + utils.LUKSMetadataSize
3497+
}
3498+
3499+
return size
3500+
}
3501+
3502+
// removes LUKS overhead iff luksEncryption is a true boolean string. Logs an error if the luksEncryption string is not a boolean or size is too small.
3503+
func decrementWithLUKSMetadataIfLUKSEnabled(ctx context.Context, size uint64, luksEncryption string) uint64 {
3504+
isLUKS, err := strconv.ParseBool(luksEncryption)
3505+
if err != nil && luksEncryption != "" {
3506+
Logc(ctx).WithError(err).Debug("Could not parse luksEncryption string.")
3507+
}
3508+
3509+
if utils.LUKSMetadataSize > size {
3510+
Logc(ctx).WithError(err).WithField("size", size).Error("Size too small to subtract LUKS metadata.")
3511+
return 0
3512+
}
3513+
3514+
if isLUKS {
3515+
return size - utils.LUKSMetadataSize
3516+
}
3517+
3518+
return size
3519+
}
3520+
34763521
// deleteAutomaticSnapshot deletes a snapshot that was created automatically during volume clone creation.
34773522
// An automatic snapshot is detected by the presence of CloneSourceSnapshotInternal in the volume config
34783523
// while CloneSourceSnapshot is not set. This method is called after the volume has been deleted, and it

storage_drivers/ontap/ontap_common_test.go

+60
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import (
66
"context"
77
"encoding/json"
88
"fmt"
9+
"math/rand"
910
"os"
11+
"strconv"
1012
"testing"
1113
"time"
1214

@@ -6360,6 +6362,64 @@ func TestConstructPoolForLabels(t *testing.T) {
63606362
assert.Equal(t, sa.NewLabelOffer(nil), pool.Attributes()["labels"])
63616363
}
63626364

6365+
func TestSubtractUintFromSizeString(t *testing.T) {
6366+
units := []string{"", "MB", "MiB", "GB", "GiB"}
6367+
count := 100
6368+
maxValue := int64(1000000000)
6369+
6370+
// Test for invalid size string
6371+
_, err := subtractUintFromSizeString("not a size", 0)
6372+
assert.ErrorContains(t, err, "invalid size")
6373+
6374+
// Fuzz tests
6375+
for range count {
6376+
sizeValue := rand.Int63n(maxValue + 1)
6377+
size := strconv.FormatInt(sizeValue, 10) + units[rand.Intn(len(units))]
6378+
val := uint64(rand.Int63n(maxValue))
6379+
6380+
sizeBytesString, err := utils.ConvertSizeToBytes(size)
6381+
assert.NoError(t, err)
6382+
sizeBytes, _ := strconv.ParseUint(sizeBytesString, 10, 64)
6383+
6384+
newSizeBytesString, err := subtractUintFromSizeString(size, val)
6385+
6386+
if val > sizeBytes {
6387+
assert.ErrorContains(t, err, "too large")
6388+
} else {
6389+
assert.NoError(t, err)
6390+
6391+
expected := strconv.FormatUint(sizeBytes-val, 10)
6392+
assert.Equal(t, expected, newSizeBytesString)
6393+
}
6394+
}
6395+
}
6396+
6397+
func TestIncrementWithLUKSMetadataIfLUKSEnabled(t *testing.T) {
6398+
size := uint64(1000000000)
6399+
6400+
actual := incrementWithLUKSMetadataIfLUKSEnabled(context.Background(), size, "true")
6401+
assert.Greater(t, actual, size)
6402+
6403+
actual = incrementWithLUKSMetadataIfLUKSEnabled(context.Background(), size, "false")
6404+
assert.Equal(t, actual, size)
6405+
6406+
actual = incrementWithLUKSMetadataIfLUKSEnabled(context.Background(), size, "blue")
6407+
assert.Equal(t, actual, size)
6408+
}
6409+
6410+
func TestDecrementWithLUKSMetadataIfLUKSEnabled(t *testing.T) {
6411+
size := uint64(1000000000)
6412+
6413+
actual := decrementWithLUKSMetadataIfLUKSEnabled(context.Background(), size, "true")
6414+
assert.Less(t, actual, size)
6415+
6416+
actual = decrementWithLUKSMetadataIfLUKSEnabled(context.Background(), size, "false")
6417+
assert.Equal(t, actual, size)
6418+
6419+
actual = decrementWithLUKSMetadataIfLUKSEnabled(context.Background(), size, "blue")
6420+
assert.Equal(t, actual, size)
6421+
}
6422+
63636423
func TestDeleteAutomaticSnapshot(t *testing.T) {
63646424
type parameters struct {
63656425
volConfig storage.VolumeConfig

storage_drivers/ontap/ontap_san.go

+21-1
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,11 @@ func (d *SANStorageDriver) Create(
343343
}
344344
lunSizeBytes := GetVolumeSize(requestedSizeBytes, storagePool.InternalAttributes()[Size])
345345

346+
// Add a constant overhead for LUKS volumes to account for LUKS metadata. This overhead is
347+
// part of the LUN but is not reported to the orchestrator.
348+
reportedSize := lunSizeBytes
349+
lunSizeBytes = incrementWithLUKSMetadataIfLUKSEnabled(ctx, lunSizeBytes, luksEncryption)
350+
346351
lunSize := strconv.FormatUint(lunSizeBytes, 10)
347352
// Get the flexvol size based on the snapshot reserve
348353
flexvolSize := drivers.CalculateVolumeSizeBytes(ctx, name, lunSizeBytes, snapshotReserveInt)
@@ -378,7 +383,7 @@ func (d *SANStorageDriver) Create(
378383
}
379384

380385
// Update config to reflect values used to create volume
381-
volConfig.Size = strconv.FormatUint(lunSizeBytes, 10)
386+
volConfig.Size = strconv.FormatUint(reportedSize, 10)
382387
volConfig.SpaceReserve = spaceReserve
383388
volConfig.SnapshotPolicy = snapshotPolicy
384389
volConfig.SnapshotReserve = snapshotReserve
@@ -692,6 +697,14 @@ func (d *SANStorageDriver) Import(ctx context.Context, volConfig *storage.Volume
692697
// Use the LUN size
693698
volConfig.Size = lunInfo.Size
694699

700+
if utils.ParseBool(volConfig.LUKSEncryption) {
701+
newSize, err := subtractUintFromSizeString(volConfig.Size, utils.LUKSMetadataSize)
702+
if err != nil {
703+
return err
704+
}
705+
volConfig.Size = newSize
706+
}
707+
695708
// Rename the volume or LUN if Trident will manage its lifecycle
696709
if !volConfig.ImportNotManaged {
697710
if lunInfo.Name != targetPath {
@@ -1348,12 +1361,16 @@ func (d *SANStorageDriver) Resize(
13481361
return fmt.Errorf("requested size %d is less than existing volume size %d", requestedSizeBytes, lunSizeBytes)
13491362
}
13501363

1364+
// Add a constant overhead for LUKS volumes to account for LUKS metadata.
1365+
requestedSizeBytes = incrementWithLUKSMetadataIfLUKSEnabled(ctx, requestedSizeBytes, volConfig.LUKSEncryption)
1366+
13511367
snapshotReserveInt, err := getSnapshotReserveFromOntap(ctx, name, d.API.VolumeInfo)
13521368
if err != nil {
13531369
Logc(ctx).WithField("name", name).Errorf("Could not get the snapshot reserve percentage for volume")
13541370
}
13551371

13561372
newFlexvolSize := drivers.CalculateVolumeSizeBytes(ctx, name, requestedSizeBytes, snapshotReserveInt)
1373+
13571374
newFlexvolSize = uint64(LUNMetadataBufferMultiplier * float64(newFlexvolSize))
13581375

13591376
sameLUNSize := utils.VolumeSizeWithinTolerance(int64(requestedSizeBytes), int64(currentLunSize),
@@ -1413,6 +1430,9 @@ func (d *SANStorageDriver) Resize(
14131430
}
14141431
}
14151432

1433+
// LUKS metadata size is not reported so remove it from LUN size
1434+
returnSize = decrementWithLUKSMetadataIfLUKSEnabled(ctx, returnSize, volConfig.LUKSEncryption)
1435+
14161436
volConfig.Size = strconv.FormatUint(returnSize, 10)
14171437
return nil
14181438
}

storage_drivers/ontap/ontap_san_economy.go

+30-9
Original file line numberDiff line numberDiff line change
@@ -447,14 +447,6 @@ func (d *SANEconomyStorageDriver) Create(
447447
}
448448
sizeBytes = GetVolumeSize(sizeBytes, storagePool.InternalAttributes()[Size])
449449

450-
lunSize := strconv.FormatUint(sizeBytes, 10)
451-
452-
if _, _, checkVolumeSizeLimitsError := drivers.CheckVolumeSizeLimits(
453-
ctx, sizeBytes, d.Config.CommonStorageDriverConfig,
454-
); checkVolumeSizeLimitsError != nil {
455-
return checkVolumeSizeLimitsError
456-
}
457-
458450
// Ensure LUN name isn't too long
459451
if len(name) > maxLunNameLength {
460452
return fmt.Errorf("volume %s name exceeds the limit of %d characters", name, maxLunNameLength)
@@ -482,6 +474,19 @@ func (d *SANEconomyStorageDriver) Create(
482474
luksEncryption = storagePool.InternalAttributes()[LUKSEncryption]
483475
)
484476

477+
// Add a constant overhead for LUKS volumes to account for LUKS metadata. This overhead is
478+
// part of the LUN but is not reported to the orchestrator.
479+
reportedSize := sizeBytes
480+
sizeBytes = incrementWithLUKSMetadataIfLUKSEnabled(ctx, sizeBytes, luksEncryption)
481+
482+
lunSize := strconv.FormatUint(sizeBytes, 10)
483+
484+
if _, _, checkVolumeSizeLimitsError := drivers.CheckVolumeSizeLimits(
485+
ctx, sizeBytes, d.Config.CommonStorageDriverConfig,
486+
); checkVolumeSizeLimitsError != nil {
487+
return checkVolumeSizeLimitsError
488+
}
489+
485490
snapshotReserveInt, err := GetSnapshotReserve(snapshotPolicy, snapshotReserve)
486491
if err != nil {
487492
return fmt.Errorf("invalid value for snapshotReserve: %v", err)
@@ -510,7 +515,7 @@ func (d *SANEconomyStorageDriver) Create(
510515
}
511516

512517
// Update config to reflect values used to create volume
513-
volConfig.Size = strconv.FormatUint(sizeBytes, 10)
518+
volConfig.Size = strconv.FormatUint(reportedSize, 10)
514519
volConfig.SpaceReserve = spaceReserve
515520
volConfig.SnapshotPolicy = snapshotPolicy
516521
volConfig.SnapshotReserve = snapshotReserve
@@ -646,6 +651,8 @@ func (d *SANEconomyStorageDriver) Create(
646651
Logc(ctx).WithField("error", err).Error("Failed to determine LUN size")
647652
return err
648653
}
654+
// Remove LUKS metadata size from actual size of LUN
655+
actualSize = decrementWithLUKSMetadataIfLUKSEnabled(ctx, actualSize, luksEncryption)
649656
volConfig.Size = strconv.FormatUint(actualSize, 10)
650657

651658
// Save the fstype in a LUN attribute so we know what to do in Attach
@@ -883,6 +890,14 @@ func (d *SANEconomyStorageDriver) Import(
883890
}
884891
volConfig.Size = extantLUN.Size
885892

893+
if utils.ParseBool(volConfig.LUKSEncryption) {
894+
newSize, err := subtractUintFromSizeString(volConfig.Size, utils.LUKSMetadataSize)
895+
if err != nil {
896+
return err
897+
}
898+
volConfig.Size = newSize
899+
}
900+
886901
if volConfig.ImportNotManaged {
887902
// Volume/LUN import is not managed by Trident
888903
if !strings.HasPrefix(flexvol.Name, d.FlexvolNamePrefix()) {
@@ -2152,6 +2167,10 @@ func (d *SANEconomyStorageDriver) Resize(ctx context.Context, volConfig *storage
21522167
Logd(ctx, d.Name(), d.Config.DebugTraceFlags["method"]).WithFields(fields).Trace(">>>> Resize")
21532168
defer Logd(ctx, d.Name(), d.Config.DebugTraceFlags["method"]).WithFields(fields).Trace("<<<< Resize")
21542169

2170+
// Add a constant overhead for LUKS volumes to account for LUKS metadata. This overhead is
2171+
// part of the LUN but is not reported to the orchestrator.
2172+
sizeBytes = incrementWithLUKSMetadataIfLUKSEnabled(ctx, sizeBytes, volConfig.LUKSEncryption)
2173+
21552174
// Generic user-facing message
21562175
resizeError := errors.New("storage driver failed to resize the volume")
21572176

@@ -2251,6 +2270,8 @@ func (d *SANEconomyStorageDriver) Resize(ctx context.Context, volConfig *storage
22512270
Logc(ctx).WithField("error", err).Error("LUN resize failed.")
22522271
return fmt.Errorf("volume resize failed")
22532272
}
2273+
// LUKS metadata is not reported to orchestrator
2274+
returnSize = decrementWithLUKSMetadataIfLUKSEnabled(ctx, returnSize, volConfig.LUKSEncryption)
22542275

22552276
volConfig.Size = strconv.FormatUint(returnSize, 10)
22562277

utils/devices.go

+3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ import (
1919
"github.com/netapp/trident/utils/errors"
2020
)
2121

22+
// LUKS2 requires ~16MiB for overhead. Default to 18MiB just in case.
23+
const LUKSMetadataSize = 18874368
24+
2225
const (
2326
luksDevicePrefix = "luks-"
2427
devPrefix = "/dev/"

utils/utils.go

+6
Original file line numberDiff line numberDiff line change
@@ -1089,6 +1089,12 @@ func GetFormattedBool(value string) (string, error) {
10891089
return strconv.FormatBool(valBool), nil
10901090
}
10911091

1092+
// ParseBool wraps strconv.ParseBool to suppress errors. Returns false if strconv.ParseBool would return an error.
1093+
func ParseBool(b string) bool {
1094+
v, _ := strconv.ParseBool(b)
1095+
return v
1096+
}
1097+
10921098
func shiftTextRight(text string, count int) string {
10931099
if text == "" {
10941100
return ""

0 commit comments

Comments
 (0)