Systemd vs RedHat service providers on is-enabled=static

1,535 views
Skip to first unread message

Michael Smith

unread,
Apr 7, 2016, 2:44:47 PM4/7/16
to puppe...@googlegroups.com
PUP-5353 notes an inconsistency between the RedHat and Systemd providers (on EL7) in how they treat the `static` state returned by `systemctl is-enabled`.

Based on the systemctl description of `static`, this is a disabled state that cannot be enabled because it has no "[Install]" section.

On the other hand, `chkconfig` will return that the service can be started, which the RedHat provider interprets as being enabled.

My interpretation of `static` is that enabling the service has no meaning, and trying to manage whether it's enabled should fail. It's enable status should report `static`.

My question for the mailing list is:
- Which interpretation makes the most sense to Linux admins?
- Would it be a breaking change to make it an error to manage the `enable` property of a service that can't be enabled/disabled?

--
Michael Smith
Developer, Puppet Labs

Trevor Vaughan

unread,
Apr 7, 2016, 5:43:40 PM4/7/16
to puppe...@googlegroups.com
I think that, if the service is 'static' then the enable/disable state should be disregarded.

You don't want to error out on this because you'll now have to have a million if/else cases for every OS out there that the Providers really should "just handle".

I would just make it a noop and note it that way in the documentation with the description that you posted above.

Thanks,

Trevor

--
You received this message because you are subscribed to the Google Groups "Puppet Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-dev+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/CABy1mMJ9wqiNwS4ha_Wgpa4ZDFxETp9JK6_H13xkAsUhqzHYcw%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.



--
Trevor Vaughan
Vice President, Onyx Point, Inc
(410) 541-6699

-- This account not approved for unencrypted proprietary information --

John Bollinger

unread,
Apr 11, 2016, 11:35:57 AM4/11/16
to Puppet Developers


On Thursday, April 7, 2016 at 1:44:47 PM UTC-5, Michael Smith wrote:
PUP-5353 notes an inconsistency between the RedHat and Systemd providers (on EL7) in how they treat the `static` state returned by `systemctl is-enabled`.

Based on the systemctl description of `static`, this is a disabled state that cannot be enabled because it has no "[Install]" section.

On the other hand, `chkconfig` will return that the service can be started, which the RedHat provider interprets as being enabled.
 
My interpretation of `static` is that enabling the service has no meaning, and trying to manage whether it's enabled should fail. It's enable status should report `static`.



Let's be very careful here.  I think part of the problem is that systemd and Puppet have slightly different ideas about what "enable" means.  In particular, the core problem seems to be that Puppet assumes (not unreasonably) that successfully "enabling" a service leaves that service in the "enabled" state, whereas with systemd / systemctl, "enabling" a unit that is initially in the 'static' enablement state is a no-op, and therefore succeeds without changing the enablement state.

In fact, although the docs describe 'static' enablement status as "not enabled", it also is not 'disabled', as that is a distinct status.  The fact that systemd has ten (ten!) enablement statuses whereas Puppet recognizes only two should be a big red flag.

 
My question for the mailing list is:
- Which interpretation makes the most sense to Linux admins?


I quibble slightly with your interpretation.  It is manifestly incorrect to say that "enabling the service has no meaning," whether you're talking about systemctl or (current) Puppet.  I would say rather that enabling the unit has no effect (though this relies systemctl's sense of "enable"), and also that its status cannot be accurately captured by a non-nullable boolean flag.

Inasmuch as an attempt to enable a unit with 'static' enablement status does not in fact effect a change in that unit's status, it could be reasonable to interpret that as a failure -- the specified state is not set -- but only if 'static' does not map to 'enabled' (which it currently does not).

One could argue that a systemctl unit with 'static' enablement status should not map to any Service instance in the first place, as I suppose is the case for units having either of the two 'masked' statuses.  Such a unit does not, in fact, represent a service in the normal sense.

 
- Would it be a breaking change to make it an error to manage the `enable` property of a service that can't be enabled/disabled?



Yes, of course it would be.  Catalogs that are now applied successfully, albeit with vacuous changes, would instead fail.  Note also that PUP-5353 has an unreported dual: attempting to manage a 'static' systemd unit to be disabled currently succeeds without applying any changes (or so I assume).  That also would break.

Moreover, if the behavior change you describe were implemented by modifying the data type of Service's 'enabled' property, as you seemed to suggest, then all Service providers, including custom ones, would break (though perhaps the resulting flaws would not immediately be evident).  Consider also that if you define another distinct allowed value for Service.enabled, then it should be possible to assert that value, even if there is no way to change a service into that state -- it would not be sensible for managing a 'static' unit to be 'static' to fail.

