Skip to content

Commit

Permalink
stages/disks: add logic to resize an existing partition
Browse files Browse the repository at this point in the history
Fixes coreos#924
This fix will allow users to resize an existing partition without wiping
out an entry from the partition table.
  • Loading branch information
sohankunkerkar committed Sep 14, 2020
1 parent 6cfc2c7 commit d7deabf
Showing 1 changed file with 53 additions and 8 deletions.
61 changes: 53 additions & 8 deletions internal/exec/stages/disks/partitions.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,25 +71,57 @@ func (s stage) createPartitions(config types.Config) error {
// also have non-zero start and size and non-nil start and size and label.
// n.b. existing.{Size,Start}MiB must be converted to sectors first (yes the variable name becomes misleading)
func partitionMatches(existing util.PartitionInfo, spec sgdisk.Partition) error {
result := partitionMatchesCommon(existing, spec)
switch result {
case "Number":
return fmt.Errorf("partition numbers did not match (specified %d, got %d). This should not happen, please file a bug", spec.Number, existing.Number)
case "StartSector":
return fmt.Errorf("starting sector did not match (specified %d, got %d)", *spec.StartSector, existing.StartSector)
case "SizeInSectors":
return fmt.Errorf("size did not match (specified %d, got %d)", *spec.SizeInSectors, existing.SizeInSectors)
case "GUID":
return fmt.Errorf("GUID did not match (specified %q, got %q)", *spec.GUID, existing.GUID)
case "TypeGUID":
return fmt.Errorf("type GUID did not match (specified %q, got %q)", *spec.TypeGUID, existing.TypeGUID)
case "Label":
return fmt.Errorf("label did not match (specified %q, got %q)", *spec.Label, existing.Label)
}
return nil
}

// partitionMatchesResize returns if the existing partition should be resized by evaluating if the `resize`
// field is set to true and all of the specified attributes matches the existing partition's attributes except
// the partition size.
func partitionMatchesResize(existing util.PartitionInfo, spec sgdisk.Partition, resize bool) bool {
result := partitionMatchesCommon(existing, spec)
if resize && strings.Contains(result, "SizeInSectors") {
return true
}
return false
}

// partitionMatchesCommon handles the common tests to match the existing partition attributes with the
// specified partition ones.
func partitionMatchesCommon(existing util.PartitionInfo, spec sgdisk.Partition) string {
if spec.Number != existing.Number {
return fmt.Errorf("partition numbers did not match (specified %d, got %d). This should not happen, please file a bug.", spec.Number, existing.Number)
return "Number"
}
if spec.StartSector != nil && *spec.StartSector != existing.StartSector {
return fmt.Errorf("starting sector did not match (specified %d, got %d)", *spec.StartSector, existing.StartSector)
return "StatSector"
}
if spec.SizeInSectors != nil && *spec.SizeInSectors != existing.SizeInSectors {
return fmt.Errorf("size did not match (specified %d, got %d)", *spec.SizeInSectors, existing.SizeInSectors)
return "SizeInSectors"
}
if spec.GUID != nil && *spec.GUID != "" && strings.ToLower(*spec.GUID) != strings.ToLower(existing.GUID) {
return fmt.Errorf("GUID did not match (specified %q, got %q)", *spec.GUID, existing.GUID)
return "GUID"
}
if spec.TypeGUID != nil && *spec.TypeGUID != "" && strings.ToLower(*spec.TypeGUID) != strings.ToLower(existing.TypeGUID) {
return fmt.Errorf("type GUID did not match (specified %q, got %q)", *spec.TypeGUID, existing.TypeGUID)
return "TypeGUID"
}
if spec.Label != nil && *spec.Label != existing.Label {
return fmt.Errorf("label did not match (specified %q, got %q)", *spec.Label, existing.Label)
return "Label"
}
return nil
return ""
}

// partitionShouldBeInspected returns if the partition has zeroes that need to be resolved to sectors.
Expand Down Expand Up @@ -339,6 +371,7 @@ func (s stage) partitionDisk(dev types.Disk, devAlias string) error {
}
matches := exists && matchErr == nil
wipeEntry := part.WipePartitionEntry != nil && *part.WipePartitionEntry
resize := part.Resize != nil && *part.Resize

// This is a translation of the matrix in the operator notes.
switch {
Expand All @@ -353,7 +386,19 @@ func (s stage) partitionDisk(dev types.Disk, devAlias string) error {
case exists && shouldExist && matches:
s.Logger.Info("partition %d found with correct specifications", part.Number)
case exists && shouldExist && !wipeEntry && !matches:
return fmt.Errorf("Partition %d didn't match: %v", part.Number, matchErr)
resizePartition := partitionMatchesResize(info, part, resize)
if resizePartition {
s.Logger.Info("resizing partition %d", part.Number)
op.DeletePartition(part.Number)
part.Number = info.Number
part.GUID = &info.GUID
part.TypeGUID = &info.TypeGUID
part.Label = &info.Label
part.StartSector = &info.StartSector
op.CreatePartition(part)
} else {
return fmt.Errorf("Partition %d didn't match: %v", part.Number, matchErr)
}
case exists && shouldExist && wipeEntry && !matches:
s.Logger.Info("partition %d did not meet specifications, wiping partition entry and recreating", part.Number)
op.DeletePartition(part.Number)
Expand Down

0 comments on commit d7deabf

Please sign in to comment.