Skip to content

Commit e59b7d4

Browse files
authored
Merge pull request #1805 from nickanderson/CFE-3381/master
CFE-3381/master: Moved systemd service management to own bundle
2 parents 7eabc40 + 92bc19d commit e59b7d4

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)