Skip to content

Commit

Permalink
Check disk space before backing up / restoring
Browse files Browse the repository at this point in the history
  • Loading branch information
pmtk committed Oct 24, 2024
1 parent 3ed7f01 commit a64a717
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 0 deletions.
8 changes: 8 additions & 0 deletions pkg/admin/autorecovery/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,17 @@ func (m *Manager) PerformRestore() error {
RENAME $STORAGE/$PREVIOUSLY_RESTORED -> $STORAGE/restored/$PREVIOUSLY_RESTORED
*/

if err := data.CheckIfEnoughSpaceToRestore(m.storage.GetBackupPath(restoreCandidate.Name())); err != nil {
return err
}

// Copies/creations into intermediate destinations
var oldData *data.AtomicDirCopy
if m.saveFailed {
if err := data.CheckIfEnoughSpaceToBackUp(string(m.storage)); err != nil {
return err
}

oldDataBackupName, err := GetBackupName()
if err != nil {
return err
Expand Down
8 changes: 8 additions & 0 deletions pkg/admin/data/data_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ func (dm *manager) Backup(name BackupName) (string, error) {
klog.InfoS("Created backup storage directory", "path", dm.storage)
}

if err := CheckIfEnoughSpaceToBackUp(string(dm.storage)); err != nil {
return "", err
}

dest := dm.GetBackupPath(name)
if err := copyPath(config.DataDir, dest); err != nil {
return "", err
Expand Down Expand Up @@ -141,6 +145,10 @@ func (dm *manager) Restore(name BackupName) error {
return fmt.Errorf("%q is not a valid MicroShift backup: %w", path, err)
}

if err := CheckIfEnoughSpaceToRestore(path); err != nil {
return err
}

tmp := fmt.Sprintf("%s.saved", config.DataDir)
klog.InfoS("Renaming existing data dir", "data", config.DataDir, "renamedTo", tmp)
if err := os.Rename(config.DataDir, tmp); err != nil {
Expand Down
97 changes: 97 additions & 0 deletions pkg/admin/data/disk_space.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package data

import (
"fmt"
"io/fs"
"path/filepath"
"syscall"

"github.com/openshift/microshift/pkg/config"

"k8s.io/klog/v2"
)

func GetSizeOfMicroShiftData() (uint64, error) {
return GetSizeOfDir(config.DataDir)
}

func GetSizeOfDir(path string) (uint64, error) {
var size int64
err := filepath.Walk(path, func(path string, info fs.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() {
size += info.Size()
}
return nil
})
if err != nil {
return 0, fmt.Errorf("failed to get size of %q: %w", path, err)
}
klog.Infof("Calculated size of %q: %vM", path, size/1024/1024)
return uint64(size), nil
}

func GetAvailableDiskSpace(path string) (uint64, error) {
var stat syscall.Statfs_t
if err := syscall.Statfs(path, &stat); err != nil {
return 0, fmt.Errorf("failed to get available disk space of %q: %w", path, err)
}
available := stat.Bavail * uint64(stat.Bsize)
klog.Infof("Calculated available disk space for %q: %vM", path, available/1024/1024)
return available, nil
}

// CheckIfEnoughSpaceToRestore performs a naive check if there is enough
// disk space on /var/lib filesystem to restore the backup.
// It does not accomodate for potential Copy-on-Write disk savings.
func CheckIfEnoughSpaceToRestore(backupPath string) error {
backupSize, err := GetSizeOfDir(backupPath)
if err != nil {
return err
}

// Restore process: renames MicroShift data dir, copies backup into place, deletes renamed copy hence the /var/lib
// needs extra space before old MicroShift data is removed.
availableSpace, err := GetAvailableDiskSpace("/var/lib")
if err != nil {
return err
}

if availableSpace < backupSize {
return fmt.Errorf(
"not enough disk space in /var/lib to restore the backup: required=%vM available=%vM",
backupSize/1024/1024,
availableSpace/1024/1024,
)
}

return nil
}

// CheckIfEnoughSpaceToBackUp performs a naive check if there is enough
// disk space on a filesystem holding the backups for another backup of MicroShift data.
// It does not accomodate for potential Copy-on-Write disk savings.
func CheckIfEnoughSpaceToBackUp(storage string) error {
dataSize, err := GetSizeOfMicroShiftData()
if err != nil {
return err
}

availableSpace, err := GetAvailableDiskSpace(storage)
if err != nil {
return err
}

if availableSpace < dataSize {
return fmt.Errorf(
"not enough disk space in %q to create a backup: required=%vM available=%vM",
storage,
dataSize/1024/1024,
availableSpace/1024/1024,
)
}

return nil
}

0 comments on commit a64a717

Please sign in to comment.