Skip to content

Commit 92bc19d

Browse files
committed
Moved systemd service management to own bundle
This change moves the systemd service management promises to their own bundle. There should be no change in behavior as using standard_services when systemd is present will still result in the use of the same promises. This change makes it easier to maintain the policy as it is logically separate and allows explicit management of systemd services. Ticket: CFE-3381 Changelog: Title
1 parent 7eabc40 commit 92bc19d

1 file changed

Lines changed: 155 additions & 88 deletions

File tree

lib/services.cf

Lines changed: 155 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,20 @@ body service_method standard_services
7676
service_bundle => default:standard_services( $(this.promiser), $(this.service_policy) );
7777
}
7878

79-
##
79+
body service_method systemd_services
80+
# @brief systemd service method
81+
#
82+
# **Example:**
83+
#
84+
# ```cf3
85+
# services:
86+
# "ssh"
87+
# service_policy => "enabled",
88+
# service_method => systemd_services;
89+
# ```
90+
{
91+
service_bundle => default:systemd_services( $(this.promiser), $(this.service_policy) );
92+
}
8093

8194
bundle agent standard_services(service,state)
8295
# @brief Standard services bundle, used by CFEngine by default
@@ -94,7 +107,7 @@ bundle agent standard_services(service,state)
94107
# This bundle receives the service name and the desired service state,
95108
# then does the needful to reach the desired state.
96109
#
97-
# If you're running systemd, systemctl will be used.
110+
# If you're running systemd, systemctl will be used via `systemd_services`.
98111
#
99112
# Else, if chkconfig is present, it will be used.
100113
#
@@ -118,10 +131,16 @@ bundle agent standard_services(service,state)
118131
# methods:
119132
# "" usebundle => standard_services("sshd", "start"); # direct
120133
# ```
134+
#
135+
# Alternatively, since services promises are an abstraction around bundles, the service state can be promised via a methods type promise.
136+
#
137+
# ```cf3
138+
#
139+
# methods:
140+
# "SSHD should be running" usebundle => standard_services("sshd", "start");
141+
# ```
121142
{
122143
vars:
123-
"call_systemctl" string => "$(paths.systemctl) --no-ask-password --global --system";
124-
"systemd_properties" string => "-pLoadState,CanStop,UnitFileState,ActiveState,LoadState,CanStart,CanReload";
125144
"c_service" string => canonify("$(service)");
126145

127146
freebsd::
@@ -140,9 +159,6 @@ bundle agent standard_services(service,state)
140159
"chkconfig_mode" string => "off";
141160
"svcadm_mode" string => "disable";
142161

143-
systemd::
144-
"systemd_service_info" slist => string_split(execresult("$(call_systemctl) $(systemd_properties) show $(service)", "noshell"), "\n", "10");
145-
146162
classes:
147163
# define a class named after the desired state
148164
"$(state)" expression => "any";
@@ -179,86 +195,7 @@ bundle agent standard_services(service,state)
179195
service is not registered it must be added. Note we do not
180196
automatically try to add the service at this time.";
181197

182-
### BEGIN ###
183-
# @brief probe the state of a systemd service
184-
# @author Bryan Burke
185-
#
186-
# A collection of classes to determine the capabilities of a given systemd
187-
# service, then start, stop, etc. the service. Also supports a custom action
188-
# for anything not supported
189-
#
190-
systemd::
191-
"service_enabled" expression => reglist(@(systemd_service_info), "UnitFileState=enabled");
192-
"service_enabled" -> { "CFE-2923" }
193-
expression => returnszero( "$(call_systemctl) is-enabled $(service) > /dev/null 2>&1", useshell);
194-
"service_active" -> { "CFE-3238" }
195-
expression => reglist(@(systemd_service_info), "ActiveState=(active|activating)");
196-
"service_loaded" expression => reglist(@(systemd_service_info), "LoadState=loaded");
197-
"service_notfound" expression => reglist(@(systemd_service_info), "LoadState=not-found");
198-
199-
"can_stop_service" expression => reglist(@(systemd_service_info), "CanStop=yes");
200-
"can_start_service" expression => reglist(@(systemd_service_info), "CanStart=yes");
201-
"can_reload_service" expression => reglist(@(systemd_service_info), "CanReload=yes");
202-
203-
"request_start" expression => strcmp("start", "$(state)");
204-
"request_stop" expression => strcmp("stop", "$(state)");
205-
"request_reload" expression => strcmp("reload", "$(state)");
206-
"request_restart" expression => strcmp("restart", "$(state)");
207-
"request_disable" expression => strcmp("disable", "$(state)");
208-
"request_disabled" expression => strcmp("disabled", "$(state)");
209-
"request_enable" expression => strcmp("enable", "$(state)");
210-
"request_enabled" expression => strcmp("enabled", "$(state)");
211-
"request_active" expression => strcmp("active", "$(state)");
212-
"request_inactive" expression => strcmp("inactive", "$(state)");
213-
214-
"action_custom" expression => "!(request_start|request_stop|request_reload|request_restart|request_disable|request_disabled|request_enable|request_enabled|request_active|request_inactive)";
215-
"action_start" expression => "(request_start|request_active).!service_active.can_start_service";
216-
"action_stop" expression => "(request_stop|request_inactive).service_active.can_stop_service";
217-
"action_reload" expression => "request_reload.service_active.can_reload_service";
218-
"action_restart" or => {
219-
"request_restart",
220-
221-
# Possibly undesirable... if a reload is
222-
# requested, and the service "can't" be
223-
# reloaded, then we restart it instead.
224-
"request_reload.!can_reload_service.service_active",
225-
};
226-
227-
# Starting a service implicitly enables it
228-
"action_enable" expression => "(request_start|request_enable|request_enabled).!service_enabled";
229-
230-
# Respectively, stopping it implicitly disables it
231-
"action_disable" expression => "(request_disable|request_disabled|request_stop).service_enabled";
232-
233198
commands:
234-
systemd.service_loaded:: # note this class is defined in `inventory/linux.cf`
235-
# conveniently, systemd states map to `services` states, except
236-
# for `enable`
237-
238-
"$(call_systemctl) -q start $(service)"
239-
ifvarclass => "action_start";
240-
241-
"$(call_systemctl) -q stop $(service)"
242-
ifvarclass => "action_stop";
243-
244-
"$(call_systemctl) -q reload $(service)"
245-
ifvarclass => "action_reload";
246-
247-
"$(call_systemctl) -q restart $(service)"
248-
ifvarclass => "action_restart";
249-
250-
"$(call_systemctl) -q enable $(service)"
251-
ifvarclass => "action_enable";
252-
253-
"$(call_systemctl) -q disable $(service)"
254-
ifvarclass => "action_disable";
255-
256-
# Custom action for any of the non-standard systemd actions such a
257-
# status, try-restart, isolate, et al.
258-
"$(call_systemctl) $(state) $(service)"
259-
ifvarclass => "action_custom";
260-
261-
### END systemd section ###
262199

263200
chkconfig.stop.onboot::
264201
# Only chkconfig disable if it's currently set to start on boot
@@ -322,6 +259,10 @@ bundle agent standard_services(service,state)
322259
fallback::
323260
"classic" usebundle => classic_services($(service), $(state));
324261

262+
systemd::
263+
"systemd"
264+
usebundle => systemd_services( $(service), $(state) );
265+
325266
reports:
326267
verbose_mode.systemd::
327268
"$(this.bundle): using systemd layer to $(state) $(service)";
@@ -340,8 +281,134 @@ bundle agent standard_services(service,state)
340281
verbose_mode.fallback::
341282
"$(this.bundle): falling back to classic_services to $(state) $(service)";
342283

343-
systemd.service_notfound.(start|restart|reload).(inform_mode|verbose_mode)::
344-
"$(this.bundle): Could not find service: $(service)";
284+
}
285+
286+
bundle agent systemd_services(service,state)
287+
# @brief Manage systemd service state
288+
# @author Bryan Burke
289+
# @param service specific service to control
290+
# @param state The desired state for that service: "active", "inactive", "restart", "reload", "enabled", "disabled", "start", and "stop" are specifically understood states. Any other custom state will be passed through to systemctl.
291+
#
292+
# **State descriptions:**
293+
#
294+
# * active - Service should be running, no promise about state on boot made.
295+
# * inactive - Service should not be running, no promise about state on boot made.
296+
# * restart - Service should be restarted, no promise about state on boot made.
297+
# * reload - Service should be reloaded, no promise about state on boot made.
298+
# * enabled - Service should be enabled, no promise about state on boot made.
299+
# * disabled - Service should be reloaded, no promise about state on boot made.
300+
# * start - Service should be running, service should be started on boot (active + enabled).
301+
# * stop - Service should not be running, service should not be started on boot (inactive + disabled).
302+
#
303+
# **Example:**
304+
#
305+
# ```cf3
306+
# services:
307+
# # Uses `standard_services`, dynamic decision about init subsystem
308+
# "sshd"
309+
# service_policy => "enabled";
310+
#
311+
# # Explicitly use `systemd_services`
312+
# "sshd"
313+
# service_policy => "running",
314+
# service_policy => "systemd_services";
315+
# ```
316+
#
317+
# Alternatively, since services promises are an abstraction around bundles, the service state can be promised via a methods type promise.
318+
#
319+
# ```cf3
320+
#
321+
# methods:
322+
# "SSHD should be running" usebundle => systemd_services("sshd", "enabled");
323+
# ```
324+
{
325+
vars:
326+
systemd::
327+
"call_systemctl"
328+
string => "$(paths.systemctl) --no-ask-password --global --system";
329+
330+
"systemd_properties"
331+
string => "-pLoadState,CanStop,UnitFileState,ActiveState,LoadState,CanStart,CanReload";
332+
333+
"systemd_service_info"
334+
slist => string_split(execresult("$(call_systemctl) $(systemd_properties) show $(service)",
335+
"noshell"), "\n", "10");
336+
337+
classes:
338+
systemd::
339+
"service_enabled" expression => reglist(@(systemd_service_info), "UnitFileState=enabled");
340+
"service_enabled" -> { "CFE-2923" }
341+
expression => returnszero( "$(call_systemctl) is-enabled $(service) > /dev/null 2>&1", useshell);
342+
"service_active" -> { "CFE-3238" }
343+
expression => reglist(@(systemd_service_info), "ActiveState=(active|activating)");
344+
"service_loaded" expression => reglist(@(systemd_service_info), "LoadState=loaded");
345+
"service_notfound" expression => reglist(@(systemd_service_info), "LoadState=not-found");
346+
347+
"can_stop_service" expression => reglist(@(systemd_service_info), "CanStop=yes");
348+
"can_start_service" expression => reglist(@(systemd_service_info), "CanStart=yes");
349+
"can_reload_service" expression => reglist(@(systemd_service_info), "CanReload=yes");
350+
351+
"request_start" expression => strcmp("start", "$(state)");
352+
"request_stop" expression => strcmp("stop", "$(state)");
353+
"request_reload" expression => strcmp("reload", "$(state)");
354+
"request_restart" expression => strcmp("restart", "$(state)");
355+
"request_disable" expression => strcmp("disable", "$(state)");
356+
"request_disabled" expression => strcmp("disabled", "$(state)");
357+
"request_enable" expression => strcmp("enable", "$(state)");
358+
"request_enabled" expression => strcmp("enabled", "$(state)");
359+
"request_active" expression => strcmp("active", "$(state)");
360+
"request_inactive" expression => strcmp("inactive", "$(state)");
361+
362+
"action_custom" expression => "!(request_start|request_stop|request_reload|request_restart|request_disable|request_disabled|request_enable|request_enabled|request_active|request_inactive)";
363+
"action_start" expression => "(request_start|request_active).!service_active.can_start_service";
364+
"action_stop" expression => "(request_stop|request_inactive).service_active.can_stop_service";
365+
"action_reload" expression => "request_reload.service_active.can_reload_service";
366+
"action_restart" or => {
367+
"request_restart",
368+
369+
# Possibly undesirable... if a reload is
370+
# requested, and the service "can't" be
371+
# reloaded, then we restart it instead.
372+
"request_reload.!can_reload_service.service_active",
373+
};
374+
375+
# Starting a service implicitly enables it
376+
"action_enable" expression => "(request_start|request_enable|request_enabled).!service_enabled";
377+
378+
# Respectively, stopping it implicitly disables it
379+
"action_disable" expression => "(request_disable|request_disabled|request_stop).service_enabled";
380+
381+
commands:
382+
systemd.service_loaded:: # note this class is defined in `inventory/linux.cf`
383+
# conveniently, systemd states map to `services` states, except
384+
# for `enable`
385+
386+
"$(call_systemctl) -q start $(service)"
387+
ifvarclass => "action_start";
388+
389+
"$(call_systemctl) -q stop $(service)"
390+
ifvarclass => "action_stop";
391+
392+
"$(call_systemctl) -q reload $(service)"
393+
ifvarclass => "action_reload";
394+
395+
"$(call_systemctl) -q restart $(service)"
396+
ifvarclass => "action_restart";
397+
398+
"$(call_systemctl) -q enable $(service)"
399+
ifvarclass => "action_enable";
400+
401+
"$(call_systemctl) -q disable $(service)"
402+
ifvarclass => "action_disable";
403+
404+
# Custom action for any of the non-standard systemd actions such a
405+
# status, try-restart, isolate, et al.
406+
"$(call_systemctl) $(state) $(service)"
407+
ifvarclass => "action_custom";
408+
409+
reports:
410+
systemd.service_notfound.(inform_mode|verbose_mode)::
411+
"$(this.bundle): Could not find service: $(service)";
345412
}
346413

347414
bundle agent classic_services(service,state)

0 commit comments

Comments
 (0)