@@ -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
8194bundle 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
347414bundle agent classic_services(service,state)
0 commit comments