Skip to content

Commit

Permalink
Code to fix the systemd instatiated services when enabled/disabled vi…
Browse files Browse the repository at this point in the history
…a ignition
  • Loading branch information
sohankunkerkar committed Mar 16, 2020
1 parent c48bcf9 commit 965dd1e
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 15 deletions.
132 changes: 121 additions & 11 deletions internal/exec/stages/files/units.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,89 @@ package files
import (
"fmt"
"path/filepath"
"strconv"
"strings"

"github.com/coreos/go-systemd/dbus"
"github.com/coreos/ignition/v2/config/v3_1_experimental/types"
"github.com/coreos/ignition/v2/internal/distro"
"github.com/coreos/ignition/v2/internal/exec/util"
)

type Preset struct {
unit string
enabled bool
instantiateable bool
instances []string
}

// warnOnOldSystemdVersion checks the version of Systemd
// in a given system.
func (s *stage) warnOnOldSystemdVersion() error {
var systemdVersion string
var begin, end int
conn, err := dbus.New()
if err != nil {
return err
}
version, err := conn.GetManagerProperty("Version")
if err != nil {
return err
}
// Handle different systemd versioning schemes that are being returned.
// for e.g:
// - Fedora 31: `v243.5-1.fc31`
// - RHEL 8: `239`
if strings.HasPrefix(version, "v") {
begin = 1

} else {
begin = 0
}
end = strings.Index(version, ".")
if end == -1 {
end = len(version)
}
systemdVersion = version[begin:end]
if value, err := strconv.Atoi(systemdVersion); err == nil {
if value < 240 {
if err := s.Logger.Warning("The version of systemd (%q) is less than 240. Enabling/disabling instantiated units may not work. See https://github.com/coreos/ignition/issues/586 for more information.", systemdVersion); err != nil {
return err
}
}
} else {
return err
}
return nil
}

// createUnits creates the units listed under systemd.units.
func (s *stage) createUnits(config types.Config) error {
enabledOneUnit := false
presets := make(map[string]*Preset)
for _, unit := range config.Systemd.Units {
if err := s.writeSystemdUnit(unit, false); err != nil {
return err
}
if unit.Enabled != nil {
if *unit.Enabled {
if err := s.Logger.LogOp(
func() error { return s.EnableUnit(unit) },
"enabling unit %q", unit.Name,
); err != nil {
return err
unitName, instanceUnit := parseInstanceUnit(unit)
if len(instanceUnit) > 0 {
if _, ok := presets[instanceUnit[0]]; ok {
presets[instanceUnit[0]].instances = append(presets[instanceUnit[0]].instances, instanceUnit[1])
} else {
presets[instanceUnit[0]] = &Preset{instanceUnit[0], true, true, []string{instanceUnit[1]}}
}
} else {
presets[unitName] = &Preset{unitName, true, false, []string{}}
}

} else {
if err := s.Logger.LogOp(
func() error { return s.DisableUnit(unit) },
"disabling unit %q", unit.Name,
); err != nil {
return err
unitName, instanceUnit := parseInstanceUnit(unit)
if len(instanceUnit) > 0 {
presets[instanceUnit[0]] = &Preset{instanceUnit[0], false, true, []string{instanceUnit[1]}}
} else {
presets[unitName] = &Preset{unitName, false, false, []string{}}
}
}
enabledOneUnit = true
Expand All @@ -66,8 +121,63 @@ func (s *stage) createUnits(config types.Config) error {
}
// and relabel the preset file itself if we enabled/disabled something
if enabledOneUnit {
s.relabel(util.PresetPath)
if err := s.createSystemdPresetFile(presets); err != nil {
return err
}
}

return nil
}

func parseInstanceUnit(unit types.Unit) (string, []string) {
var instanceUnitArr []string
if strings.Contains(unit.Name, "@") {
at := strings.Index(unit.Name, "@")
dot := strings.Index(unit.Name, ".")
instance := unit.Name[at+1 : dot]
serviceInstance := unit.Name[0:at+1] + unit.Name[dot:len(unit.Name)]
instanceUnitArr = append(instanceUnitArr, serviceInstance, instance)
}
return unit.Name, instanceUnitArr
}

// createSystemdPresetFile creates the presetfile for enabled/disabled
// instantiated/systemd units.
func (s *stage) createSystemdPresetFile(presets map[string]*Preset) error {
var enableUnitString, disableUnitString string
flag := false
for _, value := range presets {
if value.instantiateable && flag == false {
s.warnOnOldSystemdVersion()
flag = true
}
if value.enabled {
if value.instantiateable {
enableUnitString = value.unit + " " + strings.Join(value.instances, " ")
} else {
enableUnitString = value.unit
}
if err := s.Logger.LogOp(
func() error { return s.EnableUnit(enableUnitString) },
"enabling unit %q", enableUnitString,
); err != nil {
return err
}
} else {
if value.instantiateable {
disableUnitString = value.unit + " " + strings.Join(value.instances, " ")
} else {
disableUnitString = value.unit
}
if err := s.Logger.LogOp(
func() error { return s.DisableUnit(disableUnitString) },
"disabling unit %q", disableUnitString,
); err != nil {
return err
}
}
}
s.relabel(util.PresetPath)
return nil
}

Expand Down
8 changes: 4 additions & 4 deletions internal/exec/util/unit.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ func (ut Util) MaskUnit(unit types.Unit) (string, error) {
return filepath.Join("/", SystemdUnitsPath(), unit.Name), nil
}

func (ut Util) EnableUnit(unit types.Unit) error {
return ut.appendLineToPreset(fmt.Sprintf("enable %s", unit.Name))
func (ut Util) EnableUnit(enabledUnit string) error {
return ut.appendLineToPreset(fmt.Sprintf("enable %s", enabledUnit))
}

// presets link in /etc, which doesn't make sense for runtime units
Expand Down Expand Up @@ -145,8 +145,8 @@ func (ut Util) EnableRuntimeUnit(unit types.Unit, target string) error {
return ut.WriteLink(link)
}

func (ut Util) DisableUnit(unit types.Unit) error {
return ut.appendLineToPreset(fmt.Sprintf("disable %s", unit.Name))
func (ut Util) DisableUnit(disabledUnit string) error {
return ut.appendLineToPreset(fmt.Sprintf("disable %s", disabledUnit))
}

func (ut Util) appendLineToPreset(data string) error {
Expand Down

0 comments on commit 965dd1e

Please sign in to comment.