-
Bug
-
Resolution: Unresolved
-
Major
-
None
-
4.20.z
Description of problem:
Unable to enable systemd service on OCP 4.20
Version-Release number of selected component (if applicable):
OCP 4.20.8
How reproducible:
Easily
Steps to Reproduce:
1. Create below machine-config to enable iscsid.service
apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
metadata:
labels:
machineconfiguration.openshift.io/role: worker
name: 99-worker-custom-enable-iscsid
spec:
config:
ignition:
version: 3.1.0
systemd:
units:
- enabled: true
name: iscsid.service
Actual results:
# systemctl status iscsid.service
○ iscsid.service - Open-iSCSI
Loaded: loaded (/usr/lib/systemd/system/iscsid.service; disabled; preset: disabled) <---------
Active: inactive (dead)
TriggeredBy: ● iscsid.socket
Docs: man:iscsid(8)
man:iscsiuio(8)
man:iscsiadm(8)
Expected results:
Should be enabled:
● iscsid.service - Open-iSCSI
Loaded: loaded (/usr/lib/systemd/system/iscsid.service; enabled; preset: disabled)
Additional info:
If you see why the service did not get enabled is due to below error, this error is logged in machine-config-daemon pod.
Could not enable unit "iscsid.service", because it has no contents, skipping <----------
This comes via below machine-config code:
// writeUnits writes the systemd units to disk
func (dn *Daemon) writeUnits(units []ign3types.Unit) error {
var enabledUnits []string
var disabledUnits []string
isCoreOSVariant := dn.os.IsCoreOSVariant()
for _, u := range units {
if err := writeUnit(u, pathSystemd, isCoreOSVariant); err != nil {
return fmt.Errorf("daemon could not write systemd unit: %w", err)
}
// if the unit doesn't note if it should be enabled or disabled then
// honour system presets. This to account for an edge case where you
// deleted a MachineConfig that enabled/disabled the unit to revert,
// but the unit itself is referenced in other MCs. deleteStaleData() will
// catch fully deleted units.
// if the unit should be enabled/disabled, then enable/disable it.
// this is a no-op if the system wasn't change this iteration
// Also, enable and disable as one command, as if any operation fails
// we'd bubble up the error anyways, and we save a lot of time doing this.
// Presets must be done individually as we don't consider a failed preset
// as an error, but it would cause other presets that would have succeeded
// to not go through.
if u.Enabled != nil {
// Only when a unit has contents should we attempt to enable or disable it. <-----
// See: https://issues.redhat.com/browse/OCPBUGS-56648
if unitHasContent(u) {
if *u.Enabled {
enabledUnits = append(enabledUnits, u.Name)
} else {
disabledUnits = append(disabledUnits, u.Name)
}
} else {
action := "disable"
if *u.Enabled {
action = "enable"
}
klog.Infof("Could not %s unit %q, because it has no contents, skipping", action, u.Name) <--------
layered image update loops on failure to find systemd unit files, MCP degraded
https://issues.redhat.com/browse/OCPBUGS-56648
commit 702dd8b295b052efb698405bec78288f01f58f4b
Author: Zack Zlotnik <zzlotnik@redhat.com>
Date: Wed May 28 11:07:21 2025 -0400
fixes systemd unit creation for empty units
If a MachineConfig is applied with empty systemd unit contents, the MCD
will degrade because it skips writing the file in that particular
situation. For parity with the CoreOS Ignition implementation, we should
not attempt to enable or disable any systemd units where the unit file
does not have any contents.
sounds like a regression to me.As Nutanix cannot certify their csi driver on OCP 4.20, they need this service to be enabled. This worked in previous versions.