Skip to content

Commit

Permalink
disk-resize: use actual partition sizes to calculate pv shift size
Browse files Browse the repository at this point in the history
instead of relying on the config values and the constants for default
disk-size and pv partition size, this fetches the size of disk,  root
and pv partition using `lsblk` and uses these values to calculate the
size by which the pv partition needs to be shifted to apply requested
new values for 'disk-size' and 'persistent-volume-size' configs

it uses the 'strongunits' package from containers/common for bytes to
GiB conversions and its types to deal with storage sizes
  • Loading branch information
anjannath committed Jul 31, 2024
1 parent 2f814b3 commit d129b86
Show file tree
Hide file tree
Showing 6 changed files with 357 additions and 10 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ require (
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2
github.com/cavaliergopher/grab/v3 v3.0.1
github.com/cheggaaa/pb/v3 v3.1.5
github.com/containers/common v0.60.0
github.com/containers/gvisor-tap-vsock v0.7.4
github.com/containers/image/v5 v5.32.0
github.com/coreos/go-systemd/v22 v22.5.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vc
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/containers/common v0.60.0 h1:QMNygqiiit9LU/yqee9Dv0N0oQ+rQq41ElfdOBQtw7w=
github.com/containers/common v0.60.0/go.mod h1:dtKVe11xkV89tqzRX9s/B0ORjeB2dy5UB46aGjunMn8=
github.com/containers/gvisor-tap-vsock v0.7.4 h1:iOtr/KEi+r599OOx1+9Qbss91jD5yxh1HO35MKTdths=
github.com/containers/gvisor-tap-vsock v0.7.4/go.mod h1:orUOSdxU/IGEOxhecu2i7EzV7k7e2TgQlyCBfUngS0A=
github.com/containers/image/v5 v5.32.0 h1:yjbweazPfr8xOzQ2hkkYm1A2V0jN96/kES6Gwyxj7hQ=
Expand Down
95 changes: 85 additions & 10 deletions pkg/crc/machine/disks.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import (
"context"
"errors"
"fmt"
"math"
"strconv"
"strings"

"github.com/containers/common/pkg/strongunits"
"github.com/crc-org/crc/v2/pkg/crc/constants"
logging "github.com/crc-org/crc/v2/pkg/crc/logging"
"github.com/crc-org/crc/v2/pkg/crc/machine/types"
Expand All @@ -15,13 +17,13 @@ import (
"golang.org/x/crypto/ssh"
)

func moveTopolvmPartition(ctx context.Context, shiftSize int, vm *virtualMachine, sshRunner *crcssh.Runner) error {
func moveTopolvmPartition(ctx context.Context, shiftSize strongunits.GiB, vm *virtualMachine, sshRunner *crcssh.Runner) error {
pvPartition, err := getTopolvmPartition(sshRunner)
if err != nil {
return err
}
_, _, err = sshRunner.RunPrivileged("move topolvm partition to end of disk",
fmt.Sprintf("echo '+%dG,' | sudo sfdisk --move-data %s -N %s --force", shiftSize, pvPartition[:len("/dev/.da")], pvPartition[len("/dev/.da"):]))
fmt.Sprintf("echo '+%dG,' | sudo sfdisk --lock --move-data %s -N %s --force", shiftSize, pvPartition[:len("/dev/.da")], pvPartition[len("/dev/.da"):]))
var exitErr *ssh.ExitError
if err != nil {
if !errors.As(err, &exitErr) {
Expand Down Expand Up @@ -55,19 +57,92 @@ func growPartition(sshRunner *crcssh.Runner, partition string) error {
return nil
}

func ocpGetPVShiftSizeGiB(diskSize int, pvSize int) int {
defaultPvSize := constants.GetDefaultPersistentVolumeSize(crcPreset.OpenShift)
if pvSize > defaultPvSize {
return (diskSize - constants.DefaultDiskSize) - (pvSize - defaultPvSize)
func ocpGetPVShiftSizeGiB(sshRunner *crcssh.Runner, diskSize int, pvSize int) strongunits.GiB {
pvPartition, err := getTopolvmPartition(sshRunner)
if err != nil {
logging.Warnf("unable to get topolvm parition name: %v", err)
return 0
}
currentPvSize, err := getBlockDeviceSizeGiB(sshRunner, pvPartition)
if err != nil {
logging.Warnf("unable to get effective topolvm parition size: %v", err)
return 0
}
currentDiskSize, err := getBlockDeviceSizeGiB(sshRunner, pvPartition[:len("/dev/.da")])
if err != nil {
logging.Warnf("unable to get effective disk size: %v", err)
return 0
}
rootPart, err := getrootPartition(sshRunner, crcPreset.OpenShift)
if err != nil {
logging.Warnf("unable to get root partition name: %v", err)
return 0
}
currentRootPartSize, err := getBlockDeviceSizeGiB(sshRunner, rootPart)
if err != nil {
logging.Warnf("unable to get effective disk size: %v", err)
return 0
}

logging.Debug("Current disk size: ", currentDiskSize)
logging.Debug("Current pv size: ", currentPvSize)
logging.Debug("Current root partition size: ", currentRootPartSize)

diskSizeGiB := strongunits.GiB(diskSize)
pvSizeGiB := strongunits.GiB(pvSize)

logging.Debug("Requested disk size: ", diskSizeGiB)
logging.Debug("Requested pv size: ", pvSizeGiB)

// if the disk size is not increased then no need to shift pv parition
if currentDiskSize == constants.DefaultDiskSize {
return 0
}
return diskSize - constants.DefaultDiskSize

if pvSizeGiB > currentPvSize || diskSizeGiB > constants.DefaultDiskSize {
// calculating the space to move from the start of the disk including
// the root parition + 1GiB for partitions /boot and EFI
sizeOfRootAndOtherParts := currentRootPartSize + strongunits.GiB(uint64(1))
shiftSize := (currentDiskSize - sizeOfRootAndOtherParts) - pvSizeGiB

logging.Debug("Calculated pv partition shift size: ", shiftSize)

// when trying to subtract a bigger number from a smaller number there's overflow
if shiftSize == math.MaxUint64 {
return 0
}
return shiftSize
}

return 0
}

func getBlockDeviceSizeGiB(sshRunner *crcssh.Runner, device string) (strongunits.GiB, error) {
stdOut, _, err := sshRunner.Run("lsblk", "-b", "--output", "SIZE", "-n", "-d", device)
if err != nil {
return 0, err
}
stdOut = strings.TrimSuffix(stdOut, "\n")
logging.Debugf("Got size of %s using lsblk: %s", device, stdOut)
size, err := strconv.ParseUint(stdOut, 10, 64)
if err != nil {
logging.Warnf("unable to parse topolvm parition size: %v", err)
return 0, err
}
logging.Debugf("Size of %s in uint64: %d", device, size)

sizeBytes := strongunits.B(size)
logging.Debugf("Size of %s in GiB: %d", device, strongunits.ToGiB(sizeBytes))
return strongunits.ToGiB(sizeBytes), nil
}

func growFileSystem(ctx context.Context, startConfig types.StartConfig, vm *virtualMachine, sshRunner *crcssh.Runner) error {
if startConfig.Preset == crcPreset.OpenShift {
sizeToMove := ocpGetPVShiftSizeGiB(startConfig.DiskSize, startConfig.PersistentVolumeSize)
if err := moveTopolvmPartition(ctx, sizeToMove, vm, sshRunner); err != nil {
return err
sizeToMove := ocpGetPVShiftSizeGiB(sshRunner, startConfig.DiskSize, startConfig.PersistentVolumeSize)
if sizeToMove > 0 {
if err := moveTopolvmPartition(ctx, sizeToMove, vm, sshRunner); err != nil {
return err
}
}
}
rootPart, err := getrootPartition(sshRunner, startConfig.Preset)
Expand Down
201 changes: 201 additions & 0 deletions vendor/github.com/containers/common/LICENSE

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit d129b86

Please sign in to comment.