228 lines
5.8 KiB
Go
228 lines
5.8 KiB
Go
// Disk package contains abstract data-types to define disk-related entities.
|
|
//
|
|
// PartitionTable, Partition and Filesystem types are currently defined.
|
|
// All of them can be 1:1 converted to osbuild.QEMUAssemblerOptions.
|
|
package disk
|
|
|
|
import (
|
|
"sort"
|
|
|
|
osbuild "github.com/osbuild/osbuild-composer/internal/osbuild1"
|
|
"github.com/osbuild/osbuild-composer/internal/osbuild2"
|
|
)
|
|
|
|
type PartitionTable struct {
|
|
// Size of the disk.
|
|
Size uint64
|
|
UUID string
|
|
// Partition table type, e.g. dos, gpt.
|
|
Type string
|
|
Partitions []Partition
|
|
}
|
|
|
|
type Partition struct {
|
|
Start uint64
|
|
Size uint64
|
|
Type string
|
|
Bootable bool
|
|
// ID of the partition, dos doesn't use traditional UUIDs, therefore this
|
|
// is just a string.
|
|
UUID string
|
|
// If nil, the partition is raw; It doesn't contain a filesystem.
|
|
Filesystem *Filesystem
|
|
}
|
|
|
|
type Filesystem struct {
|
|
Type string
|
|
// ID of the filesystem, vfat doesn't use traditional UUIDs, therefore this
|
|
// is just a string.
|
|
UUID string
|
|
Label string
|
|
Mountpoint string
|
|
// The fourth field of fstab(5); fs_mntops
|
|
FSTabOptions string
|
|
// The fifth field of fstab(5); fs_freq
|
|
FSTabFreq uint64
|
|
// The sixth field of fstab(5); fs_passno
|
|
FSTabPassNo uint64
|
|
}
|
|
|
|
// Converts PartitionTable to osbuild.QEMUAssemblerOptions that encode
|
|
// the same partition table.
|
|
func (pt PartitionTable) QEMUAssemblerOptions() osbuild.QEMUAssemblerOptions {
|
|
var partitions []osbuild.QEMUPartition
|
|
for _, p := range pt.Partitions {
|
|
partitions = append(partitions, p.QEMUPartition())
|
|
}
|
|
|
|
return osbuild.QEMUAssemblerOptions{
|
|
Size: pt.Size,
|
|
PTUUID: pt.UUID,
|
|
PTType: pt.Type,
|
|
Partitions: partitions,
|
|
}
|
|
}
|
|
|
|
// Generates org.osbuild.fstab stage options from this partition table.
|
|
func (pt PartitionTable) FSTabStageOptions() *osbuild.FSTabStageOptions {
|
|
var options osbuild.FSTabStageOptions
|
|
for _, p := range pt.Partitions {
|
|
fs := p.Filesystem
|
|
if fs == nil {
|
|
continue
|
|
}
|
|
|
|
options.AddFilesystem(fs.UUID, fs.Type, fs.Mountpoint, fs.FSTabOptions, fs.FSTabFreq, fs.FSTabPassNo)
|
|
}
|
|
|
|
// sort the entries by PassNo to maintain backward compatibility
|
|
sort.Slice(options.FileSystems, func(i, j int) bool {
|
|
return options.FileSystems[i].PassNo < options.FileSystems[j].PassNo
|
|
})
|
|
|
|
return &options
|
|
}
|
|
|
|
// Generates org.osbuild.fstab stage options from this partition table.
|
|
func (pt PartitionTable) FSTabStageOptionsV2() *osbuild2.FSTabStageOptions {
|
|
var options osbuild2.FSTabStageOptions
|
|
for _, p := range pt.Partitions {
|
|
fs := p.Filesystem
|
|
if fs == nil {
|
|
continue
|
|
}
|
|
|
|
options.AddFilesystem(fs.UUID, fs.Type, fs.Mountpoint, fs.FSTabOptions, fs.FSTabFreq, fs.FSTabPassNo)
|
|
}
|
|
|
|
// sort the entries by PassNo to maintain backward compatibility
|
|
sort.Slice(options.FileSystems, func(i, j int) bool {
|
|
return options.FileSystems[i].PassNo < options.FileSystems[j].PassNo
|
|
})
|
|
|
|
return &options
|
|
}
|
|
|
|
// Returns the root partition (the partition whose filesystem has / as
|
|
// a mountpoint) of the partition table. Nil is returned if there's no such
|
|
// partition.
|
|
func (pt PartitionTable) RootPartition() *Partition {
|
|
for _, p := range pt.Partitions {
|
|
if p.Filesystem == nil {
|
|
continue
|
|
}
|
|
|
|
if p.Filesystem.Mountpoint == "/" {
|
|
return &p
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Returns the /boot partition (the partition whose filesystem has /boot as
|
|
// a mountpoint) of the partition table. Nil is returned if there's no such
|
|
// partition.
|
|
func (pt PartitionTable) BootPartition() *Partition {
|
|
for _, p := range pt.Partitions {
|
|
if p.Filesystem == nil {
|
|
continue
|
|
}
|
|
|
|
if p.Filesystem.Mountpoint == "/boot" {
|
|
return &p
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Returns the index of the boot partition: the partition whose filesystem has
|
|
// /boot as a mountpoint. If there is no explicit boot partition, the root
|
|
// partition is returned.
|
|
// If neither boot nor root partitions are found, returns -1.
|
|
func (pt PartitionTable) BootPartitionIndex() int {
|
|
// find partition with '/boot' mountpoint and fallback to '/'
|
|
rootIdx := -1
|
|
for idx, part := range pt.Partitions {
|
|
if part.Filesystem == nil {
|
|
continue
|
|
}
|
|
if part.Filesystem.Mountpoint == "/boot" {
|
|
return idx
|
|
} else if part.Filesystem.Mountpoint == "/" {
|
|
rootIdx = idx
|
|
}
|
|
}
|
|
return rootIdx
|
|
}
|
|
|
|
func (pt PartitionTable) RootPartitionIndex() int {
|
|
rootIdx := -1
|
|
for idx, part := range pt.Partitions {
|
|
if part.Filesystem == nil {
|
|
continue
|
|
}
|
|
if part.Filesystem.Mountpoint == "/" {
|
|
rootIdx = idx
|
|
}
|
|
}
|
|
return rootIdx
|
|
}
|
|
|
|
// dynamically calculate and update the start point
|
|
// for each of the existing partitions
|
|
// return the updated start point
|
|
func (pt *PartitionTable) updatePartitionStartPointOffsets(start uint64) uint64 {
|
|
var rootIdx = -1
|
|
for i := range pt.Partitions {
|
|
partition := &pt.Partitions[i]
|
|
if partition.Filesystem != nil && partition.Filesystem.Mountpoint == "/" {
|
|
rootIdx = i
|
|
continue
|
|
}
|
|
partition.Start = start
|
|
start += partition.Size
|
|
}
|
|
pt.Partitions[rootIdx].Start = start
|
|
return start
|
|
}
|
|
|
|
func (pt *PartitionTable) updateRootPartition(rootPartition Partition) {
|
|
pt.Partitions[pt.RootPartitionIndex()] = rootPartition
|
|
}
|
|
|
|
func (pt *PartitionTable) getPartitionTableSize() uint64 {
|
|
var size uint64
|
|
for _, p := range pt.Partitions {
|
|
size += p.Size
|
|
}
|
|
return size
|
|
}
|
|
|
|
// Converts Partition to osbuild.QEMUPartition that encodes the same partition.
|
|
func (p Partition) QEMUPartition() osbuild.QEMUPartition {
|
|
var fs *osbuild.QEMUFilesystem
|
|
if p.Filesystem != nil {
|
|
f := p.Filesystem.QEMUFilesystem()
|
|
fs = &f
|
|
}
|
|
return osbuild.QEMUPartition{
|
|
Start: p.Start,
|
|
Size: p.Size,
|
|
Type: p.Type,
|
|
Bootable: p.Bootable,
|
|
UUID: p.UUID,
|
|
Filesystem: fs,
|
|
}
|
|
}
|
|
|
|
// Converts Filesystem to osbuild.QEMUFilesystem that encodes the same fs.
|
|
func (fs Filesystem) QEMUFilesystem() osbuild.QEMUFilesystem {
|
|
return osbuild.QEMUFilesystem{
|
|
Type: fs.Type,
|
|
UUID: fs.UUID,
|
|
Label: fs.Label,
|
|
Mountpoint: fs.Mountpoint,
|
|
}
|
|
}
|