Skip to content

Commit

Permalink
stages/files: add support for runtime systemd units
Browse files Browse the repository at this point in the history
Teach `writeSystemdUnit()` how to create runtime units in `/run`. This
only adds *internal* support for our own purposes. It does not extend
the Ignition spec to allow users to specify it. Though we could do this
too later on.
  • Loading branch information
jlebon committed Aug 1, 2018
1 parent 6fe6988 commit af98f37
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 11 deletions.
19 changes: 12 additions & 7 deletions internal/exec/stages/files/units.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
// createUnits creates the units listed under systemd.units and networkd.units.
func (s stage) createUnits(config types.Config) error {
for _, unit := range config.Systemd.Units {
if err := s.writeSystemdUnit(unit); err != nil {
if err := s.writeSystemdUnit(unit, false); err != nil {
return err
}
if unit.Enable {
Expand Down Expand Up @@ -71,20 +71,25 @@ func (s stage) createUnits(config types.Config) error {
// writeSystemdUnit creates the specified unit and any dropins for that unit.
// If the contents of the unit or are empty, the unit is not created. The same
// applies to the unit's dropins.
func (s stage) writeSystemdUnit(unit types.Unit) error {
func (s stage) writeSystemdUnit(unit types.Unit, runtime bool) error {
// use a different DestDir if it's runtime so it affects our /run
u := s.Util
if runtime {
u.DestDir = "/"
}

return s.Logger.LogOp(func() error {
for _, dropin := range unit.Dropins {
if dropin.Contents == "" {
continue
}

f, err := util.FileFromSystemdUnitDropin(unit, dropin)
f, err := util.FileFromSystemdUnitDropin(unit, dropin, runtime)
if err != nil {
s.Logger.Crit("error converting systemd dropin: %v", err)
return err
}
if err := s.Logger.LogOp(
func() error { return s.PerformFetch(f) },
func() error { return u.PerformFetch(f) },
"writing systemd drop-in %q at %q", dropin.Name, f.Path,
); err != nil {
return err
Expand All @@ -95,13 +100,13 @@ func (s stage) writeSystemdUnit(unit types.Unit) error {
return nil
}

f, err := util.FileFromSystemdUnit(unit)
f, err := util.FileFromSystemdUnit(unit, runtime)
if err != nil {
s.Logger.Crit("error converting unit: %v", err)
return err
}
if err := s.Logger.LogOp(
func() error { return s.PerformFetch(f) },
func() error { return u.PerformFetch(f) },
"writing unit %q at %q", unit.Name, f.Path,
); err != nil {
return err
Expand Down
12 changes: 12 additions & 0 deletions internal/exec/util/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ func SystemdUnitsPath() string {
return filepath.Join("etc", "systemd", "system")
}

func SystemdRuntimeUnitsPath() string {
return filepath.Join("run", "systemd", "system")
}

func SystemdRuntimeUnitWantsPath(unitName string) string {
return filepath.Join("run", "systemd", "system", unitName+".wants")
}

func NetworkdUnitsPath() string {
return filepath.Join("etc", "systemd", "network")
}
Expand All @@ -30,6 +38,10 @@ func SystemdDropinsPath(unitName string) string {
return filepath.Join("etc", "systemd", "system", unitName+".d")
}

func SystemdRuntimeDropinsPath(unitName string) string {
return filepath.Join("run", "systemd", "system", unitName+".d")
}

func NetworkdDropinsPath(unitName string) string {
return filepath.Join("etc", "systemd", "network", unitName+".d")
}
45 changes: 41 additions & 4 deletions internal/exec/util/unit.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,21 @@ const (
DefaultPresetPermissions os.FileMode = 0644
)

func FileFromSystemdUnit(unit types.Unit) (*FetchOp, error) {
func FileFromSystemdUnit(unit types.Unit, runtime bool) (*FetchOp, error) {
u, err := url.Parse(dataurl.EncodeBytes([]byte(unit.Contents)))
if err != nil {
return nil, err
}

var path string
if runtime {
path = SystemdRuntimeUnitsPath()
} else {
path = SystemdUnitsPath()
}

return &FetchOp{
Path: filepath.Join(SystemdUnitsPath(), string(unit.Name)),
Path: filepath.Join(path, string(unit.Name)),
Url: *u,
Mode: configUtil.IntToPtr(int(DefaultFilePermissions)),
}, nil
Expand All @@ -55,13 +63,21 @@ func FileFromNetworkdUnit(unit types.Networkdunit) (*FetchOp, error) {
}, nil
}

func FileFromSystemdUnitDropin(unit types.Unit, dropin types.SystemdDropin) (*FetchOp, error) {
func FileFromSystemdUnitDropin(unit types.Unit, dropin types.SystemdDropin, runtime bool) (*FetchOp, error) {
u, err := url.Parse(dataurl.EncodeBytes([]byte(dropin.Contents)))
if err != nil {
return nil, err
}

var path string
if runtime {
path = SystemdRuntimeDropinsPath(string(unit.Name))
} else {
path = SystemdDropinsPath(string(unit.Name))
}

return &FetchOp{
Path: filepath.Join(SystemdDropinsPath(string(unit.Name)), string(dropin.Name)),
Path: filepath.Join(path, string(dropin.Name)),
Url: *u,
Mode: configUtil.IntToPtr(int(DefaultFilePermissions)),
}, nil
Expand Down Expand Up @@ -94,6 +110,27 @@ func (u Util) EnableUnit(unit types.Unit) error {
return u.appendLineToPreset(fmt.Sprintf("enable %s", unit.Name))
}

// presets link in /etc, which doesn't make sense for runtime units
// Related: https://github.com/coreos/ignition/issues/588
func (u Util) EnableRuntimeUnit(unit types.Unit, target string) error {
// we want to affect /run, which will be carried into the pivot,
// not a directory named /$DestDir/run
u.DestDir = "/"

link := types.Link{
Node: types.Node{
Filesystem: "root",
// XXX(jl): make Wants/Required a parameter
Path: filepath.Join(SystemdRuntimeUnitWantsPath(target), string(unit.Name)),
},
LinkEmbedded1: types.LinkEmbedded1{
Target: filepath.Join("/", SystemdRuntimeUnitsPath(), string(unit.Name)),
},
}

return u.WriteLink(link)
}

func (u Util) DisableUnit(unit types.Unit) error {
return u.appendLineToPreset(fmt.Sprintf("disable %s", unit.Name))
}
Expand Down

0 comments on commit af98f37

Please sign in to comment.