mirror of
https://github.com/kairos-io/kairos-agent.git
synced 2025-09-25 13:33:41 +00:00
Improve get partitions and reset spec (#530)
Co-authored-by: Dimitris Karakasilis <dimitris@karakasilis.me>
This commit is contained in:
@@ -114,6 +114,7 @@ func (r ResetAction) Run() (err error) {
|
|||||||
defer func() { err = cleanup.Cleanup(err) }()
|
defer func() { err = cleanup.Cleanup(err) }()
|
||||||
|
|
||||||
// Unmount partitions if any is already mounted before formatting
|
// Unmount partitions if any is already mounted before formatting
|
||||||
|
// TODO: Is this needed???
|
||||||
err = e.UnmountPartitions(r.spec.Partitions.PartitionsByMountPoint(true, r.spec.Partitions.Recovery))
|
err = e.UnmountPartitions(r.spec.Partitions.PartitionsByMountPoint(true, r.spec.Partitions.Recovery))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -129,6 +130,10 @@ func (r ResetAction) Run() (err error) {
|
|||||||
if r.spec.FormatPersistent {
|
if r.spec.FormatPersistent {
|
||||||
persistent := r.spec.Partitions.Persistent
|
persistent := r.spec.Partitions.Persistent
|
||||||
if persistent != nil {
|
if persistent != nil {
|
||||||
|
err = e.UnmountPartitions(r.spec.Partitions.PartitionsByMountPoint(true, persistent))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
err = e.FormatPartition(persistent)
|
err = e.FormatPartition(persistent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -140,6 +145,11 @@ func (r ResetAction) Run() (err error) {
|
|||||||
if r.spec.FormatOEM {
|
if r.spec.FormatOEM {
|
||||||
oem := r.spec.Partitions.OEM
|
oem := r.spec.Partitions.OEM
|
||||||
if oem != nil {
|
if oem != nil {
|
||||||
|
// Try to umount
|
||||||
|
err = e.UnmountPartitions(r.spec.Partitions.PartitionsByMountPoint(true, oem))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
err = e.FormatPartition(oem)
|
err = e.FormatPartition(oem)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@@ -438,34 +438,18 @@ func NewResetSpec(cfg *Config) (*v1.ResetSpec, error) {
|
|||||||
|
|
||||||
target := ep.State.Disk
|
target := ep.State.Disk
|
||||||
|
|
||||||
// OEM partition is not a hard requirement
|
// OEM partition is not a hard requirement for reset unless we have the reset oem flag
|
||||||
if ep.OEM != nil {
|
cfg.Logger.Info(litter.Sdump(ep.OEM))
|
||||||
if ep.OEM.MountPoint == "" {
|
if ep.OEM == nil {
|
||||||
ep.OEM.MountPoint = constants.OEMDir
|
|
||||||
}
|
|
||||||
ep.OEM.Name = constants.OEMPartName
|
|
||||||
} else {
|
|
||||||
// We could have oem in lvm which won't appear in ghw list
|
// We could have oem in lvm which won't appear in ghw list
|
||||||
ep.OEM = partitions.GetPartitionViaDM(cfg.Fs, constants.OEMLabel)
|
ep.OEM = partitions.GetPartitionViaDM(cfg.Fs, constants.OEMLabel)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ep.OEM == nil {
|
|
||||||
cfg.Logger.Warnf("no OEM partition found")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Persistent partition is not a hard requirement
|
// Persistent partition is not a hard requirement
|
||||||
if ep.Persistent != nil {
|
if ep.Persistent == nil {
|
||||||
if ep.Persistent.MountPoint == "" {
|
|
||||||
ep.Persistent.MountPoint = constants.PersistentDir
|
|
||||||
}
|
|
||||||
ep.Persistent.Name = constants.PersistentPartName
|
|
||||||
} else {
|
|
||||||
// We could have persistent encrypted or in lvm which won't appear in ghw list
|
// We could have persistent encrypted or in lvm which won't appear in ghw list
|
||||||
ep.Persistent = partitions.GetPartitionViaDM(cfg.Fs, constants.PersistentLabel)
|
ep.Persistent = partitions.GetPartitionViaDM(cfg.Fs, constants.PersistentLabel)
|
||||||
}
|
}
|
||||||
if ep.Persistent == nil {
|
|
||||||
cfg.Logger.Warnf("no Persistent partition found")
|
|
||||||
}
|
|
||||||
|
|
||||||
recoveryImg := filepath.Join(constants.RunningStateDir, "cOS", constants.RecoveryImgFile)
|
recoveryImg := filepath.Join(constants.RunningStateDir, "cOS", constants.RecoveryImgFile)
|
||||||
recoveryImg2 := filepath.Join(constants.RunningRecoveryStateDir, "cOS", constants.RecoveryImgFile)
|
recoveryImg2 := filepath.Join(constants.RunningRecoveryStateDir, "cOS", constants.RecoveryImgFile)
|
||||||
@@ -522,6 +506,25 @@ func NewResetSpec(cfg *Config) (*v1.ResetSpec, error) {
|
|||||||
return nil, fmt.Errorf("failed unmarshalling the full spec: %w", err)
|
return nil, fmt.Errorf("failed unmarshalling the full spec: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ep.OEM == nil && spec.FormatOEM {
|
||||||
|
cfg.Logger.Warnf("no OEM partition found, won't format it")
|
||||||
|
}
|
||||||
|
|
||||||
|
if ep.Persistent == nil && spec.FormatPersistent {
|
||||||
|
cfg.Logger.Warnf("no Persistent partition found, won't format it")
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we mount partitions by the /dev/disk/by-label stanza, their mountpoints wont show up due to ghw not
|
||||||
|
// accounting for them. Normally this is not an issue but in this case, if we are formatting a given partition we
|
||||||
|
// want to unmount it first. Thus we need to make sure that if its mounted we have the mountpoint info
|
||||||
|
if ep.Persistent.MountPoint == "" {
|
||||||
|
ep.Persistent.MountPoint = partitions.GetMountPointByLabel(ep.Persistent.FilesystemLabel)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ep.OEM.MountPoint == "" {
|
||||||
|
ep.OEM.MountPoint = partitions.GetMountPointByLabel(ep.OEM.FilesystemLabel)
|
||||||
|
}
|
||||||
|
|
||||||
return spec, nil
|
return spec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -47,14 +47,7 @@ func NewElemental(config *agentConfig.Config) *Elemental {
|
|||||||
|
|
||||||
// FormatPartition will format an already existing partition
|
// FormatPartition will format an already existing partition
|
||||||
func (e *Elemental) FormatPartition(part *v1.Partition, opts ...string) error {
|
func (e *Elemental) FormatPartition(part *v1.Partition, opts ...string) error {
|
||||||
var name string
|
e.config.Logger.Infof("Formatting '%s' partition", part.FilesystemLabel)
|
||||||
// Nice display name for logs
|
|
||||||
if part.Name == "" {
|
|
||||||
name = part.FilesystemLabel
|
|
||||||
} else {
|
|
||||||
name = part.Name
|
|
||||||
}
|
|
||||||
e.config.Logger.Infof("Formatting '%s' partition", name)
|
|
||||||
return partitioner.FormatDevice(e.config.Runner, part.Path, part.FS, part.FilesystemLabel, opts...)
|
return partitioner.FormatDevice(e.config.Runner, part.Path, part.FS, part.FilesystemLabel, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -17,7 +17,10 @@ limitations under the License.
|
|||||||
package partitions
|
package partitions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -61,6 +64,59 @@ func GetAllPartitions() (v1.PartitionList, error) {
|
|||||||
return parts, nil
|
return parts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetMountPointByLabel will try to get the mountpoint by using the label only
|
||||||
|
// so we can identify mounts the have been mounted with /dev/disk/by-label stanzas
|
||||||
|
func GetMountPointByLabel(label string) string {
|
||||||
|
// mount entries for mounted partitions look like this:
|
||||||
|
// /dev/sda6 / ext4 rw,relatime,errors=remount-ro,data=ordered 0 0
|
||||||
|
var r io.ReadCloser
|
||||||
|
r, err := os.Open("/proc/mounts")
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
defer r.Close()
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(r)
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
partition, mountpoint := parseMountEntry(line)
|
||||||
|
if partition == fmt.Sprintf("/dev/disk/by-label/%s", label) {
|
||||||
|
return mountpoint
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseMountEntry(line string) (string, string) {
|
||||||
|
// mount entries for mounted partitions look like this:
|
||||||
|
// /dev/sda6 / ext4 rw,relatime,errors=remount-ro,data=ordered 0 0
|
||||||
|
if line[0] != '/' {
|
||||||
|
return "", ""
|
||||||
|
}
|
||||||
|
fields := strings.Fields(line)
|
||||||
|
|
||||||
|
if len(fields) < 4 {
|
||||||
|
return "", ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// We do some special parsing of the mountpoint, which may contain space,
|
||||||
|
// tab and newline characters, encoded into the mount entry line using their
|
||||||
|
// octal-to-string representations. From the GNU mtab man pages:
|
||||||
|
//
|
||||||
|
// "Therefore these characters are encoded in the files and the getmntent
|
||||||
|
// function takes care of the decoding while reading the entries back in.
|
||||||
|
// '\040' is used to encode a space character, '\011' to encode a tab
|
||||||
|
// character, '\012' to encode a newline character, and '\\' to encode a
|
||||||
|
// backslash."
|
||||||
|
mp := fields[1]
|
||||||
|
r := strings.NewReplacer(
|
||||||
|
"\\011", "\t", "\\012", "\n", "\\040", " ", "\\\\", "\\",
|
||||||
|
)
|
||||||
|
mp = r.Replace(mp)
|
||||||
|
|
||||||
|
return fields[0], mp
|
||||||
|
}
|
||||||
|
|
||||||
// GetPartitionFS gets the FS of a partition given
|
// GetPartitionFS gets the FS of a partition given
|
||||||
func GetPartitionFS(partition string) (string, error) {
|
func GetPartitionFS(partition string) (string, error) {
|
||||||
// We want to have the device always prefixed with a /dev
|
// We want to have the device always prefixed with a /dev
|
||||||
|
Reference in New Issue
Block a user