1############################################################################
2#  Copyright 2017 Northern.tech AS
3#
4#  This program is free software; you can redistribute it and/or modify it
5#  under the terms of the GNU Lesser General Public License LGPL as published by the
6#  Free Software Foundation; version 3.
7#
8#  This program is distributed in the hope that it will be useful,
9#  but WITHOUT ANY WARRANTY; without even the implied warranty of
10#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11#  GNU General Public License for more details.
12#
13#  To the extent this program is licensed as part of the Enterprise
14#  versions of CFEngine, the applicable Commercial Open Source License
15#  (COSL) may apply to this file if you as a licensee so wish it. See
16#  included file COSL.txt.
17###########################################################################
18#
19# CFEngine Community Open Promise-Body Library
20#
21# This initiative started by CFEngine promotes a
22# standardized set of names and promise specifications
23# for template functionality within CFEngine 3.
24#
25# The aim is to promote an industry standard for
26# naming of configuration patterns, leading to a
27# de facto middleware of standardized syntax.
28#
29# Names should be intuitive and parameters should be
30# minimal to assist readability and comprehensibility.
31
32# Contributions to this file are voluntarily given to
33# the cfengine community, and are moderated by CFEngine.
34# No liability or warranty for misuse is implied.
35#
36# If you add to this file, please try to make the
37# contributions "self-documenting". Comments made
38# after the bundle/body statement are retained in
39# the online docs
40#
41
42# Services bodies
43
44###################################################
45# If you find CFEngine useful, please consider    #
46# purchasing a commercial version of the software.#
47###################################################
48
49bundle common services_common
50# @ignore
51{
52  vars:
53      "inputs" slist => { "$(this.promise_dirname)/common.cf",
54                          "$(this.promise_dirname)/paths.cf" };
55}
56
57body file control
58# @ignore
59{
60      inputs => { @(services_common.inputs) };
61}
62
63##-------------------------------------------------------
64## service promises
65##-------------------------------------------------------
66
67body service_method bootstart
68# @brief Start the service and all its dependencies at boot time
69#
70# **See also:** `service_autostart_policy`, `service_dependence_chain`
71{
72      service_autostart_policy => "boot_time";
73      service_dependence_chain => "start_parent_services";
74    windows::
75      service_type => "windows";
76}
77
78##
79
80body service_method force_deps
81# @brief Start all dependendencies when this service starts, and stop all
82# dependent services when this service stops.
83#
84# The service does not get automatically started.
85#
86# **See also:** `service_autostart_policy`, `service_dependence_chain`
87{
88      service_dependence_chain => "all_related";
89    windows::
90      service_type => "windows";
91}
92
93body service_method standard_services
94# @brief Default services_method for when you wan't to call it explicitly
95#
96# By default this service_method is *not* used. The call for standard_services
97# is within the core and not here. In case you use a promise like:
98#
99# ```cf3
100# services:
101#     "ssh"
102#       service_policy => "start";
103# ```
104#
105# Then this method is skipped and CFEngine calls standard_services bundle
106# directly. This is here as a helper in case you wan't to be explicit
107# with your service promise and point it to standard_services (for readability,
108# documentation, etc).
109#
110# Do note that any options defined in this method does not apply to service
111# promises without explicit template_method call for standard_services.
112#
113# **Example:**
114#
115# ```cf3
116# services:
117#     "ssh"
118#       service_policy => "start",
119#       service_method => standard_services;
120# ```
121{
122        service_bundle => default:standard_services( $(this.promiser), $(this.service_policy) );
123}
124
125##
126
127bundle agent standard_services(service,state)
128# @brief Standard services bundle, used by CFEngine by default
129# @author CFEngine AS
130# @param service Name of service to control
131# @param state The desired state for that service: "start", "restart", "reload", "stop", or "disable"
132#
133# This bundle is used by CFEngine if you don't specify a services
134# handler explicitly, and will work with systemd or chkconfig or other
135# non-sysvinit service managers. It will try to automate service
136# discovery, unlike `classic_services` which requires known service
137# names. If it can't do the automatic management, it will pass control
138# to `classic_services`.
139#
140# This bundle receives the service name and the desired service state,
141# then does the needful to reach the desired state.
142#
143# If you're running systemd, systemctl will be used.
144#
145# Else, if chkconfig is present, it will be used.
146#
147# Else, if the service command is available, if will be used.
148#
149# Else, if the svcadm command is available, if will be used. Note you
150# have to supply the full SMF service identifier.
151#
152# Else, control is passed to `classic_services`.
153#
154# Note you do **not** have to call this bundle from `services`
155# promises. You can simply make a `methods` call to it. That would
156# enable you to use systemd states like `try-restart` for instance.
157#
158# **Example:**
159#
160# ```cf3
161# services:
162#     "sshd" service_policy => "start"; # uses `standard_services`
163#
164# methods:
165#     "" usebundle => standard_services("sshd", "start"); # direct
166# ```
167{
168  vars:
169      "call_systemctl" string => "$(paths.systemctl) --no-ask-password --global --system";
170      "systemd_properties" string => "-pLoadState,CanStop,UnitFileState,ActiveState,LoadState,CanStart,CanReload";
171      "c_service" string => canonify("$(service)");
172
173    freebsd::
174      "init" string => ifelse(fileexists("/usr/local/etc/rc.d/$(service)"),
175                              "/usr/local/etc/rc.d/$(service)",
176                              "/etc/rc.d/$(service)");
177
178    !freebsd::
179      "init" string => "/etc/init.d/$(service)";
180
181    start|restart|reload::
182      "chkconfig_mode" string => "on";
183      "svcadm_mode" string => "enable";
184
185    stop|disable::
186      "chkconfig_mode" string => "off";
187      "svcadm_mode" string => "disable";
188
189    systemd::
190      "systemd_service_info" slist => string_split(execresult("$(call_systemctl) $(systemd_properties) show $(service)", "noshell"), "\n", "10");
191
192  classes:
193      # define a class named after the desired state
194      "$(state)" expression => "any";
195      "non_disabling" or => { "start", "stop", "restart", "reload" };
196
197      "chkconfig" expression => "!systemd._stdlib_path_exists_chkconfig";
198      "sysvservice" expression => "!systemd.!chkconfig._stdlib_path_exists_service";
199      "smf" expression => "!systemd.!chkconfig.!sysvservice._stdlib_path_exists_svcadm";
200      "fallback" expression => "!systemd.!chkconfig.!sysvservice.!smf";
201
202      "have_init" expression => fileexists($(init));
203
204    chkconfig.have_init::
205      "running" expression => returnszero("$(init) status > /dev/null", "useshell");
206
207    sysvservice.have_init::
208      "running" expression => returnszero("$(paths.service) $(service) status > /dev/null", "useshell");
209
210    chkconfig.SuSE::
211      "onboot"
212        expression => returnszero("$(paths.chkconfig) $(service) | $(paths.grep) 'on$' >/dev/null", "useshell"),
213        comment => "SuSE chkconfig outputs current state to stdout rather than as an exit code";
214
215    chkconfig.!SuSE::
216      "onboot"
217        expression => returnszero("$(paths.chkconfig) $(service)", "noshell"),
218        comment => "We need to know if the service is configured to start at boot or not";
219
220      # We redirect stderr and stdout to dev null so that we do not create noise in the logs
221      "chkconfig_$(c_service)_unregistered"
222        not => returnszero("$(paths.chkconfig) --list $(service) &> /dev/null", "useshell"),
223        comment => "We need to know if the service is registered with chkconfig
224                    so that we can perform other chkconfig operations, if the
225                    service is not registered it must be added.  Note we do not
226                    automatically try to add the service at this time.";
227
228### BEGIN ###
229# @brief probe the state of a systemd service
230# @author Bryan Burke
231#
232# A collection of classes to determine the capabilities of a given systemd
233# service, then start, stop, etc. the service. Also supports a custom action
234# for anything not supported
235#
236    systemd::
237      "service_enabled" expression => reglist(@(systemd_service_info), "UnitFileState=enabled");
238      "service_enabled" -> { "CFE-2923" }
239        expression => returnszero( "$(call_systemctl) is-enabled $(service) > /dev/null 2>&1", useshell);
240      "service_active" -> { "CFE-3238" }
241        expression => reglist(@(systemd_service_info), "ActiveState=(active|activating)");
242      "service_loaded"  expression => reglist(@(systemd_service_info), "LoadState=loaded");
243      "service_notfound" expression => reglist(@(systemd_service_info), "LoadState=not-found");
244
245      "can_stop_service"   expression => reglist(@(systemd_service_info), "CanStop=yes");
246      "can_start_service"  expression => reglist(@(systemd_service_info), "CanStart=yes");
247      "can_reload_service" expression => reglist(@(systemd_service_info), "CanReload=yes");
248
249      "request_start"   expression => strcmp("start", "$(state)");
250      "request_stop"    expression => strcmp("stop", "$(state)");
251      "request_reload"  expression => strcmp("reload", "$(state)");
252      "request_restart" expression => strcmp("restart", "$(state)");
253      "request_disable" expression => strcmp("disable", "$(state)");
254
255      "action_custom"  expression => "!(request_start|request_stop|request_reload|request_restart|request_disable)";
256      "action_start"   expression => "request_start.!service_active.can_start_service";
257      "action_stop"    expression => "request_stop.service_active.can_stop_service";
258      "action_reload"  expression => "request_reload.service_active.can_reload_service";
259      "action_restart"         or => {
260                                      "request_restart",
261
262                                      # Possibly undesirable... if a reload is
263                                      # requested, and the service "can't" be
264                                      # reloaded, then we restart it instead.
265                                      "request_reload.!can_reload_service.service_active",
266                                     };
267
268      # Starting a service implicitly enables it
269      "action_enable"  expression => "request_start.!service_enabled";
270
271      # Respectively, stopping it implicitly disables it
272      "action_disable" expression => "(request_disable|request_stop).service_enabled";
273
274  commands:
275    systemd.service_loaded:: # note this class is defined in `inventory/linux.cf`
276      # conveniently, systemd states map to `services` states, except
277      # for `enable`
278
279      "$(call_systemctl) -q start $(service)"
280        ifvarclass => "action_start";
281
282      "$(call_systemctl) -q stop $(service)"
283        ifvarclass => "action_stop";
284
285      "$(call_systemctl) -q reload $(service)"
286        ifvarclass => "action_reload";
287
288      "$(call_systemctl) -q restart $(service)"
289        ifvarclass => "action_restart";
290
291      "$(call_systemctl) -q enable $(service)"
292        ifvarclass => "action_enable";
293
294      "$(call_systemctl) -q disable $(service)"
295        ifvarclass => "action_disable";
296
297      # Custom action for any of the non-standard systemd actions such a
298      # status, try-restart, isolate, et al.
299      "$(call_systemctl) $(state) $(service)"
300        ifvarclass => "action_custom";
301
302### END systemd section ###
303
304    chkconfig.stop.onboot::
305      # Only chkconfig disable if it's currently set to start on boot
306      "$(paths.chkconfig) $(service) $(chkconfig_mode)"
307      classes => kept_successful_command,
308      contain => silent;
309
310    chkconfig.start.!onboot::
311      # Only chkconfig enable service if it's not already set to start on boot, and if its a registered chkconfig service
312      "$(paths.chkconfig) $(service) $(chkconfig_mode)"
313      ifvarclass => "!chkconfig_$(c_service)_unregistered",
314      classes => kept_successful_command,
315      contain => silent;
316
317    chkconfig.have_init.(((start|restart).!running)|((stop|restart|reload).running)).non_disabling::
318      "$(init) $(state)"
319      contain => silent;
320
321    sysvservice.start.!running::
322      "$(paths.service) $(service) start"
323      handle => "standard_services_sysvservice_not_running_start",
324      classes => kept_successful_command,
325      comment => "If the service should be running and it is not
326                  currently running then we should issue the standard service
327                  command to start the service.";
328
329    sysvservice.restart::
330      "$(paths.service) $(service) restart"
331      handle => "standard_services_sysvservice_restart",
332      classes => kept_successful_command,
333      comment => "If the service should be restarted we issue the
334                  standard service command to restart or reload the service.
335                  There is no restriction based on the services current state as
336                  restart can start a service that was not already
337                  running.";
338
339    sysvservice.reload.running::
340      "$(paths.service) $(service) reload"
341      handle => "standard_services_sysvservice_reload",
342      classes => kept_successful_command,
343      comment => "If the service should be reloaded we issue the
344                  standard service command to reload the service.
345                  It is restricted to when the service is running as a reload
346                  should not start services that are not already running. This
347                  may not be triggered as service state parameters are limited
348                  and translated to the closest meaning.";
349
350    sysvservice.((stop|disable).running)::
351      "$(paths.service) $(service) stop"
352      handle => "standard_services_sysvservice_stop",
353      classes => kept_successful_command,
354      comment => "If the service should be stopped or disabled and it is
355                  currently running then we should issue the standard service
356                  command to stop the service.";
357
358    smf::
359      "$(paths.svcadm) $(svcadm_mode) $(service)"
360      classes => kept_successful_command;
361
362  methods:
363    fallback::
364      "classic" usebundle => classic_services($(service), $(state));
365
366  reports:
367    verbose_mode.systemd::
368      "$(this.bundle): using systemd layer to $(state) $(service)";
369    verbose_mode.systemd.!service_loaded::
370      "$(this.bundle): Service $(service) unit file is not loaded; doing nothing";
371    verbose_mode.chkconfig::
372      "$(this.bundle): using chkconfig layer to $(state) $(service) (chkconfig mode $(chkconfig_mode))"
373        ifvarclass => "!chkconfig_$(c_service)_unregistered.((start.!onboot)|(stop.onboot))";
374    verbose_mode.chkconfig::
375      "$(this.bundle): skipping chkconfig layer to $(state) $(service) because $(service) is not registered with chkconfig (chkconfig --list $(service))"
376        ifvarclass => "chkconfig_$(c_service)_unregistered";
377    verbose_mode.sysvservice::
378      "$(this.bundle): using System V service / Upstart layer to $(state) $(service)";
379    verbose_mode.smf::
380      "$(this.bundle): using Solaris SMF to $(state) $(service) (svcadm mode $(svcadm_mode))";
381    verbose_mode.fallback::
382      "$(this.bundle): falling back to classic_services to $(state) $(service)";
383
384    systemd.service_notfound.(start|restart|reload).(inform_mode|verbose_mode)::
385        "$(this.bundle): Could not find service: $(service)";
386}
387
388bundle agent classic_services(service,state)
389# @brief Classic services bundle
390# @author CFEngine AS
391# @author Tero Kantonen <prkele@gmail.com>
392# @param service specific service to control
393# @param state desired state for that service
394#
395# This bundle is used by `standard_services` if it doesn't have an
396# automatic driver for the current service manager.
397#
398# It receives the service name and the desired service state, then
399# does the needful to reach the desired state.
400#
401# **Example:**
402#
403# ```cf3
404# services:
405#     "ntp" service_policy => "start";
406#     "ssh" service_policy => "stop";
407# ```
408#
409# There's multiple ways you can add new services to this list.
410# Here's few examples:
411#
412# a) The zeroconf mode; If the new service matches these rules,
413#    you don't need to add anything to the standard_services:
414#
415#  1. Your init script basename = `$(service)`
416#  2. Your init script argument = `$(state)`
417#  3. Your init script lives in `/etc/init.d/` (for non-*bsd),
418#     or `/etc/rc.d/` (for *bsd)
419#  4. Your process regex pattern = `\b$(service)\b`
420#  5. You call the init as `/etc/init.d/<script> <arg>` (for non-*bsd),
421#     or `/etc/rc.d/<script> <arg>` (for *bsd)
422#
423# b) If the 1st rule doesn't match, but rest does:
424#
425#   Use the `baseinit[$(service)]` array to point towards your
426#   init script's basename. For example:
427#
428# ```cf3
429#    "baseinit[www]" string => "httpd";
430# ```
431#
432#   This would fire up init script `/etc/init.d/httpd`, instead of
433#   the default `/etc/init.d/www`. From `/etc/rc.d/` if you're on *bsd system.
434#
435# c) If the 4th rule doesn't match, but rest does:
436#
437#   Use the `pattern[$(service)]` array to specify your own
438#   regex match. It's advisable to use conservative regex so
439#   there's less chance of getting a mismatch.
440#
441# ```cf3
442#    "pattern[www]" string => ".*httpd.*";
443# ```
444#
445#   Instead of matching the default '\bwww\b', this now matches
446#   your given string,
447#
448# d) 5th rule doesn't match:
449#
450#   If you can specify the init system used.
451#    Currently supported: `sysvinitd`, `sysvservice`, `systemd`
452#
453# ```cf3
454#     "init[www]" string => "sysvservice";
455#     "init[www]" string => "sysvinitd";
456#     "init[www]" string => "systemd";
457# ```
458#
459#   ^^ The above is not a valid syntax as you can only use one `init[]`
460#      per service, but it shows all the currently supported ones.
461#
462# ```cf3
463#     "sysvservice" == /(usr/)?sbin/service
464#     "sysvinitd"   == /etc/init.d/ (non-*bsd) | /etc/rc.d/ (*bsd)
465#     "systemd"     == /bin/systemctl
466# ```
467#
468# e) 2nd and 3rd rule matches, but rest doesn't:
469#
470#   Use a combination of the `pattern[]`, `baseinit[]` and `init[]`,
471#   to fill your need.
472#
473# ```cf3
474#     "baseinit[www]" string => "httpd";
475#     "pattern[www]"  string => ".*httpd.*";
476#     "init[www]"     string => "sysvservice";
477# ```
478#
479# f) As a fallback, if none of the above rules match, you can also
480#    define exactly what you need for each `$(state)`.
481#
482# ```cf3
483#    "startcommand[rhnsd]"   string => "/sbin/service rhnsd start";
484#    "restartcommand[rhnsd]" string => "/sbin/service rhnsd restart";
485#    "reloadcommand[rhnsd]"  string => "/sbin/service rhnsd reload";
486#    "stopcommand[rhnsd]"    string => "/sbin/service rhnsd stop";
487#    "pattern[rhnsd]"        string => "rhnsd";
488# ```
489#
490# If *any* of the `(re)?(start|load|stop)command` variables are set for
491# your service, they take _priority_ in case there's conflict of intent
492# with other data.
493#
494# Say you'd have the following service definition:
495#
496# ```cf3
497#    "startcommand[qwerty]"   string => "/sbin/service qwerty start";
498#    "stopcommand[qwerty]"    string => "/sbin/service qwerty stop";
499#    "pattern[qwerty]"        string => ".*qwerty.*";
500#    "baseinit[qwerty]"       string => "asdfgh"
501#    "init[qwerty]"           string => "systemd";
502# ```
503#
504# There's a conflict of intent now. As the `~command` definitions takes
505# priority, this kind of service config for `qwerty` would execute the
506# following commands:
507#
508# ```
509#   start:   "/sbin/service qwerty start"
510#   stop:    "/sbin/service qwerty stop"
511#   restart: "/bin/systemctl asdfgh restart"
512#   reload:  "/bin/systemctl asdfgh reload"
513# ```
514{
515  vars:
516      "all_states" slist => { "start", "restart", "reload", "stop", "disable" };
517
518      "inits" slist => { "sysvinitd", "sysvservice", "systemd", "chkconfig" },
519      comment => "Currently handled init systems";
520
521      "default[prefix][sysvservice]" string => "$(paths.service) ",
522      comment => "Command for sysv service interactions";
523
524      "default[prefix][systemd]" string => "$(paths.systemctl) ",
525      comment => "Command for systemd interactions";
526
527      "default[prefix][sysvinitd]" string => ifelse("openbsd", "/etc/rc.d/",
528                                                    "freebsd", "/etc/rc.d/",
529                                                    "netbsd", "/etc/rc.d/",
530                                                    "/etc/init.d/"),
531      comment => "Command prefix for sysv init script interactions";
532
533      "default[prefix][chkconfig]" string => "$(default[prefix][sysvinitd])",
534      comment => "Command prefix for chkconfig init script interactions";
535
536      "default[cmd][$(inits)]" string => "$(default[prefix][$(inits)])$(service) $(state)",
537      comment => "Default command to control the service";
538
539      "default[pattern]" string => "\b$(service)\b",
540      comment => "Set default pattern for proc matching";
541
542    _stdlib_path_exists_chkconfig::
543      "default[init]" string => "chkconfig",
544      comment => "Use chkconfig as the default init system if one isn't defined";
545
546    !_stdlib_path_exists_chkconfig::
547      "default[init]" string => "sysvinitd",
548      comment => "Use sysvinitd as the default init system if one isn't defined";
549
550    no_inits_set::
551      "init_system" string => "$(default[init])";
552
553    any::
554      "init_system" string => "$(init[$(service)])",
555      ifvarclass => "$(inits_set)";
556
557    start|restart|reload::
558      "chkconfig_mode" string => "on";
559
560    stop|disable::
561      "chkconfig_mode" string => "off";
562
563    any::
564      "stakeholders[cfengine3]" slist => { "cfengine_in" };
565      "stakeholders[acpid]" slist => { "cpu", "cpu0", "cpu1", "cpu2", "cpu3" };
566      "stakeholders[postfix]" slist => { "smtp_in" };
567      "stakeholders[sendmail]" slist => { "smtp_in" };
568      "stakeholders[www]" slist => { "www_in", "wwws_in", "www_alt_in" };
569      "stakeholders[ssh]" slist => { "ssh_in" };
570      "stakeholders[mysql]" slist => { "mysql_in" };
571      "stakeholders[nfs]" slist => { "nfsd_in" };
572      "stakeholders[syslog]" slist => { "syslog" };
573      "stakeholders[rsyslog]" slist => { "syslog" };
574      "stakeholders[tomcat5]" slist => { "www_alt_in" };
575      "stakeholders[tomcat6]" slist => { "www_alt_in" };
576
577    linux::
578
579      "pattern[acpid]"            string => ".*acpid.*";
580      "pattern[cfengine3]"        string => ".*cf-execd.*";
581      "pattern[fancontrol]"       string => ".*fancontrol.*";
582      "pattern[hddtemp]"          string => ".*hddtemp.*";
583      "pattern[irqbalance]"       string => ".*irqbalance.*";
584      "pattern[lm-sensor]"        string => ".*psensor.*";
585      "pattern[openvpn]"          string => ".*openvpn.*";
586      "pattern[postfix]"          string => ".*postfix.*";
587      "pattern[rsync]"            string => ".*rsync.*";
588      "pattern[rsyslog]"          string => ".*rsyslogd.*";
589      "pattern[sendmail]"         string => ".*sendmail.*";
590      "pattern[tomcat5]"          string => ".*tomcat5.*";
591      "pattern[tomcat6]"          string => ".*tomcat6.*";
592      "pattern[varnish]"          string => ".*varnish.*";
593      "pattern[wpa_supplicant]"   string => ".*wpa_supplicant.*";
594
595    suse|sles::
596
597      "baseinit[mysql]"           string => "mysqld";
598      "pattern[mysql]"            string => ".*mysqld.*";
599
600      "baseinit[www]"             string => "apache2";
601      "pattern[www]"              string => ".*apache2.*";
602
603      "baseinit[ssh]"             string => "sshd";
604      # filter out "sshd: ..." children
605      "pattern[ssh]"              string => ".*\Ssshd.*";
606
607      "pattern[ntpd]"             string => ".*ntpd.*";
608
609    redhat::
610
611      "pattern[anacron]"          string => ".*anacron.*";
612      "pattern[atd]"              string => ".*sbin/atd.*";
613      "pattern[auditd]"           string => ".*auditd$";
614      "pattern[autofs]"           string => ".*automount.*";
615      "pattern[capi]"             string => ".*capiinit.*";
616      "pattern[conman]"           string => ".*conmand.*";
617      "pattern[cpuspeed]"         string => ".*cpuspeed.*";
618      "pattern[crond]"            string => ".*crond.*";
619      "pattern[dc_client]"        string => ".*dc_client.*";
620      "pattern[dc_server]"        string => ".*dc_server.*";
621      "pattern[dnsmasq]"          string => ".*dnsmasq.*";
622      "pattern[dund]"             string => ".*dund.*";
623      "pattern[gpm]"              string => ".*gpm.*";
624      "pattern[haldaemon]"        string => ".*hald.*";
625      "pattern[hidd]"             string => ".*hidd.*";
626      "pattern[irda]"             string => ".*irattach.*";
627      "pattern[iscsid]"           string => ".*iscsid.*";
628      "pattern[isdn]"             string => ".*isdnlog.*";
629      "pattern[lvm2-monitor]"     string => ".*vgchange.*";
630      "pattern[mcstrans]"         string => ".*mcstransd.*";
631      "pattern[mdmonitor]"        string => ".*mdadm.*";
632      "pattern[mdmpd]"            string => ".*mdmpd.*";
633      "pattern[messagebus]"       string => ".*dbus-daemon.*";
634      "pattern[microcode_ctl]"    string => ".*microcode_ctl.*";
635      "pattern[multipathd]"       string => ".*multipathd.*";
636      "pattern[netplugd]"         string => ".*netplugd.*";
637      "pattern[NetworkManager]"   string => ".*NetworkManager.*";
638      "pattern[nfs]"              string => ".*nfsd.*";
639      "pattern[nfslock]"          string => ".*rpc.statd.*";
640      "pattern[nscd]"             string => ".*nscd.*";
641      "pattern[ntpd]"             string => ".*ntpd.*";
642      "pattern[oddjobd]"          string => ".*oddjobd.*";
643      "pattern[pand]"             string => ".*pand.*";
644      "pattern[pcscd]"            string => ".*pcscd.*";
645      "pattern[portmap]"          string => ".*portmap.*";
646      "pattern[postgresql]"       string => ".*postmaster.*";
647      "pattern[rdisc]"            string => ".*rdisc.*";
648      "pattern[readahead_early]"  string => ".*readahead.*early.*";
649      "pattern[readahead_later]"  string => ".*readahead.*later.*";
650      "pattern[restorecond]"      string => ".*restorecond.*";
651      "pattern[rpcgssd]"          string => ".*rpc.gssd.*";
652      "pattern[rpcidmapd]"        string => ".*rpc.idmapd.*";
653      "pattern[rpcsvcgssd]"       string => ".*rpc.svcgssd.*";
654      "pattern[saslauthd]"        string => ".*saslauthd.*";
655      "pattern[smartd]"           string => ".*smartd.*";
656      "pattern[svnserve]"         string => ".*svnserve.*";
657      "pattern[syslog]"           string => ".*syslogd.*";
658      "pattern[tcsd]"             string => ".*tcsd.*";
659      "pattern[xfs]"              string => ".*xfs.*";
660      "pattern[ypbind]"           string => ".*ypbind.*";
661      "pattern[yum-updatesd]"     string => ".*yum-updatesd.*";
662      "pattern[munin-node]"       string => ".*munin-node.*";
663
664      "baseinit[bluetoothd]"      string => "bluetooth";
665      "pattern[bluetoothd]"       string => ".*hcid.*";
666
667      "baseinit[mysql]"           string => "mysqld";
668      "pattern[mysql]"            string => ".*mysqld.*";
669
670      "baseinit[www]"             string => "httpd";
671      "pattern[www]"              string => ".*httpd.*";
672
673      "baseinit[ssh]"             string => "sshd";
674      # filter out "sshd: ..." children
675      "pattern[ssh]"              string => ".*\Ssshd.*";
676
677      "init[rhnsd]"               string => "sysvservice";
678      "pattern[rhnsd]"            string => "rhnsd";
679
680      "baseinit[snmpd]"           string => "snmpd";
681      "pattern[snmpd]"            string => "/usr/sbin/snmpd";
682
683    debian|ubuntu::
684
685      "pattern[atd]"              string => "atd.*";
686      "pattern[bluetoothd]"       string => ".*bluetoothd.*";
687      "pattern[bootlogd]"         string => ".*bootlogd.*";
688      "pattern[crond]"            string => ".*cron.*";
689      "pattern[kerneloops]"       string => ".*kerneloops.*";
690      "pattern[mysql]"            string => ".*mysqld.*";
691      "pattern[NetworkManager]"   string => ".*NetworkManager.*";
692      "pattern[ondemand]"         string => ".*ondemand.*";
693      "pattern[plymouth]"         string => ".*plymouthd.*";
694      "pattern[saned]"            string => ".*saned.*";
695      "pattern[udev]"             string => ".*udev.*";
696      "pattern[udevmonitor]"      string => ".*udevadm.*monitor.*";
697      "pattern[snmpd]"            string => "/usr/sbin/snmpd";
698      "pattern[pgbouncer]"        string => ".*pgbouncer.*";
699      "pattern[supervisor]"       string => ".*supervisord.*";
700      "pattern[munin-node]"       string => ".*munin-node.*";
701      "pattern[carbon-cache]"     string => ".*carbon-cache.*";
702      "pattern[cassandra]"        string => ".*jsvc\.exec.*apache-cassandra\.jar.*";
703      # filter out "sshd: ..." children
704      "pattern[ssh]"              string => ".*\Ssshd.*";
705
706      "baseinit[ntpd]"            string => "ntp";
707      "pattern[ntpd]"             string => ".*ntpd.*";
708
709      "baseinit[postgresql84]"    string => "postgresql-8.4";
710      "pattern[postgresql84]"     string => ".*postgresql.*";
711
712      "baseinit[postgresql91]"    string => "postgresql-9.1";
713      "pattern[postgresql91]"     string => ".*postgresql.*";
714
715      "baseinit[www]"             string => "apache2";
716      "pattern[www]"              string => ".*apache2.*";
717
718      "baseinit[nrpe]"            string => "nagios-nrpe-server";
719      "pattern[nrpe]"             string => ".*nrpe.*";
720
721      "baseinit[omsa-dataeng]"    string => "dataeng";
722      "pattern[omsa-dataeng]"     string => ".*dsm_sa_datamgr.*";
723
724      "baseinit[quagga]"          string => "quagga";
725      "pattern[quagga]"           string => "quagga/.*";
726
727    freebsd::
728
729      "pattern[ntpd]"       string => ".*ntpd.*";
730
731      "baseinit[ssh]"       string => "sshd";
732      "pattern[ssh]"        string => "/usr/sbin/sshd.*";
733
734      "baseinit[syslog]"    string => "syslogd";
735      "pattern[syslog]"     string => "/usr/sbin/syslogd.*";
736
737      "baseinit[crond]"     string => "cron";
738      "pattern[crond]"      string => "/usr/sbin/cron.*";
739
740      "baseinit[snmpd]"     string => "bsnmpd";
741      "pattern[snmpd]"      string => "/usr/sbin/bsnmpd.*";
742
743      "pattern[newsyslog]"  string => "/usr/sbin/newsyslog.*";
744
745  classes:
746      # Set classes for each possible state after $(all_states)
747      "$(all_states)" expression => strcmp($(all_states), $(state)),
748      comment => "Set a class named after the desired state";
749
750      "$(inits)_set" expression => strcmp("$(init[$(service)])","$(inits)"),
751      comment => "Check if init system is specified";
752      "no_inits_set" not => isvariable("init[$(service)]"),
753      comment => "Check if no init system is specified";
754
755      # define a class to tell us what init system we're using
756      "using_$(init_system)" expression => "any";
757
758  commands:
759    using_chkconfig::
760      "$(paths.chkconfig) $(service) $(chkconfig_mode)"
761      classes => kept_successful_command;
762
763  processes:
764
765    start::
766
767      "$(pattern[$(service)])" ->  { "@(stakeholders[$(service)])" }
768
769      comment => "Verify that the service appears in the process table",
770      restart_class => "start_$(service)",
771      ifvarclass => and(isvariable("pattern[$(service)]"));
772
773      "$(default[pattern])" ->  { "@(stakeholders[$(service)])" }
774
775      comment => "Verify that the service appears in the process table",
776      restart_class => "start_$(service)",
777      ifvarclass => not(isvariable("pattern[$(service)]"));
778
779    stop|disable::
780
781      "$(pattern[$(service)])" -> { "@(stakeholders[$(service)])" }
782
783      comment => "Verify that the service does not appear in the process",
784      process_stop => "$(stopcommand[$(service)])",
785      signals => { "term", "kill"},
786      ifvarclass => and(isvariable("stopcommand[$(service)]"),
787                        isvariable("pattern[$(service)]"));
788
789      "$(default[pattern])" -> { "@(stakeholders[$(service)])" }
790
791      comment => "Verify that the service does not appear in the process",
792      process_stop => "$(stopcommand[$(service)])",
793      signals => { "term", "kill"},
794      ifvarclass => and(isvariable("stopcommand[$(service)]"),
795                        not(isvariable("pattern[$(service)]")));
796
797      "$(pattern[$(service)])" -> { "@(stakeholders[$(service)])" }
798
799      comment => "Verify that the service does not appear in the process",
800      process_stop => "$(default[prefix][$(default[init])])$(baseinit[$(service)]) $(state)",
801      signals => { "term", "kill"},
802      ifvarclass => and(not(isvariable("stopcommand[$(service)]")),
803                        isvariable("baseinit[$(service)]"),
804                        isvariable("pattern[$(service)]"),
805                        "no_inits_set");
806
807      "$(pattern[$(service)])" -> { "@(stakeholders[$(service)])" }
808
809      comment => "Verify that the service does not appear in the process",
810      process_stop => "$(default[prefix][$(inits)])$(baseinit[$(service)]) $(state)",
811      signals => { "term", "kill"},
812      ifvarclass => and(not(isvariable("stopcommand[$(service)]")),
813                        isvariable("baseinit[$(service)]"),
814                        isvariable("pattern[$(service)]"),
815                        canonify("$(inits)_set"));
816
817##
818      "$(default[pattern])" -> { "@(stakeholders[$(service)])" }
819
820      comment => "Verify that the service does not appear in the process",
821      process_stop => "$(default[prefix][$(default[init])])$(baseinit[$(service)]) $(state)",
822      signals => { "term", "kill"},
823      ifvarclass => and(not(isvariable("stopcommand[$(service)]")),
824                        isvariable("baseinit[$(service)]"),
825                        not(isvariable("pattern[$(service)]")),
826                        "no_inits_set");
827
828      "$(default[pattern])" -> { "@(stakeholders[$(service)])" }
829
830      comment => "Verify that the service does not appear in the process",
831      process_stop => "$(default[prefix][$(inits)])$(baseinit[$(service)]) $(state)",
832      signals => { "term", "kill"},
833      ifvarclass => and(not(isvariable("stopcommand[$(service)]")),
834                        isvariable("baseinit[$(service)]"),
835                        not(isvariable("pattern[$(service)]")),
836                        canonify("$(inits)_set"));
837
838##
839      "$(pattern[$(service)])" -> { "@(stakeholders[$(service)])" }
840
841      comment => "Verify that the service does not appear in the process",
842      process_stop => "$(default[cmd][$(default[init])])",
843      signals => { "term", "kill"},
844      ifvarclass => and(not(isvariable("stopcommand[$(service)]")),
845                        not(isvariable("baseinit[$(service)]")),
846                        isvariable("pattern[$(service)]"),
847                        "no_inits_set");
848
849      "$(pattern[$(service)])" -> { "@(stakeholders[$(service)])" }
850
851      comment => "Verify that the service does not appear in the process",
852      process_stop => "$(default[cmd][$(inits)])",
853      signals => { "term", "kill"},
854      ifvarclass => and(not(isvariable("stopcommand[$(service)]")),
855                        not(isvariable("baseinit[$(service)]")),
856                        isvariable("pattern[$(service)]"),
857                        canonify("$(inits)_set"));
858
859##
860      "$(default[pattern])" -> { "@(stakeholders[$(service)])" }
861
862      comment => "Verify that the service does not appear in the process",
863      process_stop => "$(default[cmd][$(default[init])])",
864      signals => { "term", "kill"},
865      ifvarclass => and(not(isvariable("stopcommand[$(service)]")),
866                        not(isvariable("baseinit[$(service)]")),
867                        not(isvariable("pattern[$(service)]")),
868                        "no_inits_set");
869
870      "$(default[pattern])" -> { "@(stakeholders[$(service)])" }
871
872      comment => "Verify that the service does not appear in the process",
873      process_stop => "$(default[cmd][$(inits)])",
874      signals => { "term", "kill"},
875      ifvarclass => and(not(isvariable("stopcommand[$(service)]")),
876                        not(isvariable("baseinit[$(service)]")),
877                        not(isvariable("pattern[$(service)]")),
878                        canonify("$(inits)_set"));
879
880  commands:
881
882      "$(startcommand[$(service)])" -> { "@(stakeholders[$(service)])" }
883      comment => "Execute command to start the $(service) service",
884      classes => kept_successful_command,
885      ifvarclass => and(isvariable("startcommand[$(service)]"),
886                        canonify("start_$(service)"));
887##
888      "$(default[prefix][$(default[init])])$(baseinit[$(service)]) $(state)" -> { "@(stakeholders[$(service)])" }
889      comment => "Execute (baseinit init) command to start the $(service) service",
890      classes => kept_successful_command,
891      ifvarclass => and(not(isvariable("startcommand[$(service)]")),
892                        isvariable("baseinit[$(service)]"),
893                        canonify("start_$(service)"),
894                        "no_inits_set");
895
896      "$(default[prefix][$(inits)])$(baseinit[$(service)]) $(state)" -> { "@(stakeholders[$(service)])" }
897      comment => "Execute (baseinit init) command to start the $(service) service",
898      classes => kept_successful_command,
899      ifvarclass => and(not(isvariable("startcommand[$(service)]")),
900                        isvariable("baseinit[$(service)]"),
901                        canonify("start_$(service)"),
902                        canonify("$(inits)_set"));
903##
904      "$(default[cmd][$(default[init])])" -> { "@(stakeholders[$(service)])" }
905      comment => "Execute (default) command to start the $(service) service",
906      classes => kept_successful_command,
907      ifvarclass => and(not(isvariable("startcommand[$(service)]")),
908                        not(isvariable("baseinit[$(service)]")),
909                        canonify("start_$(service)"),
910                        "no_inits_set");
911
912      "$(default[cmd][$(inits)])" -> { "@(stakeholders[$(service)])" }
913      comment => "Execute (default) command to start the $(service) service",
914      classes => kept_successful_command,
915      ifvarclass => and(not(isvariable("startcommand[$(service)]")),
916                        not(isvariable("baseinit[$(service)]")),
917                        canonify("start_$(service)"),
918                        canonify("$(inits)_set"));
919
920    restart::
921      "$(restartcommand[$(service)])" -> { "@(stakeholders[$(service)])" }
922      comment => "Execute command to restart the $(service) service",
923      classes => kept_successful_command,
924      ifvarclass => and(isvariable("restartcommand[$(service)]"));
925##
926
927      "$(default[prefix][$(default[init])])$(baseinit[$(service)]) $(state)" -> { "@(stakeholders[$(service)])" }
928      comment => "Execute (baseinit init) command to restart the $(service) service",
929      classes => kept_successful_command,
930      ifvarclass => and(not(isvariable("restartcommand[$(service)]")),
931                        isvariable("baseinit[$(service)]"),
932                        "no_inits_set");
933
934      "$(default[prefix][$(inits)])$(baseinit[$(service)]) $(state)" -> { "@(stakeholders[$(service)])" }
935      comment => "Execute (baseinit init) command to restart the $(service) service",
936      classes => kept_successful_command,
937      ifvarclass => and(not(isvariable("restartcommand[$(service)]")),
938                        isvariable("baseinit[$(service)]"),
939                        canonify("$(inits)_set"));
940##
941      "$(default[cmd][$(default[init])])" -> { "@(stakeholders[$(service)])" }
942      comment => "Execute (default) command to restart the $(service) service",
943      classes => kept_successful_command,
944      ifvarclass => and(not(isvariable("restartcommand[$(service)]")),
945                        not(isvariable("baseinit[$(service)]")),
946                        "no_inits_set");
947
948      "$(default[cmd][$(inits)])" -> { "@(stakeholders[$(service)])" }
949      comment => "Execute (default) command to restart the $(service) service",
950      classes => kept_successful_command,
951      ifvarclass => and(not(isvariable("restartcommand[$(service)]")),
952                        not(isvariable("baseinit[$(service)]")),
953                        canonify("$(inits)_set"));
954
955    reload::
956      "$(reloadcommand[$(service)])" -> { "@(stakeholders[$(service)])" }
957      comment => "Execute command to reload the $(service) service",
958      classes => kept_successful_command,
959      ifvarclass => and(isvariable("reloadcommand[$(service)]"));
960##
961      "$(default[prefix][$(default[init])])$(baseinit[$(service)]) $(state)" -> { "@(stakeholders[$(service)])" }
962      comment => "Execute (baseinit init) command to reload the $(service) service",
963      classes => kept_successful_command,
964      ifvarclass => and(not(isvariable("reloadcommand[$(service)]")),
965                        isvariable("baseinit[$(service)]"),
966                        "no_inits_set");
967
968      "$(default[prefix][$(inits)])$(baseinit[$(service)]) $(state)" -> { "@(stakeholders[$(service)])" }
969      comment => "Execute (baseinit init) command to reload the $(service) service",
970      classes => kept_successful_command,
971      ifvarclass => and(not(isvariable("reloadcommand[$(service)]")),
972                        isvariable("baseinit[$(service)]"),
973                        canonify("$(inits)_set"));
974##
975      "$(default[cmd][$(default[init])])" -> { "@(stakeholders[$(service)])" }
976      comment => "Execute (default) command to reload the $(service) service",
977      classes => kept_successful_command,
978      ifvarclass => and(not(isvariable("reloadcommand[$(service)]")),
979                        not(isvariable("baseinit[$(service)]")),
980                        "no_inits_set");
981
982      "$(default[cmd][$(inits)])" -> { "@(stakeholders[$(service)])" }
983      comment => "Execute (default) command to reload the $(service) service",
984      classes => kept_successful_command,
985      ifvarclass => and(not(isvariable("reloadcommand[$(service)]")),
986                        not(isvariable("baseinit[$(service)]")),
987                        canonify("$(inits)_set"));
988
989  reports:
990    "DEBUG|DEBUG_$(this.bundle)"::
991      "DEBUG $(this.bundle): Using init system $(inits)"
992      ifvarclass => and(canonify("$(inits)_set"));
993
994      "DEBUG $(this.bundle): No init system is set, using $(default[init])"
995      ifvarclass => "no_inits_set";
996
997      "DEBUG $(this.bundle): The service $(service) needs to be started"
998      ifvarclass => and(canonify("start_$(service)"));
999
1000      "DEBUG $(this.bundle): The service pattern is provided: $(pattern[$(service)])"
1001      ifvarclass => and(isvariable("pattern[$(service)]"));
1002
1003      "DEBUG $(this.bundle): The default service pattern was used: $(default[pattern])"
1004      ifvarclass => not(isvariable("pattern[$(service)]"));
1005
1006      "DEBUG $(this.bundle): The stopcommand is provided: $(stopcommand[$(service)])"
1007      ifvarclass => and(isvariable("stopcommand[$(service)]"));
1008
1009      "DEBUG $(this.bundle): The stopcommand is NOT provided, using default"
1010      ifvarclass => not(isvariable("stopcommand[$(service)]"));
1011
1012      "DEBUG $(this.bundle): The startcommand is provided: $(startcommand[$(service)])"
1013      ifvarclass => and(isvariable("startcommand[$(service)]"));
1014
1015      "DEBUG $(this.bundle): The startcommand is NOT provided, using default"
1016      ifvarclass => not(isvariable("startcommand[$(service)]"));
1017
1018      "DEBUG $(this.bundle): The restartcommand is provided: $(restartcommand[$(service)])"
1019      ifvarclass => and(isvariable("restartcommand[$(service)]"));
1020
1021      "DEBUG $(this.bundle): The restartcommand is NOT provided, using default"
1022      ifvarclass => not(isvariable("restartcommand[$(service)]"));
1023
1024      "DEBUG $(this.bundle): The reloadcommand is provided: $(reloadcommand[$(service)])"
1025      ifvarclass => and(isvariable("reloadcommand[$(service)]"));
1026
1027      "DEBUG $(this.bundle): The reloadcommand is NOT provided, using default"
1028      ifvarclass => not(isvariable("reloadcommand[$(service)]"));
1029
1030      "DEBUG $(this.bundle): The baseinit is provided: $(baseinit[$(service)])"
1031      ifvarclass => and(isvariable("baseinit[$(service)]"));
1032
1033      "DEBUG $(this.bundle): The baseinit is NOT provided, using default"
1034      ifvarclass => not(isvariable("baseinit[$(service)]"));
1035}
1036