Skip to content

Commit 891f94a

Browse files
authored
feat:[close Vanilla-OS#159] make use of systemd mount units
This is cleaner than using a mount script and running this as a service.
1 parent 24951bc commit 891f94a

File tree

2 files changed

+77
-93
lines changed

2 files changed

+77
-93
lines changed

core/disk-manager.go

+6
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"fmt"
2020
"os"
2121
"os/exec"
22+
"strings"
2223
"syscall"
2324
)
2425

@@ -210,3 +211,8 @@ func (p *Partition) Unmount() error {
210211
func (p *Partition) IsDevMapper() bool {
211212
return p.Parent != nil
212213
}
214+
215+
// IsEncrypted returns whether the partition is encrypted
216+
func (p *Partition) IsEncrypted() bool {
217+
return strings.HasPrefix(p.Device, "luks-")
218+
}

core/system.go

+71-93
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,7 @@ const (
4747
)
4848

4949
const (
50-
MountScriptPath = "/usr/sbin/.abroot-mountpoints"
51-
MountUnitDir = "/etc/systemd/system"
52-
SystemDTargetDir = "/etc/systemd/system/%s.target.wants"
53-
MountUnitFile = "/abroot-mount.service"
50+
MountUnitDir = "/etc/systemd/system"
5451
)
5552

5653
type ABSystemOperation string
@@ -315,14 +312,24 @@ func (s *ABSystem) GenerateFstab(rootPath string, root ABRootPartition) error {
315312
#
316313
# <file system> <mount point> <type> <options> <dump> <pass>
317314
UUID=%s / %s defaults 0 0
315+
/.system/usr /.system/usr none bind,ro
316+
%s /var auto defaults 0 0
318317
`
318+
varSource := ""
319+
if s.RootM.VarPartition.IsDevMapper() {
320+
varSource = fmt.Sprintf("/dev/mapper/%s", s.RootM.VarPartition.Device)
321+
} else {
322+
varSource = fmt.Sprintf("-U %s", s.RootM.VarPartition.Uuid)
323+
}
324+
319325
fstab := fmt.Sprintf(
320326
template,
321327
root.Partition.Uuid,
322328
root.Partition.FsType,
329+
varSource,
323330
)
324331

325-
err := os.WriteFile(rootPath+"/etc/fstab", []byte(fstab), 0644)
332+
err := os.WriteFile(filepath.Join(rootPath, "/etc/fstab"), []byte(fstab), 0644)
326333
if err != nil {
327334
PrintVerbose("ABSystem.GenerateFstab:err: %s", err)
328335
return err
@@ -382,100 +389,77 @@ func (s *ABSystem) GenerateCrypttab(rootPath string) error {
382389
return nil
383390
}
384391

385-
// GenerateMountpointsScript generates a /usr/sbin/.abroot-mountpoints file for the future root
386-
func (s *ABSystem) GenerateMountpointsScript(rootPath string, root ABRootPartition) error {
387-
PrintVerbose("ABSystem.GenerateMountpointsScript: generating script")
388-
389-
template := `#!/usr/bin/bash
390-
echo "ABRoot: Initializing mount points..."
391-
392-
# /var mount
393-
mount %s /var
394-
395-
# /etc overlay
396-
mount -t overlay overlay -o lowerdir=/.system/etc,upperdir=/var/lib/abroot/etc/%s,workdir=/var/lib/abroot/etc/%s-work /etc
392+
// GenerateSystemdUnits generates systemd units that mount the mutable parts of the system
393+
func (s *ABSystem) GenerateSystemdUnits(rootPath string, root ABRootPartition) error {
394+
PrintVerbose("ABSystem.GenerateSystemdUnits: generating units")
397395

398-
# /var binds
399-
mount -o bind /var/home /home
400-
mount -o bind /var/opt /opt
401-
mount -o bind,ro /.system/usr /usr
402-
mount -o bind /var/lib/abroot/etc/%s/locales /usr/lib/locale
403-
`
404-
mountExtCmd := ""
405-
if s.RootM.VarPartition.IsDevMapper() {
406-
mountExtCmd = fmt.Sprintf("/dev/mapper/%s", s.RootM.VarPartition.Device)
407-
} else {
408-
mountExtCmd = fmt.Sprintf("-U %s", s.RootM.VarPartition.Uuid)
396+
extraDepends := ""
397+
if root.Partition.IsEncrypted() || s.RootM.VarPartition.IsEncrypted() {
398+
extraDepends = "cryptsetup.target"
409399
}
410-
mountpoints := fmt.Sprintf(template, mountExtCmd, root.Label, root.Label, root.Label)
411400

412-
err := os.WriteFile(rootPath+MountScriptPath, []byte(mountpoints), 0755)
413-
if err != nil {
414-
PrintVerbose("ABSystem.GenerateMountpointsScript:err(3): %s", err)
415-
return err
401+
type varmount struct {
402+
source string
403+
destination string
404+
fsType string
405+
options string
416406
}
417407

418-
err = os.Chmod(rootPath+MountScriptPath, 0755)
419-
if err != nil {
420-
PrintVerbose("ABSystem.GenerateMountpointsScript:err(4): %s", err)
421-
return err
408+
mounts := []varmount{
409+
{"/var/home", "/home", "none", "bind"},
410+
{"/var/opt", "/opt", "none", "bind"},
411+
{"/var/lib/abroot/etc/" + root.Label + "/locales", "/.system/usr/lib/locale", "none", "bind"},
412+
{"overlay", "/.system/etc", "overlay", "lowerdir=/.system/etc,upperdir=/var/lib/abroot/etc/" + root.Label + ",workdir=/var/lib/abroot/etc/" + root.Label + "-work"},
422413
}
423414

424-
PrintVerbose("ABSystem.GenerateMountpointsScript: script generated")
425-
return nil
426-
}
415+
afterVarTemplate := `[Unit]
416+
Description=Mounts %s from var
417+
After=local-fs-pre.target %s
418+
Before=local-fs.target nss-user-lookup.target
419+
RequiresMountsFor=/var
427420
428-
// GenerateMountpointsSystemDUnit creates a SystemD unit to setup the /var partition and its
429-
// derivatives such as /home, /opt, and /etc.
430-
// This unit must run as soon as all encrypted partitions (if any) have been decrupted.
431-
func (s *ABSystem) GenerateMountpointsSystemDUnit(rootPath string, root ABRootPartition) error {
432-
PrintVerbose("ABSystem.GenerateMountpointsSystemDUnit: generating script")
433-
434-
depTarget := "local-fs"
435-
template := `[Unit]
436-
Description=Mount partitions
437-
Requires=%s.target
438-
After=%s.target
439-
Before=nss-user-lookup.target
440-
441-
[Service]
442-
Type=oneshot
443-
ExecStart=%s
421+
[Mount]
422+
What=%s
423+
Where=%s
424+
Type=%s
425+
Options=%s
444426
`
445-
// Check for encrypted roots
446-
for _, rootDevice := range s.RootM.Partitions {
447-
if strings.HasPrefix(rootDevice.Partition.Device, "luks-") {
448-
depTarget = "cryptsetup"
449-
break
450-
}
451-
}
452427

453-
// Check for encrypted var
454-
if strings.HasPrefix(s.RootM.VarPartition.Device, "luks-") {
455-
depTarget = "cryptsetup"
456-
}
428+
for _, mount := range mounts {
429+
PrintVerbose("ABSystem.GenerateSystemdUnits: generating unit for %s", mount.destination)
457430

458-
unit := fmt.Sprintf(template, depTarget, depTarget, MountScriptPath)
431+
unit := fmt.Sprintf(afterVarTemplate, mount.destination, extraDepends, mount.source, mount.destination, mount.fsType, mount.options)
459432

460-
err := os.WriteFile(rootPath+MountUnitDir+MountUnitFile, []byte(unit), 0755)
461-
if err != nil {
462-
PrintVerbose("ABSystem.GenerateMountpointsSystemDUnit:err(2): %s", err)
463-
return err
464-
}
433+
// the unit file needs to have the escaped mount point as its name
434+
out, err := exec.Command("systemd-escape", "--path", mount.destination).Output()
435+
if err != nil {
436+
PrintVerbose("ABSystem.GenerateSystemdUnits:err(1): failed to determine escaped path: %s", err)
437+
return err
438+
}
439+
mountUnitFile := "/" + strings.Replace(string(out), "\n", "", -1) + ".mount"
465440

466-
err = os.MkdirAll(rootPath+fmt.Sprintf(SystemDTargetDir, depTarget), 0755)
467-
if err != nil {
468-
PrintVerbose("ABSystem.GenerateMountpointsSystemDUnit:err(3): %s", err)
469-
return err
470-
}
441+
err = os.WriteFile(filepath.Join(rootPath, MountUnitDir, mountUnitFile), []byte(unit), 0644)
442+
if err != nil {
443+
PrintVerbose("ABSystem.GenerateSystemdUnits:err(2): %s", err)
444+
return err
445+
}
471446

472-
err = os.Symlink(".."+MountUnitFile, rootPath+fmt.Sprintf(SystemDTargetDir, depTarget)+MountUnitFile)
473-
if err != nil {
474-
PrintVerbose("ABSystem.GenerateMountpointsSystemDUnit:err(4): %s", err)
475-
return err
447+
const targetWants string = "/local-fs.target.wants"
448+
449+
err = os.MkdirAll(filepath.Join(rootPath, MountUnitDir, targetWants), 0755)
450+
if err != nil {
451+
PrintVerbose("ABSystem.GenerateSystemdUnits:err(3): %s", err)
452+
return err
453+
}
454+
455+
err = os.Symlink(filepath.Join("../", mountUnitFile), filepath.Join(rootPath, MountUnitDir, targetWants, mountUnitFile))
456+
if err != nil {
457+
PrintVerbose("ABSystem.GenerateSystemdUnits:err(4): failed to create symlink: %s", err)
458+
return err
459+
}
476460
}
477461

478-
PrintVerbose("ABSystem.GenerateMountpointsSystemDUnit: unit generated")
462+
PrintVerbose("ABSystem.GenerateSystemdUnits: units generated")
479463
return nil
480464
}
481465

@@ -707,8 +691,8 @@ func (s *ABSystem) RunOperation(operation ABSystemOperation) error {
707691
return err
708692
}
709693

710-
// Stage 6: Generate /etc/fstab, /etc/crypttab, /usr/sbin/.abroot-mountpoints, and the
711-
// SystemD unit to setup mountpoints
694+
// Stage 6: Generate /etc/fstab, /etc/crypttab, and the
695+
// SystemD units to setup mountpoints
712696
// ------------------------------------------------
713697
PrintVerbose("[Stage 6] -------- ABSystemRunOperation")
714698

@@ -724,15 +708,9 @@ func (s *ABSystem) RunOperation(operation ABSystemOperation) error {
724708
return err
725709
}
726710

727-
err = s.GenerateMountpointsScript(systemNew, partFuture)
728-
if err != nil {
729-
PrintVerbose("ABSystem.RunOperation:err(6.2): %s", err)
730-
return err
731-
}
732-
733-
err = s.GenerateMountpointsSystemDUnit(systemNew, partFuture)
711+
err = s.GenerateSystemdUnits(systemNew, partFuture)
734712
if err != nil {
735-
PrintVerbose("ABSystem.RunOperation:err(6.3): %s", err)
713+
PrintVerbose("ABSystem.RunOperation:err(6.2): Failed to Generate SystemdUnits: %s", err)
736714
return err
737715
}
738716

0 commit comments

Comments
 (0)