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 c59233c
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 18 deletions.
147 changes: 133 additions & 14 deletions internal/exec/stages/files/units.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,37 +17,96 @@ 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
if strings.Contains(unit.Name, "@") {
unitName, instance := parseInstanceUnit(unit)
if len(instance) > 0 {
if _, ok := presets[unitName]; ok {
presets[unitName].instances = append(presets[unitName].instances, instance)
} else {
presets[unitName] = &Preset{unitName, true, true, []string{instance}}
}
}

} else {
presets[unit.Name] = &Preset{unit.Name, true, false, []string{}}
}

} else {
if err := s.Logger.LogOp(
func() error { return s.DisableUnit(unit) },
"disabling unit %q", unit.Name,
); err != nil {
return err
if strings.Contains(unit.Name, "@") {
unitName, instance := parseInstanceUnit(unit)
if len(instance) > 0 {
presets[unitName] = &Preset{unitName, false, true, []string{instance}}
}

} else {
presets[unit.Name] = &Preset{unit.Name, false, false, []string{}}
}
}
enabledOneUnit = true
}
if unit.Mask != nil && *unit.Mask {
relabelpath := ""
Expand All @@ -65,9 +124,69 @@ 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 len(presets) != 0 {
if err := s.createSystemdPresetFile(presets); err != nil {
return err
}
}

return nil
}

// parseInstanceUnit is a helper function to extract the name
// and coresponding instances for a given instantiated unit.
func parseInstanceUnit(unit types.Unit) (string, string) {
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)]

return serviceInstance, instance
}

// createSystemdPresetFile creates the presetfile for enabled/disabled
// instantiated/systemd units.
func (s *stage) createSystemdPresetFile(presets map[string]*Preset) error {
var enableUnitString, disableUnitString string
hasInstanceUnit := false
for _, value := range presets {
if value.instantiateable {
hasInstanceUnit = 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
}
}
}

// Print the warning if there's an instantiated unit present under
// the systemd units and the version of systemd in a given system
// is less than 240.
if hasInstanceUnit {
s.warnOnOldSystemdVersion()
}
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 c59233c

Please sign in to comment.