Skip to content

Commit

Permalink
feat: scan ostree
Browse files Browse the repository at this point in the history
  • Loading branch information
slntopp committed Dec 13, 2024
1 parent 0ccc07c commit 78d101e
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 21 deletions.
11 changes: 9 additions & 2 deletions providers/os/connection/device/device_connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package device

import (
"errors"
"path"
"runtime"
"strings"

Expand Down Expand Up @@ -185,10 +186,16 @@ func (p *DeviceConnection) Partitions() map[string]*snapshot.PartitionInfo {

// tryDetectAsset tries to detect the OS on a given block device
func tryDetectAsset(connId uint32, partition *snapshot.PartitionInfo, conf *inventory.Config, asset *inventory.Asset) (*fs.FileSystemConnection, error) {
fsPath := partition.MountPoint
if partition.Bind != "" {
fsPath = path.Join(fsPath, partition.Bind)
}

// create and initialize fs provider
conf.Options["path"] = partition.MountPoint
log.Debug().Str("path", fsPath).Msg("device connection> trying to detect asset")
conf.Options["path"] = fsPath
fsConn, err := fs.NewConnection(connId, &inventory.Config{
Path: partition.MountPoint,
Path: fsPath,
PlatformId: conf.PlatformId,
Options: conf.Options,
Type: "fs",
Expand Down
94 changes: 75 additions & 19 deletions providers/os/connection/device/linux/device_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ package linux

import (
"bytes"
"os"
"os/exec"
"path"
"path/filepath"
"strconv"
"strings"

Expand Down Expand Up @@ -91,7 +93,7 @@ func (d *LinuxDeviceManager) IdentifyMountTargets(opts map[string]string) ([]*sn
return partitions, nil
}

fstabEntries, err := d.AttemptFindFstab(partitions)
fstabEntries, err := d.HintFSTypes(partitions)
if err != nil {
log.Warn().Err(err).Msg("could not find fstab")
return partitions, nil
Expand All @@ -107,8 +109,10 @@ func (d *LinuxDeviceManager) IdentifyMountTargets(opts map[string]string) ([]*sn
return partitions, nil
}

func (d *LinuxDeviceManager) AttemptFindFstab(partitions []*snapshot.PartitionInfo) ([]resources.FstabEntry, error) {
for _, partition := range partitions {
func (d *LinuxDeviceManager) HintFSTypes(partitions []*snapshot.PartitionInfo) ([]resources.FstabEntry, error) {
for i := range partitions {
partition := partitions[i]

dir, err := d.volumeMounter.MountP(&snapshot.MountPartitionDto{PartitionInfo: partition})
if err != nil {
continue
Expand All @@ -119,33 +123,85 @@ func (d *LinuxDeviceManager) AttemptFindFstab(partitions []*snapshot.PartitionIn
}
}()

cmd := exec.Command("find", dir, "-type", "f", "-wholename", `*/etc/fstab`)
out, err := cmd.CombinedOutput()
entries, err := d.AttemptFindFstab(dir)
if err != nil {
log.Error().Err(err).Msg("error finding fstab")
continue
return nil, err
}

if len(strings.Split(string(out), "\n")) != 2 {
log.Debug().Bytes("find", out).Msg("fstab not found, too many results")
continue
if entries != nil {
return entries, nil
}

mnt, fstab := path.Split(strings.TrimSpace(string(out)))
fstabFile, err := afero.ReadFile(
fs.NewMountedFs(mnt),
path.Base(fstab))
if err != nil {
log.Error().Err(err).Msg("error reading fstab")
continue
if ok := d.AttemptFindOSTree(dir, partition); ok {
return nil, nil
}

return resources.ParseFstab(bytes.NewReader(fstabFile))
}

return nil, errors.New("fstab not found")
}

func (d *LinuxDeviceManager) AttemptFindFstab(dir string) ([]resources.FstabEntry, error) {
cmd := exec.Command("find", dir, "-type", "f", "-wholename", `*/etc/fstab`)
out, err := cmd.CombinedOutput()
if err != nil {
log.Error().Err(err).Msg("error searching for fstab")
return nil, nil
}

if len(strings.Split(string(out), "\n")) != 2 {
log.Debug().Bytes("find", out).Msg("fstab not found, too many results")
return nil, nil
}

mnt, fstab := path.Split(strings.TrimSpace(string(out)))
fstabFile, err := afero.ReadFile(
fs.NewMountedFs(mnt),
path.Base(fstab))
if err != nil {
log.Error().Err(err).Msg("error reading fstab")
return nil, nil
}

return resources.ParseFstab(bytes.NewReader(fstabFile))
}

func (d *LinuxDeviceManager) AttemptFindOSTree(dir string, partition *snapshot.PartitionInfo) bool {
info, err := os.Stat(path.Join(dir, "ostree"))
if err != nil {
if os.IsNotExist(err) {
return false
}

log.Error().Err(err).Str("device", partition.Name).Msg("unable to stat ostree")
return false
}

if !info.IsDir() {
return false
}

boot1, err := os.Readlink(path.Join(dir, "ostree", "boot.1"))
if err != nil {
log.Error().Err(err).Str("device", partition.Name).Msg("unable to readlink boot.1")
return false
}

matches, err := filepath.Glob(path.Join(dir, "ostree", boot1, "*", "*", "0"))
if err != nil {
log.Error().Err(err).Str("device", partition.Name).Msg("unable to glob ostree")
return false
}

if len(matches) == 0 {
return false
} else if len(matches) > 1 {
log.Warn().Str("device", partition.Name).Msg("multiple ostree matches")
}

partition.Bind = strings.TrimPrefix(matches[0], dir)
return true
}

// MountWithFstab mounts partitions adjusting the mountpoint and mount options according to the discovered fstab entries
func (d *LinuxDeviceManager) MountWithFstab(partitions []*snapshot.PartitionInfo, entries []resources.FstabEntry) ([]*snapshot.PartitionInfo, error) {
for _, entry := range entries {
Expand Down
2 changes: 2 additions & 0 deletions providers/os/connection/snapshot/partition.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ type PartitionInfo struct {

// (optional) MountOptions are the mount options
MountOptions []string
// (optional) Bind adjusts the root for FS connection
Bind string
}

type MountPartitionDto struct {
Expand Down

0 comments on commit 78d101e

Please sign in to comment.