Without regard to implementation details, it seems to me that the simplest non-breaking fix for PUP-5353 would be to make 'static' enablement status always be in-sync.  This coincides with systemctl's dynamic behavior and is at odds with Puppet's state-based model of the system, but there's no non-breaking way to make Puppet Service resources model this aspect of the state space of systemd units.  If that approach sticks in your craw, then you could consider refusing to map 'static' systemd units to Service resources at all.  That, too, would be a breaking change, but it's conceivable that you would find it more acceptable.


John

Michael Smith

unread,
Apr 11, 2016, 1:20:22 PM4/11/16
to puppe...@googlegroups.com
On Mon, Apr 11, 2016 at 8:35 AM, John Bollinger <john.bo...@stjude.org> wrote:


On Thursday, April 7, 2016 at 1:44:47 PM UTC-5, Michael Smith wrote:
PUP-5353 notes an inconsistency between the RedHat and Systemd providers (on EL7) in how they treat the `static` state returned by `systemctl is-enabled`.

Based on the systemctl description of `static`, this is a disabled state that cannot be enabled because it has no "[Install]" section.

On the other hand, `chkconfig` will return that the service can be started, which the RedHat provider interprets as being enabled.
 
My interpretation of `static` is that enabling the service has no meaning, and trying to manage whether it's enabled should fail. It's enable status should report `static`.



Let's be very careful here.  I think part of the problem is that systemd and Puppet have slightly different ideas about what "enable" means.  In particular, the core problem seems to be that Puppet assumes (not unreasonably) that successfully "enabling" a service leaves that service in the "enabled" state, whereas with systemd / systemctl, "enabling" a unit that is initially in the 'static' enablement state is a no-op, and therefore succeeds without changing the enablement state.

In fact, although the docs describe 'static' enablement status as "not enabled", it also is not 'disabled', as that is a distinct status.  The fact that systemd has ten (ten!) enablement statuses whereas Puppet recognizes only two should be a big red flag.

The question of how to deal with more states (systemd's 10 enablement statuses), some of which can't be enforced, seems interesting. Have any thoughts on it?
 

 
My question for the mailing list is:
- Which interpretation makes the most sense to Linux admins?


I quibble slightly with your interpretation.  It is manifestly incorrect to say that "enabling the service has no meaning," whether you're talking about systemctl or (current) Puppet.  I would say rather that enabling the unit has no effect (though this relies systemctl's sense of "enable"), and also that its status cannot be accurately captured by a non-nullable boolean flag.

Inasmuch as an attempt to enable a unit with 'static' enablement status does not in fact effect a change in that unit's status, it could be reasonable to interpret that as a failure -- the specified state is not set -- but only if 'static' does not map to 'enabled' (which it currently does not).

One could argue that a systemctl unit with 'static' enablement status should not map to any Service instance in the first place, as I suppose is the case for units having either of the two 'masked' statuses.  Such a unit does not, in fact, represent a service in the normal sense.

 
- Would it be a breaking change to make it an error to manage the `enable` property of a service that can't be enabled/disabled?



Yes, of course it would be.  Catalogs that are now applied successfully, albeit with vacuous changes, would instead fail.  Note also that PUP-5353 has an unreported dual: attempting to manage a 'static' systemd unit to be disabled currently succeeds without applying any changes (or so I assume).  That also would break.

Moreover, if the behavior change you describe were implemented by modifying the data type of Service's 'enabled' property, as you seemed to suggest, then all Service providers, including custom ones, would break (though perhaps the resulting flaws would not immediately be evident).  Consider also that if you define another distinct allowed value for Service.enabled, then it should be possible to assert that value, even if there is no way to change a service into that state -- it would not be sensible for managing a 'static' unit to be 'static' to fail.

Without regard to implementation details, it seems to me that the simplest non-breaking fix for PUP-5353 would be to make 'static' enablement status always be in-sync.  This coincides with systemctl's dynamic behavior and is at odds with Puppet's state-based model of the system, but there's no non-breaking way to make Puppet Service resources model this aspect of the state space of systemd units.  If that approach sticks in your craw, then you could consider refusing to map 'static' systemd units to Service resources at all.  That, too, would be a breaking change, but it's conceivable that you would find it more acceptable.


I err on providing more feedback when trying to do things that don't make sense - like apply Puppet's enable/disable states to a static service - but accept that this would make applying the same resource across multiple systems difficult. Making it always in-sync would work. Displaying the state as enabled if queried is probably the best fit for Puppet's concept of enabled/disabled, as it's check `systemctl is-enabled` returns 0 (enabled) for `static` status.


John

--
You received this message because you are subscribed to the Google Groups "Puppet Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-dev+...@googlegroups.com.

John Bollinger

