mirror of
https://github.com/kairos-io/kairos-sdk.git
synced 2025-09-07 02:00:20 +00:00
108 lines
3.6 KiB
Go
108 lines
3.6 KiB
Go
package ghw
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/kairos-io/kairos-sdk/types"
|
|
)
|
|
|
|
type MultipathPartitionHandler struct {
|
|
DiskName string
|
|
}
|
|
|
|
func NewMultipathPartitionHandler(diskName string) *MultipathPartitionHandler {
|
|
return &MultipathPartitionHandler{DiskName: diskName}
|
|
}
|
|
|
|
var _ PartitionHandler = &MultipathPartitionHandler{}
|
|
|
|
func (m *MultipathPartitionHandler) GetPartitions(paths *Paths, logger *types.KairosLogger) types.PartitionList {
|
|
out := make(types.PartitionList, 0)
|
|
|
|
// For multipath devices, partitions appear as holders of the parent device
|
|
// in /sys/block/<disk>/holders/<holder>
|
|
holdersPath := filepath.Join(paths.SysBlock, m.DiskName, "holders")
|
|
logger.Logger.Debug().Str("path", holdersPath).Msg("Reading multipath holders")
|
|
|
|
holders, err := os.ReadDir(holdersPath)
|
|
if err != nil {
|
|
logger.Logger.Error().Err(err).Msg("failed to read holders directory")
|
|
return out
|
|
}
|
|
|
|
// Find all multipath partitions by checking each holder
|
|
for _, holder := range holders {
|
|
partName := holder.Name()
|
|
|
|
// Only consider dm- devices as potential multipath partitions
|
|
if !isMultipathDevice(paths, holder, logger) {
|
|
logger.Logger.Debug().Str("path", holder.Name()).Msg("Is not a multipath device")
|
|
continue
|
|
}
|
|
|
|
// Verify this holder is actually a multipath partition
|
|
// We can use the holder DirEntry directly - no need to search for it!
|
|
if !isMultipathPartition(holder, paths, logger) {
|
|
logger.Logger.Debug().Str("partition", partName).Msg("Holder is not a multipath partition")
|
|
continue
|
|
}
|
|
|
|
logger.Logger.Debug().Str("partition", partName).Msg("Found multipath partition")
|
|
|
|
udevInfo, err := udevInfoPartition(paths, partName, logger)
|
|
if err != nil {
|
|
logger.Logger.Error().Err(err).Str("devNo", partName).Msg("Failed to get udev info")
|
|
return out
|
|
}
|
|
|
|
mapperName, ok := udevInfo["DM_NAME"]
|
|
if !ok {
|
|
logger.Logger.Error().Str("devNo", partName).Msg("DM_NAME not found in udev info")
|
|
continue
|
|
}
|
|
|
|
// For multipath partitions, we need to get size directly from the partition device
|
|
// since it's a top-level entry in /sys/block, not nested under the parent
|
|
size := partitionSizeBytes(paths, partName, logger)
|
|
du := diskPartUUID(paths, partName, logger)
|
|
|
|
// The mount point is usually the same as the mapper name
|
|
// however you can also mount it as /dev/dm-<n> or /dev/mapper/<mapperName>
|
|
// so we need to check both
|
|
potentialMountNames := []string{
|
|
filepath.Join("/dev/mapper", mapperName),
|
|
filepath.Join("/dev", partName),
|
|
}
|
|
|
|
// Search for the mount point in the system
|
|
var mp, pt string
|
|
for _, mountName := range potentialMountNames {
|
|
mp, pt = partitionInfo(paths, mountName, logger)
|
|
if mp != "" {
|
|
logger.Logger.Debug().Str("mountPoint", mp).Msg("Found mount point for partition")
|
|
break
|
|
}
|
|
}
|
|
|
|
if pt == "" {
|
|
pt = diskPartTypeUdev(paths, partName, logger)
|
|
}
|
|
fsLabel := diskFSLabel(paths, partName, logger)
|
|
|
|
p := &types.Partition{
|
|
Name: partName,
|
|
Size: uint(size / (1024 * 1024)),
|
|
MountPoint: mp,
|
|
UUID: du,
|
|
FilesystemLabel: fsLabel,
|
|
FS: pt,
|
|
Path: filepath.Join("/dev", partName),
|
|
Disk: filepath.Join("/dev", m.DiskName),
|
|
}
|
|
out = append(out, p)
|
|
}
|
|
|
|
return out
|
|
}
|