feat: skip filesystem for state and ephemeral partitions in the installer
Filesystem creation step is moved on the later stage: when Talos mounts the partition for the first time. Now it checks if the partition doesn't have any filesystem and formats it right before mounting. Additionally refactored mount options a bit: - replaced separate options with a set of binary flags. - implemented pre-mount and post-unmount hooks. And fixed typos in couple of places and increased timeout for `apid ready`. Signed-off-by: Artem Chernyshev <artem.0xD2@gmail.com>
This commit is contained in:
parent
edbaa0bc72
commit
02b3719df9
@ -182,10 +182,51 @@ func (i *Installer) Install(seq runtime.Sequence) (err error) {
|
||||
}
|
||||
|
||||
// Mount the partitions.
|
||||
mountpoints := mount.NewMountPoints()
|
||||
|
||||
mountpoints, err := i.manifest.SystemMountpoints()
|
||||
if err != nil {
|
||||
return err
|
||||
for _, label := range []string{constants.BootPartitionLabel, constants.EFIPartitionLabel} {
|
||||
err = func() error {
|
||||
var device string
|
||||
// searching targets for the device to be used
|
||||
OuterLoop:
|
||||
for dev, targets := range i.manifest.Targets {
|
||||
for _, target := range targets {
|
||||
if target.Label == label {
|
||||
device = dev
|
||||
|
||||
break OuterLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if device == "" {
|
||||
return fmt.Errorf("failed to detect %s target device", label)
|
||||
}
|
||||
|
||||
var bd *blockdevice.BlockDevice
|
||||
|
||||
bd, err = blockdevice.Open(device)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer bd.Close() //nolint:errcheck
|
||||
|
||||
var mountpoint *mount.Point
|
||||
|
||||
mountpoint, err = mount.SystemMountPointForLabel(bd, label)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mountpoints.Set(label, mountpoint)
|
||||
|
||||
return nil
|
||||
}()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err = mount.Mount(mountpoints); err != nil {
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/talos-systems/go-blockdevice/blockdevice"
|
||||
"github.com/talos-systems/go-blockdevice/blockdevice/partition/gpt"
|
||||
"github.com/talos-systems/go-blockdevice/blockdevice/util"
|
||||
@ -22,6 +23,7 @@ import (
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/board"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount"
|
||||
"github.com/talos-systems/talos/internal/pkg/partition"
|
||||
"github.com/talos-systems/talos/pkg/machinery/constants"
|
||||
)
|
||||
|
||||
@ -131,16 +133,12 @@ func NewManifest(label string, sequence runtime.Sequence, bootPartitionFound boo
|
||||
|
||||
stateTarget := StateTarget(opts.Disk, &Target{
|
||||
PreserveContents: bootPartitionFound,
|
||||
ExtraPreserveSources: []PreserveSource{
|
||||
{
|
||||
Label: constants.LegacyBootPartitionLabel,
|
||||
FileSystemType: FilesystemTypeVFAT,
|
||||
FnmatchFilters: []string{"config.yaml"},
|
||||
},
|
||||
FormatOptions: &partition.FormatOptions{
|
||||
FileSystemType: partition.FilesystemTypeNone,
|
||||
},
|
||||
})
|
||||
|
||||
ephemeralTarget := EphemeralTarget(opts.Disk, nil)
|
||||
ephemeralTarget := EphemeralTarget(opts.Disk, NoFilesystem)
|
||||
|
||||
if opts.Force {
|
||||
ephemeralTarget.Force = true
|
||||
@ -417,7 +415,7 @@ func (m *Manifest) preserveContents(device Device, targets []*Target) (err error
|
||||
|
||||
var (
|
||||
sourcePart *gpt.Partition
|
||||
fileSystemType FileSystemType
|
||||
fileSystemType partition.FileSystemType
|
||||
fnmatchFilters []string
|
||||
)
|
||||
|
||||
@ -466,11 +464,11 @@ func (m *Manifest) restoreContents(targets []*Target) error {
|
||||
}
|
||||
|
||||
// SystemMountpoints returns list of system mountpoints for the manifest.
|
||||
func (m *Manifest) SystemMountpoints() (*mount.Points, error) {
|
||||
func (m *Manifest) SystemMountpoints(opts ...mount.Option) (*mount.Points, error) {
|
||||
mountpoints := mount.NewMountPoints()
|
||||
|
||||
for dev := range m.Targets {
|
||||
mp, err := mount.SystemMountPointsForDevice(dev)
|
||||
mp, err := mount.SystemMountPointsForDevice(dev, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -511,12 +509,7 @@ func (m *Manifest) zeroDevice(device Device) (err error) {
|
||||
// nolint: dupl, gocyclo
|
||||
func (t *Target) Partition(pt *gpt.GPT, pos int, bd *blockdevice.BlockDevice) (err error) {
|
||||
if t.Skip {
|
||||
var part *gpt.Partition
|
||||
|
||||
part, err = t.Locate(pt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
part := pt.Partitions().FindByName(t.Label)
|
||||
|
||||
if part != nil {
|
||||
log.Printf("skipped %s (%s) size %d blocks", t.PartitionName, t.Label, part.Length())
|
||||
@ -525,7 +518,7 @@ func (t *Target) Partition(pt *gpt.GPT, pos int, bd *blockdevice.BlockDevice) (e
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Printf("partitioning %s - %s\n", t.Device, t.Label)
|
||||
log.Printf("partitioning %s - %s %q\n", t.Device, t.Label, humanize.Bytes(t.Size))
|
||||
|
||||
opts := []gpt.PartitionOption{
|
||||
gpt.WithPartitionType(t.PartitionType),
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"github.com/talos-systems/talos/cmd/installer/pkg/install"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount"
|
||||
"github.com/talos-systems/talos/internal/pkg/partition"
|
||||
"github.com/talos-systems/talos/pkg/machinery/constants"
|
||||
"github.com/talos-systems/talos/pkg/makefs"
|
||||
)
|
||||
@ -45,7 +46,7 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
legacyBootSize = 512 * install.MiB
|
||||
legacyBootSize = 512 * partition.MiB
|
||||
legacyEphemeralSize = diskSize - legacyBootSize - gptReserved*lbaSize
|
||||
)
|
||||
|
||||
@ -112,47 +113,47 @@ func (suite *manifestSuite) verifyBlockdevice(manifest *install.Manifest, curren
|
||||
suite.Assert().Len(table.Partitions().Items(), 6)
|
||||
|
||||
part := table.Partitions().Items()[0]
|
||||
suite.Assert().Equal(install.EFISystemPartition, strings.ToUpper(part.Type.String()))
|
||||
suite.Assert().Equal(partition.EFISystemPartition, strings.ToUpper(part.Type.String()))
|
||||
suite.Assert().Equal(constants.EFIPartitionLabel, part.Name)
|
||||
suite.Assert().EqualValues(0, part.Attributes)
|
||||
suite.Assert().EqualValues(install.EFISize/lbaSize, part.Length())
|
||||
suite.Assert().EqualValues(partition.EFISize/lbaSize, part.Length())
|
||||
|
||||
part = table.Partitions().Items()[1]
|
||||
suite.Assert().Equal(install.BIOSBootPartition, strings.ToUpper(part.Type.String()))
|
||||
suite.Assert().Equal(partition.BIOSBootPartition, strings.ToUpper(part.Type.String()))
|
||||
suite.Assert().Equal(constants.BIOSGrubPartitionLabel, part.Name)
|
||||
suite.Assert().EqualValues(4, part.Attributes)
|
||||
suite.Assert().EqualValues(install.BIOSGrubSize/lbaSize, part.Length())
|
||||
suite.Assert().EqualValues(partition.BIOSGrubSize/lbaSize, part.Length())
|
||||
|
||||
part = table.Partitions().Items()[2]
|
||||
suite.Assert().Equal(install.LinuxFilesystemData, strings.ToUpper(part.Type.String()))
|
||||
suite.Assert().Equal(partition.LinuxFilesystemData, strings.ToUpper(part.Type.String()))
|
||||
suite.Assert().Equal(constants.BootPartitionLabel, part.Name)
|
||||
suite.Assert().EqualValues(0, part.Attributes)
|
||||
suite.Assert().EqualValues(install.BootSize/lbaSize, part.Length())
|
||||
suite.Assert().EqualValues(partition.BootSize/lbaSize, part.Length())
|
||||
|
||||
part = table.Partitions().Items()[3]
|
||||
suite.Assert().Equal(install.LinuxFilesystemData, strings.ToUpper(part.Type.String()))
|
||||
suite.Assert().Equal(partition.LinuxFilesystemData, strings.ToUpper(part.Type.String()))
|
||||
suite.Assert().Equal(constants.MetaPartitionLabel, part.Name)
|
||||
suite.Assert().EqualValues(0, part.Attributes)
|
||||
suite.Assert().EqualValues(install.MetaSize/lbaSize, part.Length())
|
||||
suite.Assert().EqualValues(partition.MetaSize/lbaSize, part.Length())
|
||||
|
||||
part = table.Partitions().Items()[4]
|
||||
suite.Assert().Equal(install.LinuxFilesystemData, strings.ToUpper(part.Type.String()))
|
||||
suite.Assert().Equal(partition.LinuxFilesystemData, strings.ToUpper(part.Type.String()))
|
||||
suite.Assert().Equal(constants.StatePartitionLabel, part.Name)
|
||||
suite.Assert().EqualValues(0, part.Attributes)
|
||||
|
||||
if !upgradeFromLegacy {
|
||||
suite.Assert().EqualValues(install.StateSize/lbaSize, part.Length())
|
||||
suite.Assert().EqualValues(partition.StateSize/lbaSize, part.Length())
|
||||
} else {
|
||||
suite.Assert().EqualValues((diskSize-legacyEphemeralSize-install.EFISize-install.BIOSGrubSize-install.BootSize-install.MetaSize)/lbaSize-gptReserved, part.Length())
|
||||
suite.Assert().EqualValues((diskSize-legacyEphemeralSize-partition.EFISize-partition.BIOSGrubSize-partition.BootSize-partition.MetaSize)/lbaSize-gptReserved, part.Length())
|
||||
}
|
||||
|
||||
part = table.Partitions().Items()[5]
|
||||
suite.Assert().Equal(install.LinuxFilesystemData, strings.ToUpper(part.Type.String()))
|
||||
suite.Assert().Equal(partition.LinuxFilesystemData, strings.ToUpper(part.Type.String()))
|
||||
suite.Assert().Equal(constants.EphemeralPartitionLabel, part.Name)
|
||||
suite.Assert().EqualValues(0, part.Attributes)
|
||||
|
||||
if !upgradeFromLegacy {
|
||||
suite.Assert().EqualValues((diskSize-install.EFISize-install.BIOSGrubSize-install.BootSize-install.MetaSize-install.StateSize)/lbaSize-gptReserved, part.Length())
|
||||
suite.Assert().EqualValues((diskSize-partition.EFISize-partition.BIOSGrubSize-partition.BootSize-partition.MetaSize-partition.StateSize)/lbaSize-gptReserved, part.Length())
|
||||
} else {
|
||||
suite.Assert().EqualValues(legacyEphemeralSize/lbaSize, part.Length())
|
||||
}
|
||||
@ -399,7 +400,7 @@ func (suite *manifestSuite) createTalosLegacyLayout() {
|
||||
table, err := gpt.New(bd.Device())
|
||||
suite.Require().NoError(err)
|
||||
|
||||
partBoot, err := table.Add(512*install.MiB,
|
||||
partBoot, err := table.Add(512*partition.MiB,
|
||||
gpt.WithLegacyBIOSBootableAttribute(true),
|
||||
gpt.WithPartitionName(constants.LegacyBootPartitionLabel),
|
||||
gpt.WithPartitionType("28732AC1-1FF8-D211-BA4B-00A0C93EC93B"),
|
||||
@ -437,8 +438,8 @@ func (suite *manifestSuite) createTalosLegacyLayout() {
|
||||
}()
|
||||
|
||||
mountpoints := mount.NewMountPoints()
|
||||
mountpoints.Set(constants.LegacyBootPartitionLabel, mount.NewMountPoint(partBootPath, filepath.Join(tempDir, "boot"), install.FilesystemTypeVFAT, 0, ""))
|
||||
mountpoints.Set(constants.EphemeralPartitionLabel, mount.NewMountPoint(partEphemeralPath, filepath.Join(tempDir, "var"), install.FilesystemTypeXFS, 0, ""))
|
||||
mountpoints.Set(constants.LegacyBootPartitionLabel, mount.NewMountPoint(partBootPath, filepath.Join(tempDir, "boot"), partition.FilesystemTypeVFAT, 0, ""))
|
||||
mountpoints.Set(constants.EphemeralPartitionLabel, mount.NewMountPoint(partEphemeralPath, filepath.Join(tempDir, "var"), partition.FilesystemTypeXFS, 0, ""))
|
||||
|
||||
err = mount.Mount(mountpoints)
|
||||
suite.Require().NoError(err)
|
||||
|
@ -19,24 +19,20 @@ import (
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/talos-systems/talos/internal/pkg/mount"
|
||||
"github.com/talos-systems/talos/internal/pkg/partition"
|
||||
"github.com/talos-systems/talos/pkg/archiver"
|
||||
"github.com/talos-systems/talos/pkg/machinery/constants"
|
||||
"github.com/talos-systems/talos/pkg/makefs"
|
||||
)
|
||||
|
||||
// Target represents an installation partition.
|
||||
//
|
||||
//nolint: golint, maligned
|
||||
type Target struct {
|
||||
*partition.FormatOptions
|
||||
Device string
|
||||
|
||||
Label string
|
||||
PartitionType PartitionType
|
||||
FileSystemType FileSystemType
|
||||
LegacyBIOSBootable bool
|
||||
|
||||
Size uint64
|
||||
Force bool
|
||||
Assets []*Asset
|
||||
|
||||
// Preserve contents of the partition with the same label (if it exists).
|
||||
@ -67,18 +63,21 @@ type Asset struct {
|
||||
type PreserveSource struct {
|
||||
Label string
|
||||
FnmatchFilters []string
|
||||
FileSystemType FileSystemType
|
||||
FileSystemType partition.FileSystemType
|
||||
}
|
||||
|
||||
// NoFilesystem preset to override default filesystem type to none.
|
||||
var NoFilesystem = &Target{
|
||||
FormatOptions: &partition.FormatOptions{
|
||||
FileSystemType: partition.FilesystemTypeNone,
|
||||
},
|
||||
}
|
||||
|
||||
// EFITarget builds the default EFI target.
|
||||
func EFITarget(device string, extra *Target) *Target {
|
||||
target := &Target{
|
||||
Device: device,
|
||||
Label: constants.EFIPartitionLabel,
|
||||
PartitionType: EFISystemPartition,
|
||||
FileSystemType: FilesystemTypeVFAT,
|
||||
Size: EFISize,
|
||||
Force: true,
|
||||
FormatOptions: partition.NewFormatOptions(constants.EFIPartitionLabel),
|
||||
Device: device,
|
||||
}
|
||||
|
||||
return target.enhance(extra)
|
||||
@ -87,13 +86,9 @@ func EFITarget(device string, extra *Target) *Target {
|
||||
// BIOSTarget builds the default BIOS target.
|
||||
func BIOSTarget(device string, extra *Target) *Target {
|
||||
target := &Target{
|
||||
FormatOptions: partition.NewFormatOptions(constants.BIOSGrubPartitionLabel),
|
||||
Device: device,
|
||||
Label: constants.BIOSGrubPartitionLabel,
|
||||
PartitionType: BIOSBootPartition,
|
||||
FileSystemType: FilesystemTypeNone,
|
||||
LegacyBIOSBootable: true,
|
||||
Size: BIOSGrubSize,
|
||||
Force: true,
|
||||
}
|
||||
|
||||
return target.enhance(extra)
|
||||
@ -102,12 +97,8 @@ func BIOSTarget(device string, extra *Target) *Target {
|
||||
// BootTarget builds the default boot target.
|
||||
func BootTarget(device string, extra *Target) *Target {
|
||||
target := &Target{
|
||||
Device: device,
|
||||
Label: constants.BootPartitionLabel,
|
||||
PartitionType: LinuxFilesystemData,
|
||||
FileSystemType: FilesystemTypeXFS,
|
||||
Size: BootSize,
|
||||
Force: true,
|
||||
FormatOptions: partition.NewFormatOptions(constants.BootPartitionLabel),
|
||||
Device: device,
|
||||
}
|
||||
|
||||
return target.enhance(extra)
|
||||
@ -116,12 +107,8 @@ func BootTarget(device string, extra *Target) *Target {
|
||||
// MetaTarget builds the default meta target.
|
||||
func MetaTarget(device string, extra *Target) *Target {
|
||||
target := &Target{
|
||||
Device: device,
|
||||
Label: constants.MetaPartitionLabel,
|
||||
PartitionType: LinuxFilesystemData,
|
||||
FileSystemType: FilesystemTypeNone,
|
||||
Size: MetaSize,
|
||||
Force: true,
|
||||
FormatOptions: partition.NewFormatOptions(constants.MetaPartitionLabel),
|
||||
Device: device,
|
||||
}
|
||||
|
||||
return target.enhance(extra)
|
||||
@ -130,12 +117,8 @@ func MetaTarget(device string, extra *Target) *Target {
|
||||
// StateTarget builds the default state target.
|
||||
func StateTarget(device string, extra *Target) *Target {
|
||||
target := &Target{
|
||||
Device: device,
|
||||
Label: constants.StatePartitionLabel,
|
||||
PartitionType: LinuxFilesystemData,
|
||||
FileSystemType: FilesystemTypeXFS,
|
||||
Size: StateSize,
|
||||
Force: true,
|
||||
FormatOptions: partition.NewFormatOptions(constants.StatePartitionLabel),
|
||||
Device: device,
|
||||
}
|
||||
|
||||
return target.enhance(extra)
|
||||
@ -144,12 +127,8 @@ func StateTarget(device string, extra *Target) *Target {
|
||||
// EphemeralTarget builds the default ephemeral target.
|
||||
func EphemeralTarget(device string, extra *Target) *Target {
|
||||
target := &Target{
|
||||
Device: device,
|
||||
Label: constants.EphemeralPartitionLabel,
|
||||
PartitionType: LinuxFilesystemData,
|
||||
FileSystemType: FilesystemTypeXFS,
|
||||
Size: 0,
|
||||
Force: true,
|
||||
FormatOptions: partition.NewFormatOptions(constants.EphemeralPartitionLabel),
|
||||
Device: device,
|
||||
}
|
||||
|
||||
return target.enhance(extra)
|
||||
@ -165,6 +144,10 @@ func (t *Target) enhance(extra *Target) *Target {
|
||||
t.ExtraPreserveSources = extra.ExtraPreserveSources
|
||||
t.Skip = extra.Skip
|
||||
|
||||
if extra.FormatOptions != nil {
|
||||
t.FormatOptions.FileSystemType = extra.FormatOptions.FileSystemType
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
@ -198,22 +181,7 @@ func (t *Target) Format() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if t.FileSystemType == FilesystemTypeNone {
|
||||
return t.zeroPartition()
|
||||
}
|
||||
|
||||
log.Printf("formatting partition %q as %q with label %q\n", t.PartitionName, t.FileSystemType, t.Label)
|
||||
|
||||
opts := []makefs.Option{makefs.WithForce(t.Force), makefs.WithLabel(t.Label)}
|
||||
|
||||
switch t.FileSystemType {
|
||||
case FilesystemTypeVFAT:
|
||||
return makefs.VFAT(t.PartitionName, opts...)
|
||||
case FilesystemTypeXFS:
|
||||
return makefs.XFS(t.PartitionName, opts...)
|
||||
default:
|
||||
return fmt.Errorf("unsupported filesystem type: %q", t.FileSystemType)
|
||||
}
|
||||
return partition.Format(t.PartitionName, t.FormatOptions)
|
||||
}
|
||||
|
||||
// Save copies the assets to the bootloader partition.
|
||||
@ -275,7 +243,7 @@ func (t *Target) Save() (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func withTemporaryMounted(partPath string, flags uintptr, fileSystemType FileSystemType, label string, f func(mountPath string) error) error {
|
||||
func withTemporaryMounted(partPath string, flags uintptr, fileSystemType partition.FileSystemType, label string, f func(mountPath string) error) error {
|
||||
mountPath := filepath.Join(constants.SystemPath, "mnt")
|
||||
|
||||
mountpoints := mount.NewMountPoints()
|
||||
@ -297,13 +265,13 @@ func withTemporaryMounted(partPath string, flags uintptr, fileSystemType FileSys
|
||||
}
|
||||
|
||||
// SaveContents saves contents of partition to the target (in-memory).
|
||||
func (t *Target) SaveContents(device Device, source *gpt.Partition, fileSystemType FileSystemType, fnmatchFilters []string) error {
|
||||
func (t *Target) SaveContents(device Device, source *gpt.Partition, fileSystemType partition.FileSystemType, fnmatchFilters []string) error {
|
||||
partPath, err := util.PartPath(device.Device, int(source.Number))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if fileSystemType == FilesystemTypeNone {
|
||||
if fileSystemType == partition.FilesystemTypeNone {
|
||||
err = t.saveRawContents(partPath)
|
||||
} else {
|
||||
err = t.saveFilesystemContents(partPath, fileSystemType, fnmatchFilters)
|
||||
@ -341,7 +309,7 @@ func (t *Target) saveRawContents(partPath string) error {
|
||||
return src.Close()
|
||||
}
|
||||
|
||||
func (t *Target) saveFilesystemContents(partPath string, fileSystemType FileSystemType, fnmatchFilters []string) error {
|
||||
func (t *Target) saveFilesystemContents(partPath string, fileSystemType partition.FileSystemType, fnmatchFilters []string) error {
|
||||
t.Contents = bytes.NewBuffer(nil)
|
||||
|
||||
return withTemporaryMounted(partPath, unix.MS_RDONLY, fileSystemType, t.Label, func(mountPath string) error {
|
||||
@ -357,7 +325,7 @@ func (t *Target) RestoreContents() error {
|
||||
|
||||
var err error
|
||||
|
||||
if t.FileSystemType == FilesystemTypeNone {
|
||||
if t.FileSystemType == partition.FilesystemTypeNone {
|
||||
err = t.restoreRawContents()
|
||||
} else {
|
||||
err = t.restoreFilesystemContents()
|
||||
@ -400,26 +368,3 @@ func (t *Target) restoreFilesystemContents() error {
|
||||
return archiver.UntarGz(context.TODO(), t.Contents, mountPath)
|
||||
})
|
||||
}
|
||||
|
||||
// zeroPartition fills the partition with zeroes.
|
||||
func (t *Target) zeroPartition() (err error) {
|
||||
log.Printf("zeroing out %q", t.PartitionName)
|
||||
|
||||
zeroes, err := os.Open("/dev/zero")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer zeroes.Close() //nolint: errcheck
|
||||
|
||||
part, err := os.OpenFile(t.PartitionName, os.O_WRONLY, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer part.Close() //nolint: errcheck
|
||||
|
||||
_, err = io.CopyN(part, zeroes, int64(t.Size))
|
||||
|
||||
return err
|
||||
}
|
||||
|
2
go.mod
2
go.mod
@ -64,7 +64,7 @@ require (
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2
|
||||
github.com/talos-systems/crypto v0.2.1-0.20210202170911-39584f1b6e54
|
||||
github.com/talos-systems/go-blockdevice v0.2.0
|
||||
github.com/talos-systems/go-blockdevice v0.2.1-0.20210216182145-8f976c203110
|
||||
github.com/talos-systems/go-cmd v0.0.0-20210216164758-68eb0067e0f0
|
||||
github.com/talos-systems/go-loadbalancer v0.1.0
|
||||
github.com/talos-systems/go-procfs v0.0.0-20210108152626-8cbc42d3dc24
|
||||
|
4
go.sum
4
go.sum
@ -868,9 +868,9 @@ github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 h1:b6uOv7YOFK0
|
||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/talos-systems/crypto v0.2.1-0.20210202170911-39584f1b6e54 h1:2IGs3f0qG7f33Fv37XuYzIMxLARl4dcpwahZXLmdT2A=
|
||||
github.com/talos-systems/crypto v0.2.1-0.20210202170911-39584f1b6e54/go.mod h1:OXCK52Q0dzm88YRG4VdTBdidkPUtqrCxCyW7bUs4DAw=
|
||||
github.com/talos-systems/go-blockdevice v0.2.0 h1:tTu0ak3GfF8iSxNsdsicVhTKebIcyBARQYxhRV86AF0=
|
||||
github.com/talos-systems/go-blockdevice v0.2.0/go.mod h1:DGbop5CJa0PYdhQK9cNVF61pPJNedas1m7Gi/qAnrsM=
|
||||
github.com/talos-systems/go-cmd v0.0.0-20210216164758-68eb0067e0f0 h1:DI+BjK+fcrLBc70Fi50dZocQcaHosqsuWHrGHKp2NzE=
|
||||
github.com/talos-systems/go-blockdevice v0.2.1-0.20210216182145-8f976c203110 h1:qyJ+0mNpddRvt2KRGOGU3KFIFFVWuP7KjYgnn3aVbqk=
|
||||
github.com/talos-systems/go-blockdevice v0.2.1-0.20210216182145-8f976c203110/go.mod h1:Wt0/JMsa+WysYRDlNo6fu9rdn/re73uRnktFWyVUqjs=
|
||||
github.com/talos-systems/go-cmd v0.0.0-20210216164758-68eb0067e0f0/go.mod h1:kf+rZzTEmlDiYQ6ulslvRONnKLQH8x83TowltGMhO+k=
|
||||
github.com/talos-systems/go-loadbalancer v0.1.0 h1:MQFONvSjoleU8RrKq1O1Z8CyTCJGd4SLqdAHDlR6o9s=
|
||||
github.com/talos-systems/go-loadbalancer v0.1.0/go.mod h1:D5Qjfz+29WVjONWECZvOkmaLsBb3f5YeWME0u/5HmIc=
|
||||
|
@ -498,9 +498,9 @@ func (s *Server) Reset(ctx context.Context, in *machine.ResetRequest) (reply *ma
|
||||
case constants.MetaPartitionLabel:
|
||||
target = installer.MetaTarget(bd.Device().Name(), nil)
|
||||
case constants.StatePartitionLabel:
|
||||
target = installer.StateTarget(bd.Device().Name(), nil)
|
||||
target = installer.StateTarget(bd.Device().Name(), installer.NoFilesystem)
|
||||
case constants.EphemeralPartitionLabel:
|
||||
target = installer.EphemeralTarget(bd.Device().Name(), nil)
|
||||
target = installer.EphemeralTarget(bd.Device().Name(), installer.NoFilesystem)
|
||||
default:
|
||||
return nil, fmt.Errorf("label %q is not supported", spec.Label)
|
||||
}
|
||||
|
@ -213,7 +213,7 @@ func (*Sequencer) Boot(r runtime.Runtime) []runtime.Phase {
|
||||
).AppendWhen(
|
||||
r.State().Platform().Mode() != runtime.ModeContainer,
|
||||
"ephemeral",
|
||||
MountEphermeralPartition,
|
||||
MountEphemeralPartition,
|
||||
).AppendWhen(
|
||||
r.State().Platform().Mode() != runtime.ModeContainer,
|
||||
"verifyInstall",
|
||||
|
@ -54,6 +54,7 @@ import (
|
||||
"github.com/talos-systems/talos/internal/pkg/kernel/kspp"
|
||||
"github.com/talos-systems/talos/internal/pkg/kmsg"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount"
|
||||
"github.com/talos-systems/talos/internal/pkg/partition"
|
||||
"github.com/talos-systems/talos/pkg/conditions"
|
||||
"github.com/talos-systems/talos/pkg/images"
|
||||
"github.com/talos-systems/talos/pkg/kubernetes"
|
||||
@ -882,11 +883,13 @@ func partitionAndFormatDisks(logger *log.Logger, r runtime.Runtime) error {
|
||||
|
||||
for _, part := range disk.Partitions() {
|
||||
extraTarget := &installer.Target{
|
||||
Device: disk.Device(),
|
||||
Size: part.Size(),
|
||||
Force: true,
|
||||
PartitionType: installer.LinuxFilesystemData,
|
||||
FileSystemType: installer.FilesystemTypeXFS,
|
||||
Device: disk.Device(),
|
||||
FormatOptions: &partition.FormatOptions{
|
||||
Size: part.Size(),
|
||||
Force: true,
|
||||
PartitionType: partition.LinuxFilesystemData,
|
||||
FileSystemType: partition.FilesystemTypeXFS,
|
||||
},
|
||||
}
|
||||
|
||||
m.Targets[disk.Device()] = append(m.Targets[disk.Device()], extraTarget)
|
||||
@ -1580,7 +1583,7 @@ func UnmountEFIPartition(seq runtime.Sequence, data interface{}) (runtime.TaskEx
|
||||
// MountStatePartition mounts the system partition.
|
||||
func MountStatePartition(seq runtime.Sequence, data interface{}) (runtime.TaskExecutionFunc, string) {
|
||||
return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) (err error) {
|
||||
return mount.SystemPartitionMount(r, constants.StatePartitionLabel, mount.WithSkipIfMounted(true))
|
||||
return mount.SystemPartitionMount(r, constants.StatePartitionLabel, mount.WithFlags(mount.SkipIfMounted))
|
||||
}, "mountStatePartition"
|
||||
}
|
||||
|
||||
@ -1591,11 +1594,11 @@ func UnmountStatePartition(seq runtime.Sequence, data interface{}) (runtime.Task
|
||||
}, "unmountStatePartition"
|
||||
}
|
||||
|
||||
// MountEphermeralPartition mounts the ephemeral partition.
|
||||
func MountEphermeralPartition(seq runtime.Sequence, data interface{}) (runtime.TaskExecutionFunc, string) {
|
||||
// MountEphemeralPartition mounts the ephemeral partition.
|
||||
func MountEphemeralPartition(seq runtime.Sequence, data interface{}) (runtime.TaskExecutionFunc, string) {
|
||||
return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) error {
|
||||
return mount.SystemPartitionMount(r, constants.EphemeralPartitionLabel, mount.WithResize(true))
|
||||
}, "mountEphermeralPartition"
|
||||
return mount.SystemPartitionMount(r, constants.EphemeralPartitionLabel, mount.WithFlags(mount.Resize))
|
||||
}, "mountEphemeralPartition"
|
||||
}
|
||||
|
||||
// UnmountEphemeralPartition unmounts the ephemeral partition.
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
// +build integration
|
||||
|
||||
// Package provision provides integration tests which rely on on provisioning cluster per test.
|
||||
// Package provision provides integration tests which rely on provisioning cluster per test.
|
||||
package provision
|
||||
|
||||
import (
|
||||
|
@ -403,7 +403,7 @@ func (suite *UpgradeSuite) waitForClusterHealth() {
|
||||
time.Sleep(15 * time.Second)
|
||||
}
|
||||
|
||||
checkCtx, checkCtxCancel := context.WithTimeout(suite.ctx, 10*time.Minute)
|
||||
checkCtx, checkCtxCancel := context.WithTimeout(suite.ctx, 15*time.Minute)
|
||||
defer checkCtxCancel()
|
||||
|
||||
suite.Require().NoError(check.Wait(checkCtx, suite.clusterAccess, check.DefaultClusterChecks(), check.StderrReporter()))
|
||||
|
@ -48,13 +48,13 @@ func mountMountpoint(mountpoint *Point) (err error) {
|
||||
var skipMount bool
|
||||
|
||||
// Repair the disk's partition table.
|
||||
if mountpoint.Resize {
|
||||
if mountpoint.MountFlags.Check(Resize) {
|
||||
if _, err = mountpoint.ResizePartition(); err != nil {
|
||||
return fmt.Errorf("error resizing %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if mountpoint.SkipIfMounted {
|
||||
if mountpoint.MountFlags.Check(SkipIfMounted) {
|
||||
skipMount, err = mountpoint.IsMounted()
|
||||
if err != nil {
|
||||
return fmt.Errorf("mountpoint is set to skip if mounted, but the mount check failed: %w", err)
|
||||
@ -71,7 +71,7 @@ func mountMountpoint(mountpoint *Point) (err error) {
|
||||
//
|
||||
// Growfs is called always, even if ResizePartition returns false to workaround failure scenario
|
||||
// when partition was resized, but growfs never got called.
|
||||
if mountpoint.Resize {
|
||||
if mountpoint.MountFlags.Check(Resize) {
|
||||
if err = mountpoint.GrowFilesystem(); err != nil {
|
||||
return fmt.Errorf("error resizing filesystem: %w", err)
|
||||
}
|
||||
@ -226,16 +226,22 @@ func (p *Point) Data() string {
|
||||
func (p *Point) Mount() (err error) {
|
||||
p.target = path.Join(p.Prefix, p.target)
|
||||
|
||||
for _, hook := range p.Options.PreMountHooks {
|
||||
if err = hook(p); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err = ensureDirectory(p.target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.ReadOnly {
|
||||
if p.MountFlags.Check(ReadOnly) {
|
||||
p.flags |= unix.MS_RDONLY
|
||||
}
|
||||
|
||||
switch {
|
||||
case p.Overlay:
|
||||
case p.MountFlags.Check(Overlay):
|
||||
err = mountRetry(overlay, p, false)
|
||||
default:
|
||||
err = mountRetry(mount, p, false)
|
||||
@ -245,7 +251,7 @@ func (p *Point) Mount() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.Shared {
|
||||
if p.MountFlags.Check(Shared) {
|
||||
if err = mountRetry(share, p, false); err != nil {
|
||||
return fmt.Errorf("error sharing mount point %s: %+v", p.target, err)
|
||||
}
|
||||
@ -257,11 +263,25 @@ func (p *Point) Mount() (err error) {
|
||||
// Unmount attempts to retry an unmount on EBUSY. It will attempt a
|
||||
// retry every 100 milliseconds over the course of 5 seconds.
|
||||
func (p *Point) Unmount() (err error) {
|
||||
p.target = path.Join(p.Prefix, p.target)
|
||||
if err := mountRetry(unmount, p, true); err != nil {
|
||||
var mounted bool
|
||||
|
||||
if mounted, err = p.IsMounted(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if mounted {
|
||||
p.target = path.Join(p.Prefix, p.target)
|
||||
if err = mountRetry(unmount, p, true); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, hook := range p.Options.PostUnmountHooks {
|
||||
if err = hook(p); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -4,20 +4,46 @@
|
||||
|
||||
package mount
|
||||
|
||||
const (
|
||||
// ReadOnly is a flag for setting the mount point as readonly.
|
||||
ReadOnly Flags = 1 << iota
|
||||
// Shared is a flag for setting the mount point as shared.
|
||||
Shared
|
||||
// Resize indicates that a the partition for a given mount point should be
|
||||
// resized to the maximum allowed.
|
||||
Resize
|
||||
// Overlay indicates that a the partition for a given mount point should be
|
||||
// mounted using overlayfs.
|
||||
Overlay
|
||||
// SkipIfMounted is a flag for skipping mount if the mountpoint is already mounted.
|
||||
SkipIfMounted
|
||||
)
|
||||
|
||||
// Flags is the mount flags.
|
||||
type Flags uint
|
||||
|
||||
// Options is the functional options struct.
|
||||
type Options struct {
|
||||
Loopback string
|
||||
Prefix string
|
||||
ReadOnly bool
|
||||
Shared bool
|
||||
Resize bool
|
||||
Overlay bool
|
||||
SkipIfMounted bool
|
||||
Loopback string
|
||||
Prefix string
|
||||
MountFlags Flags
|
||||
PreMountHooks []Hook
|
||||
PostUnmountHooks []Hook
|
||||
}
|
||||
|
||||
// Option is the functional option func.
|
||||
type Option func(*Options)
|
||||
|
||||
// Check checks if all provided flags are set.
|
||||
func (f Flags) Check(flags Flags) bool {
|
||||
return (f & flags) == flags
|
||||
}
|
||||
|
||||
// Intersects checks if at least one flag is set.
|
||||
func (f Flags) Intersects(flags Flags) bool {
|
||||
return (f & flags) != 0
|
||||
}
|
||||
|
||||
// WithPrefix is a functional option for setting the mount point prefix.
|
||||
func WithPrefix(o string) Option {
|
||||
return func(args *Options) {
|
||||
@ -25,52 +51,38 @@ func WithPrefix(o string) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithReadOnly is a functional option for setting the mount point as readonly.
|
||||
func WithReadOnly(o bool) Option {
|
||||
// WithFlags is a functional option to set up mount flags.
|
||||
func WithFlags(flags Flags) Option {
|
||||
return func(args *Options) {
|
||||
args.ReadOnly = o
|
||||
args.MountFlags = flags
|
||||
}
|
||||
}
|
||||
|
||||
// WithShared is a functional option for setting the mount point as shared.
|
||||
func WithShared(o bool) Option {
|
||||
// WithPreMountHooks adds functions to be called before mounting the partition.
|
||||
func WithPreMountHooks(hooks ...Hook) Option {
|
||||
return func(args *Options) {
|
||||
args.Shared = o
|
||||
args.PreMountHooks = hooks
|
||||
}
|
||||
}
|
||||
|
||||
// WithSkipIfMounted is a functional option for skipping mount if the mountpoint is already mounted.
|
||||
func WithSkipIfMounted(o bool) Option {
|
||||
// WithPostUnmountHooks adds functions to be called after unmounting the partition.
|
||||
func WithPostUnmountHooks(hooks ...Hook) Option {
|
||||
return func(args *Options) {
|
||||
args.SkipIfMounted = o
|
||||
args.PostUnmountHooks = hooks
|
||||
}
|
||||
}
|
||||
|
||||
// WithResize indicates that a the partition for a given mount point should be
|
||||
// resized to the maximum allowed.
|
||||
func WithResize(o bool) Option {
|
||||
return func(args *Options) {
|
||||
args.Resize = o
|
||||
}
|
||||
}
|
||||
|
||||
// WithOverlay indicates that a the partition for a given mount point should be
|
||||
// mounted using overlayfs.
|
||||
func WithOverlay(o bool) Option {
|
||||
return func(args *Options) {
|
||||
args.Overlay = o
|
||||
}
|
||||
}
|
||||
// Hook represents pre/post mount hook.
|
||||
type Hook func(p *Point) error
|
||||
|
||||
// NewDefaultOptions initializes a Options struct with default values.
|
||||
func NewDefaultOptions(setters ...Option) *Options {
|
||||
opts := &Options{
|
||||
Loopback: "",
|
||||
Prefix: "",
|
||||
ReadOnly: false,
|
||||
Shared: false,
|
||||
Resize: false,
|
||||
Overlay: false,
|
||||
Loopback: "",
|
||||
Prefix: "",
|
||||
MountFlags: 0,
|
||||
PreMountHooks: []Hook{},
|
||||
PostUnmountHooks: []Hook{},
|
||||
}
|
||||
|
||||
for _, setter := range setters {
|
||||
|
@ -22,7 +22,7 @@ func OverlayMountPoints() (mountpoints *Points, err error) {
|
||||
}
|
||||
|
||||
for _, target := range overlays {
|
||||
mountpoint := NewMountPoint("", target, "", unix.MS_I_VERSION, "", WithOverlay(true))
|
||||
mountpoint := NewMountPoint("", target, "", unix.MS_I_VERSION, "", WithFlags(Overlay))
|
||||
mountpoints.Set(target, mountpoint)
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ func SquashfsMountPoints(prefix string) (mountpoints *Points, err error) {
|
||||
}
|
||||
|
||||
squashfs := NewMountPoints()
|
||||
squashfs.Set("squashfs", NewMountPoint(dev.Path(), "/", "squashfs", unix.MS_RDONLY|unix.MS_I_VERSION, "", WithPrefix(prefix), WithReadOnly(true), WithShared(true)))
|
||||
squashfs.Set("squashfs", NewMountPoint(dev.Path(), "/", "squashfs", unix.MS_RDONLY|unix.MS_I_VERSION, "", WithPrefix(prefix), WithFlags(ReadOnly|Shared)))
|
||||
|
||||
return squashfs, nil
|
||||
}
|
||||
|
@ -9,13 +9,17 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/talos-systems/go-blockdevice/blockdevice"
|
||||
"github.com/talos-systems/go-blockdevice/blockdevice/filesystem"
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/disk"
|
||||
"github.com/talos-systems/talos/internal/pkg/partition"
|
||||
"github.com/talos-systems/talos/pkg/machinery/constants"
|
||||
)
|
||||
|
||||
var mountpoints = map[string]*Point{}
|
||||
|
||||
// SystemMountPointsForDevice returns the mountpoints required to boot the system.
|
||||
// This function is called exclusively during installations ( both image
|
||||
// creation and bare metall installs ). This is why we want to look up
|
||||
@ -61,12 +65,12 @@ func SystemMountPointForLabel(device *blockdevice.BlockDevice, label string, opt
|
||||
return nil, fmt.Errorf("unknown label: %q", label)
|
||||
}
|
||||
|
||||
partition, err := device.GetPartition(label)
|
||||
part, err := device.GetPartition(label)
|
||||
if err != nil && err != os.ErrNotExist {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if partition == nil {
|
||||
if part == nil {
|
||||
// A boot partitition is not required.
|
||||
if label == constants.BootPartitionLabel {
|
||||
return nil, nil
|
||||
@ -75,16 +79,47 @@ func SystemMountPointForLabel(device *blockdevice.BlockDevice, label string, opt
|
||||
return nil, fmt.Errorf("failed to find device with label %s: %w", label, err)
|
||||
}
|
||||
|
||||
fsType, err := partition.Filesystem()
|
||||
fsType, err := part.Filesystem()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
partPath, err := partition.Path()
|
||||
partPath, err := part.Path()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
preMountHooks := []Hook{}
|
||||
|
||||
// Format the partition if it does not have any filesystem
|
||||
preMountHooks = append(preMountHooks, func(p *Point) error {
|
||||
sb, err := filesystem.Probe(p.source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.fstype = ""
|
||||
|
||||
// skip formatting the partition if filesystem is detected
|
||||
// and assign proper fs type to the mountpoint
|
||||
if sb != nil && sb.Type() != filesystem.Unknown {
|
||||
p.fstype = sb.Type()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
opts := partition.NewFormatOptions(part.Name)
|
||||
if opts == nil {
|
||||
return fmt.Errorf("failed to determine format options for partition label %s", part.Name)
|
||||
}
|
||||
|
||||
p.fstype = opts.FileSystemType
|
||||
|
||||
return partition.Format(p.source, opts)
|
||||
})
|
||||
|
||||
opts = append(opts, WithPreMountHooks(preMountHooks...))
|
||||
|
||||
mountpoint = NewMountPoint(partPath, target, fsType, unix.MS_NOATIME, "", opts...)
|
||||
|
||||
return mountpoint, nil
|
||||
@ -97,8 +132,6 @@ func SystemPartitionMount(r runtime.Runtime, label string, opts ...Option) (err
|
||||
return fmt.Errorf("failed to find device with partition labeled %s", label)
|
||||
}
|
||||
|
||||
mountpoints := NewMountPoints()
|
||||
|
||||
mountpoint, err := SystemMountPointForLabel(device.BlockDevice, label, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -108,37 +141,24 @@ func SystemPartitionMount(r runtime.Runtime, label string, opts ...Option) (err
|
||||
return fmt.Errorf("no mountpoints for label %q", label)
|
||||
}
|
||||
|
||||
mountpoints.Set(label, mountpoint)
|
||||
|
||||
if err = Mount(mountpoints); err != nil {
|
||||
if err = mountMountpoint(mountpoint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mountpoints[label] = mountpoint
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SystemPartitionUnmount unmounts a system partition by the label.
|
||||
func SystemPartitionUnmount(r runtime.Runtime, label string) (err error) {
|
||||
device := r.State().Machine().Disk(disk.WithPartitionLabel(label))
|
||||
if device == nil {
|
||||
return fmt.Errorf("failed to find device with partition labeled %s", label)
|
||||
}
|
||||
if mountpoint, ok := mountpoints[label]; ok {
|
||||
err = mountpoint.Unmount()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mountpoints := NewMountPoints()
|
||||
|
||||
mountpoint, err := SystemMountPointForLabel(device.BlockDevice, label)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if mountpoint == nil {
|
||||
return fmt.Errorf("no mountpoints for label %q", label)
|
||||
}
|
||||
|
||||
mountpoints.Set(label, mountpoint)
|
||||
|
||||
if err = Unmount(mountpoints); err != nil {
|
||||
return err
|
||||
delete(mountpoints, label)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -2,18 +2,18 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package install
|
||||
package partition
|
||||
|
||||
// PartitionType in partition table.
|
||||
type PartitionType = string
|
||||
// Type in partition table.
|
||||
type Type = string
|
||||
|
||||
// GPT partition types.
|
||||
//
|
||||
// TODO: should be moved into the blockdevice library.
|
||||
const (
|
||||
EFISystemPartition PartitionType = "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
|
||||
BIOSBootPartition PartitionType = "21686148-6449-6E6F-744E-656564454649"
|
||||
LinuxFilesystemData PartitionType = "0FC63DAF-8483-4772-8E79-3D69D8477DE4"
|
||||
EFISystemPartition Type = "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
|
||||
BIOSBootPartition Type = "21686148-6449-6E6F-744E-656564454649"
|
||||
LinuxFilesystemData Type = "0FC63DAF-8483-4772-8E79-3D69D8477DE4"
|
||||
)
|
||||
|
||||
// FileSystemType is used to format partitions.
|
129
internal/pkg/partition/format.go
Normal file
129
internal/pkg/partition/format.go
Normal file
@ -0,0 +1,129 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// Package partition provides common utils for system partition format.
|
||||
package partition
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/talos-systems/go-blockdevice/blockdevice"
|
||||
|
||||
"github.com/talos-systems/talos/pkg/machinery/constants"
|
||||
"github.com/talos-systems/talos/pkg/makefs"
|
||||
)
|
||||
|
||||
// FormatOptions contains format parameters.
|
||||
type FormatOptions struct {
|
||||
Label string
|
||||
PartitionType Type
|
||||
FileSystemType FileSystemType
|
||||
Size uint64
|
||||
Force bool
|
||||
}
|
||||
|
||||
// NewFormatOptions creates a new format options.
|
||||
func NewFormatOptions(label string) *FormatOptions {
|
||||
opts, ok := systemPartitions[label]
|
||||
if ok {
|
||||
return &opts
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Format zeroes the device and formats it using filesystem type provided.
|
||||
func Format(devname string, t *FormatOptions) error {
|
||||
if t.FileSystemType == FilesystemTypeNone {
|
||||
return zeroPartition(devname, int64(t.Size))
|
||||
}
|
||||
|
||||
opts := []makefs.Option{makefs.WithForce(t.Force), makefs.WithLabel(t.Label)}
|
||||
log.Printf("formatting the partition %q as %q with label %q\n", devname, t.FileSystemType, t.Label)
|
||||
|
||||
switch t.FileSystemType {
|
||||
case FilesystemTypeVFAT:
|
||||
return makefs.VFAT(devname, opts...)
|
||||
case FilesystemTypeXFS:
|
||||
return makefs.XFS(devname, opts...)
|
||||
default:
|
||||
return fmt.Errorf("unsupported filesystem type: %q", t.FileSystemType)
|
||||
}
|
||||
}
|
||||
|
||||
// zeroPartition fills the partition with zeroes.
|
||||
func zeroPartition(devname string, size int64) (err error) {
|
||||
log.Printf("zeroing out %q", devname)
|
||||
|
||||
zeroes, err := os.Open("/dev/zero")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer zeroes.Close() //nolint: errcheck
|
||||
|
||||
part, err := os.OpenFile(devname, os.O_WRONLY, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer part.Close() //nolint: errcheck
|
||||
|
||||
// wipe at least minimal header size
|
||||
if size == 0 {
|
||||
size = blockdevice.FastWipeRange
|
||||
}
|
||||
|
||||
_, err = io.CopyN(part, zeroes, size)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var systemPartitions = map[string]FormatOptions{
|
||||
constants.EFIPartitionLabel: {
|
||||
Label: constants.EFIPartitionLabel,
|
||||
PartitionType: EFISystemPartition,
|
||||
FileSystemType: FilesystemTypeVFAT,
|
||||
Size: EFISize,
|
||||
Force: true,
|
||||
},
|
||||
constants.BIOSGrubPartitionLabel: {
|
||||
Label: constants.BIOSGrubPartitionLabel,
|
||||
PartitionType: BIOSBootPartition,
|
||||
FileSystemType: FilesystemTypeNone,
|
||||
Size: BIOSGrubSize,
|
||||
Force: true,
|
||||
},
|
||||
constants.BootPartitionLabel: {
|
||||
Label: constants.BootPartitionLabel,
|
||||
PartitionType: LinuxFilesystemData,
|
||||
FileSystemType: FilesystemTypeXFS,
|
||||
Size: BootSize,
|
||||
Force: true,
|
||||
},
|
||||
constants.MetaPartitionLabel: {
|
||||
Label: constants.MetaPartitionLabel,
|
||||
PartitionType: LinuxFilesystemData,
|
||||
FileSystemType: FilesystemTypeNone,
|
||||
Size: MetaSize,
|
||||
Force: true,
|
||||
},
|
||||
constants.StatePartitionLabel: {
|
||||
Label: constants.StatePartitionLabel,
|
||||
PartitionType: LinuxFilesystemData,
|
||||
FileSystemType: FilesystemTypeXFS,
|
||||
Size: StateSize,
|
||||
Force: true,
|
||||
},
|
||||
constants.EphemeralPartitionLabel: {
|
||||
Label: constants.EphemeralPartitionLabel,
|
||||
PartitionType: LinuxFilesystemData,
|
||||
FileSystemType: FilesystemTypeXFS,
|
||||
Size: 0,
|
||||
Force: true,
|
||||
},
|
||||
}
|
6
internal/pkg/partition/partition.go
Normal file
6
internal/pkg/partition/partition.go
Normal file
@ -0,0 +1,6 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// Package partition provides common utils for system partition format.
|
||||
package partition
|
@ -41,7 +41,7 @@ func DefaultClusterChecks() []ClusterCheck {
|
||||
func(cluster ClusterInfo) conditions.Condition {
|
||||
return conditions.PollingCondition("apid to be ready", func(ctx context.Context) error {
|
||||
return ApidReadyAssertion(ctx, cluster)
|
||||
}, 2*time.Minute, 5*time.Second)
|
||||
}, 5*time.Minute, 5*time.Second)
|
||||
},
|
||||
// wait for kubelet to be healthy on all
|
||||
func(cluster ClusterInfo) conditions.Condition {
|
||||
|
Loading…
x
Reference in New Issue
Block a user