unread,
Apr 11, 2016, 6:31:12 PM4/11/16
to Puppet Developers


On Monday, April 11, 2016 at 12:20:22 PM UTC-5, Michael Smith wrote:


On Mon, Apr 11, 2016 at 8:35 AM, John Bollinger <john.bo...@stjude.org> wrote:
 
Let's be very careful here.  I think part of the problem is that systemd and Puppet have slightly different ideas about what "enable" means.  In particular, the core problem seems to be that Puppet assumes (not unreasonably) that successfully "enabling" a service leaves that service in the "enabled" state, whereas with systemd / systemctl, "enabling" a unit that is initially in the 'static' enablement state is a no-op, and therefore succeeds without changing the enablement state.

In fact, although the docs describe 'static' enablement status as "not enabled", it also is not 'disabled', as that is a distinct status.  The fact that systemd has ten (ten!) enablement statuses whereas Puppet recognizes only two should be a big red flag.

The question of how to deal with more states (systemd's 10 enablement statuses), some of which can't be enforced, seems interesting. Have any thoughts on it?


There are really only two main alternatives from the perspective of Puppet's configuration model:
  1. model the additional states on the existing resource type via additional properties or additional allowed values for existing properties, or
  2. model resources in some states via altogether different resource types.
The latter is appealing from a consistency perspective for handling resources with an immutable piece of state, such as systemd services having 'static' enablement status: if we take it as a matter of the definition of "service" that services are either enabled or disabled and can be switched between those two states, then it follows that a systemd 'service' unit that has 'static' enablement status is not, in fact, a "service" by our definition.  More generally, it should be self-evident that no immutable piece of state is well modeled as a value of a mutable Puppet property.

Where one does model an aspect of machine state as a property, Puppet should be able to determine whether that property is in sync, should recognize and accept that property being in sync, and should fail if it attempts unsuccessfully to change the property's actual value on a target node.  This is what you suggested for PUP-5353; the problem there is that you also want to avoid a breaking change.

There is a bit of grey area here, however, in that resource property values are not necessarily mutually exclusive.  Consider, for example, the 'ensure' property of the Package or File resource type: if you ensure a File 'present' or a Package 'installed' then that encompasses several possible specific states.  In fact, in the Package case, it encompasses an unspecified, unbounded, and perhaps unknown number of possible specific states for any given instance at any given time.

Going back to systemd, the approach that both Trevor and I suggested is close to considering 'static' as a property value that is encompassed by both of the recognized states of the 'enabled' property.  That's not quite what I described before, because the Service resource does not recognize 'static' enablement in its own right.  It would also be novel in that as far as I am aware, it would make Service.enabled the only property I can think of that with recognized values that overlap without one subsuming the other.  Nevertheless, it's not necessarily inconsistent to treat 'static' enablement as simultaneously both enabled and not enabled, as opposed to neither.  I think it is inconsistent, however, to consider 'static' enablement as one of those but not the other.

 
I err on providing more feedback when trying to do things that don't make sense - like apply Puppet's enable/disable states to a static service - but accept that this would make applying the same resource across multiple systems difficult. Making it always in-sync would work. Displaying the state as enabled if queried is probably the best fit for Puppet's concept of enabled/disabled, as it's check `systemctl is-enabled` returns 0 (enabled) for `static` status.



You could, of course, have Puppet emit a warning when it manages the enablement status of a service that initially has 'static' status.  That would perhaps be better than accepting silently.  Or perhaps not.

The need to be able to answer a query for the state with exactly one of the two defined alternatives constitutes a bit of a sore spot, but I'm inclined to think that's the least bad alternative currently available.


John

Michael Smith

unread,
Apr 15, 2016, 1:32:43 PM4/15/16
to puppe...@googlegroups.com
 
I err on providing more feedback when trying to do things that don't make sense - like apply Puppet's enable/disable states to a static service - but accept that this would make applying the same resource across multiple systems difficult. Making it always in-sync would work. Displaying the state as enabled if queried is probably the best fit for Puppet's concept of enabled/disabled, as it's check `systemctl is-enabled` returns 0 (enabled) for `static` status.



You could, of course, have Puppet emit a warning when it manages the enablement status of a service that initially has 'static' status.  That would perhaps be better than accepting silently.  Or perhaps not.

The need to be able to answer a query for the state with exactly one of the two defined alternatives constitutes a bit of a sore spot, but I'm inclined to think that's the least bad alternative currently available.

Thanks, we ended up opting for logging a debug message when trying to disable 'static', and otherwise following Trevor and your suggestion. The conclusion is captured at https://tickets.puppetlabs.com/browse/PUP-5353?focusedCommentId=286407&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-286407.

Reply all
Reply to author
Forward
0 new messages