Part 3 - Systemd Integration and Administration

44 views
Skip to first unread message

Mike Svoboda

unread,
Mar 10, 2016, 3:27:27 PM3/10/16
to help-cfengine
Part 3: Source codesystemd_administration.cf
[root@lva1-cfe-guppy04 msvoboda]# cat
/var/cfengine/sequences/policies/systemd_administration.cf
body file control {
inputs => { @(systemd_administration.input_files) };
}

bundle agent systemd_administration {
meta:
# sysops_only = only production servers should execute this top level
bundle
# all = sysops, GRID, NETOPS, GTS, etc. can import this sequence and
execute it
"tags" slist => { "sysops" };

vars:
any::
"input_files" slist => {};

# This is the filters class which will activate this top level policy.
If the system does not
# match the filter class below, nothing else will process.
filters:execute_systemd_administration::
"policy_name" string => "$(this.bundle)";
"rootdir" string => "$(sequences.policies_root)/$(policy_name)";
"bundle_root" string => "$(rootdir)/bundles";
"data_root" string => "$(rootdir)/data";
"file_root" string => "$(rootdir)/files";
"template_root" string => "$(rootdir)/templates";
"module_root" string => "$(rootdir)/modules";
"executable_bundles" slist => {
"$(policy_name)_probe_all_services",
"$(policy_name)_rhel7_services",
"$(policy_name)_discover_deployables",
};
"executable_files" slist => maplist("$(bundle_root)/$(this).cf",
"@(executable_bundles)");
"input_only_bundles" slist => {
"$(policy_name)_discover_current_state",
"$(policy_name)_standard_services",
"$(policy_name)_unit",
"$(policy_name)_adjust_service_state",
"$(policy_name)_enforce_standards",
};
"input_only_files" slist => maplist("$(bundle_root)/$(this).cf",
"@(input_only_bundles)");
"input_files" slist => { "@(executable_files)", "@(input_only_files)"
};

classes:
any::
"executable_bundles_populated" expression => reglist(
"@(executable_bundles)", ".+");

files:
any::
"$(module_root)"
comment => "validate $(policy_name) modules are execuable",
perms => mog("0700", "root", "root"),
depth_search => recurse("inf"),
file_select => plain;

methods:
executable_bundles_populated::
"execute" usebundle => $(executable_bundles);

reports:
executable_bundles_populated.list_bundles::
"$(global.execution_report) $(policy_name) Executable bundle:
$(executable_files)";

input_only_bundles_populated.list_bundles::
"$(global.execution_report) $(policy_name) Data import bundle:
$(input_only_files)";


(executable_bundles_populated|input_only_bundles_populated).list_bundles::
"$(global.execution_report) Sequences active. Executing top level
policy: $(systemd_administration.policy_name)";
}


systemd_administration_probe_all_services.cf
[root@lva1-cfe-guppy04 msvoboda]# cat
/var/cfengine/sequences/policies/systemd_administration/bundles/systemd_administration_probe_all_services.cf
bundle agent systemd_administration_probe_all_services {
methods:
systemd::
"probe_all_services" usebundle =>
systemd_administration_discover_current_state("");
}


systemd_administration_rhel7_services.cf
[root@lva1-cfe-guppy04 msvoboda]# cat
/var/cfengine/sequences/policies/systemd_administration/bundles/systemd_administration_rhel7_services.cf
bundle agent systemd_administration_rhel7_services {
vars:
systemd::
"unmanaged_rhel7_services" slist => {
"abrt-vmcore.service",
"psacct.service",
"blk-availability.service",
"brandbot.service",
"dbus.service",
"lvm2-lvmetad.service",
"lvm2-monitor.service",
"lvm2-pvscan@.service",
"lvm2-lvmpolld.service",
"multipathd.service",
"ldconfig.service",
"microcode.service",
"named.service",
"nfs-config.service",
"nfs-idmapd.service",
"nfs-mountd.service",
"nfs-server.service",
"nfs-utils.service",
"nfs-lock.service",
"nfslock.service",
"nfs-secure-server.service",
"nfs-secure.service",
"nfs-server.service",
"nfs.service",
"nfs-utils.service",
"rpc-statd-notify.service",
"rpc-statd.service",
"rpc-svcgssd.service",
"rsyncd.service",
"sshd-keygen.service",
};

systemd::
"start_rhel7_services" slist => {
"abrt-ccpp.service",
"abrtd.service",
"abrt-oops.service",
"auditd.service",
"autofs.service",
"cfe_bootstrap.service",
"cfengine3.service",
"cgconfig.service",
"cgred.service",
"cpupower.service",
"crond.service",
"dm-event.service",
"getty@.service",
"ge...@tty1.service",
"gssproxy.service",
"irqbalance.service",
"ipmievd.service",
"ipmi.service",
"kdump.service",
"messagebus.service",
"mdmonitor.service",
"mdmon@.service",
"mdadm-last-resort@.service",
"network.service",
"ntpd.service",
"postfix.service",
"rngd.service",
"rpcbind.service",
"rpc-gssd.service",
"rsyslog.service",
"serial...@ttyS0.service",
"smartd.service",
"sshd.service",
"sysstat.service",
};
systemd::
"stop_rhel7_services" slist => {
"abrt-xorg.service",
"arp-ethers.service",
"atd.service",
"autovt@.service",
"chronyd.service",
"chrony-dnssrv@.service",
"chrony-wait.service",
"console-getty.service",
"console-shell.service",
"container-getty@.service",
"dmraid-activation.service",

"dbus-org.freedesktop.hostname1.service",
"dbus-org.freedesktop.locale1.service",
"dbus-org.freedesktop.login1.service",
"dbus-org.freedesktop.machine1.service"
,
"dbus-org.freedesktop.network1.service"
,

"dbus-org.freedesktop.timedate1.service",
"dnsmasq.service",
"ebtables.service",
"firewalld.service",
"fprintd.service",
"iprdump.service",
"iprinit.service",
"iprupdate.service",
"kmod-static-nodes.service",
"libstoragemgmt.service",
"NetworkManager.service",
"NetworkManager-wait-online.service",
"ntpdate.service",
"plymouth-quit.service",
"plymouth-quit-wait.service",
"plymouth-read-write.service",
"plymouth-start.service",
"polkit.service",
"quotaon.service",
"rdisc.service",
"rhnsd.service",
"rhsmcertd.service",
"snmpd.service",
"snmptrapd.service",
"tcsd.service",
"tmp.mount",
"tuned.service",
"wpa_supplicant.service",
};

services:
systemd::
"$(start_rhel7_services)"
service_policy => "start",
service_method => systemd_method;

"$(stop_rhel7_services)"
service_policy => "stop",
service_method => systemd_method;
}


systemd_administration_discover_deployables.cf
[root@lva1-cfe-guppy04 msvoboda]# cat
/var/cfengine/sequences/policies/systemd_administration/bundles/systemd_administration_discover_deployables.cf
bundle agent systemd_administration_discover_deployables
{
vars:
systemd::
"systemd_json_deployment_directory" string =>
"/etc/cfe.d/systemd_service_deployments";
"systemd_user_deployments" slist => {"root", "app", "mysql", "oracle"
, "couchbase", "slideshare"};
"systemd_user_deployment_directory[$(systemd_user_deployments)]" string
=> "$(systemd_json_deployment_directory)/$(systemd_user_deployments)";
"systemd_user_json_containers[$(systemd_user_deployments)]" slist =>
findfiles(
"$(systemd_user_deployment_directory[$(systemd_user_deployments)])/*.json");

classes:
systemd::
"systemd_user_$(systemd_user_deployments)_containers_discovered" expression
=> reglist("@(systemd_user_json_containers[$(systemd_user_deployments)])",
".+");
"systemd_user_$(systemd_user_deployments)_exists" expression =>
userexists("$(systemd_user_deployments)");

files:
systemd::
"$(systemd_json_deployment_directory)/."
comment => "create the cfengine / systemd deployment root directory"
,
create => "true",
perms => mog("0755", "root", "root");

systemd::
"$(systemd_user_deployment_directory[$(systemd_user_deployments)])/."
comment => "create the per-user systemd deployment directories",
create => "true",
perms => mog("0755", "$(systemd_user_deployments)",
"$(systemd_user_deployments)"),
ifvarclass => canonify(
"systemd_user_$(systemd_user_deployments)_exists");

methods:
systemd::
"deploy_systemd_service" usebundle => systemd_administration_unit(
"$(systemd_user_json_containers[$(systemd_user_deployments)])"),
ifvarclass => canonify(
"systemd_user_$(systemd_user_deployments)_containers_discovered");

reports:
systemd.debug_systemd_state::
"$(global.execution_report) We discovered JSON container
$(systemd_user_json_containers[$(systemd_user_deployments)]). Entering
systemd_administration_unit.cf"
ifvarclass => canonify(
"systemd_user_$(systemd_user_deployments)_containers_discovered");
}
systemd_administration_discover_current_state.cf
[root@lva1-cfe-guppy04 msvoboda]# cat
/var/cfengine/sequences/policies/systemd_administration/bundles/systemd_administration_discover_current_state.cf
bundle agent systemd_administration_discover_current_state(service) {
vars:
any::
"cfengine_systemd_root" string => "/etc/cfe.d/systemd_state";

# All of the following array data is calculated via the python utility
below.
systemd_state_probed::
"systemd_all" slist => getindices("systemd_service_status.systemd_all"
);

systemd_all_defined::
"systemd_service_recovery[$(systemd_all)]"
string =>
"$(systemd_service_status.systemd_service_recovery[$(systemd_all)])";
"systemd_service_shutdown[$(systemd_all)]"
string =>
"$(systemd_service_status.systemd_service_shutdown[$(systemd_all)])";
"systemd_unit_file_state[$(systemd_all)]"
string =>
"$(systemd_service_status.systemd_unit_file_state[$(systemd_all)])";
"systemd_load_state[$(systemd_all)]"
string =>
"$(systemd_service_status.systemd_load_state[$(systemd_all)])";
"systemd_active_state[$(systemd_all)]"
string =>
"$(systemd_service_status.systemd_active_state[$(systemd_all)])";
"systemd_can_stop[$(systemd_all)]"
string =>
"$(systemd_service_status.systemd_can_stop[$(systemd_all)])";
"systemd_can_start[$(systemd_all)]"
string =>
"$(systemd_service_status.systemd_can_start[$(systemd_all)])";
"systemd_can_reload[$(systemd_all)]"
string =>
"$(systemd_service_status.systemd_can_reload[$(systemd_all)])";

# dump all systemd classes for debugging so we can see what cfengine
was doing
"all_services_all_classes" slist => classesmatching(
"systemd_administration.*");
"all_services_all_classes_sorted" slist => sort(
"all_services_all_classes", "lex");

classes:
systemd.agent::
"in_policy" expression => "any";
"service_defined" expression => regcmp(".+", "$(service)");
"systemd_all_defined" expression => reglist("@(systemd_all)", ".+");
"systemd_debug_classes_defined" expression => reglist(
"@(all_services_all_classes_sorted)",
".+");

systemd_all_defined::
"systemd_administration_$(systemd_all)_service_recovery_defined"
expression => regcmp(".+",
"$(systemd_service_recovery[$(systemd_all)])");
"systemd_administration_$(systemd_all)_service_shutdown_defined"
expression => regcmp(".+",
"$(systemd_service_shutdown[$(systemd_all)])");
"systemd_administration_$(systemd_all)_unit_file_state_defined"
expression => regcmp(".+",
"$(systemd_unit_file_state[$(systemd_all)])");
"systemd_administration_$(systemd_all)_active_state_defined"
expression => regcmp(".+", "$(systemd_active_state[$(systemd_all)])"
);
"systemd_administration_$(systemd_all)_can_stop_defined"
expression => regcmp(".+", "$(systemd_can_stop[$(systemd_all)])");
"systemd_administration_$(systemd_all)_can_start_defined"
expression => regcmp(".+", "$(systemd_can_start[$(systemd_all)])");
"systemd_administration_$(systemd_all)_can_reload_defined"
expression => regcmp(".+", "$(systemd_can_reload[$(systemd_all)])");
"systemd_administration_$(systemd_all)_load_state_defined"
expression => regcmp(".+", "$(systemd_load_state[$(systemd_all)])");

# This namespace class is used to determine if we need to reprobe the
service.
"systemd_administration_$(systemd_all)_service_probed"
expression => "any",
scope => "namespace";

files:
any::
"$(cfengine_systemd_root)/."
comment => "create cfengine systemd root",
create => "true",
perms => mog("0755", "root", "root"),
classes => if_repaired("cfengine_systemd_root_modified");

systemd_debug_classes_defined::

"$(cfengine_systemd_root)/cfengine_classes_from_all_systemd_services.txt"
edit_defaults => empty,
create => "true",
perms => mog("0644", "root", "root"),
edit_line => append_if_no_line("@(all_services_all_classes_sorted)"
);

commands:
in_policy.!service_defined::
"$(systemd_administration.module_root)/systemd_service_status
--probe-all"
module => "true",
contain => no_shell_no_output,
classes => if_ok("systemd_state_probed");

in_policy.service_defined::
"$(systemd_administration.module_root)/systemd_service_status
--service $(service)"
module => "true",
contain => no_shell_no_output,
classes => if_ok("systemd_state_probed");

reports:
any::
"$(global.execution_report) SYSTEMD RECOVER SERVICE: $(systemd_all)
STATE IS: $(systemd_service_recovery[$(systemd_all)])"
ifvarclass => canonify("$(systemd_all)_service_recovery_defined");

"$(global.execution_report) SYSTEMD SHUTDOWN SERVICE: $(systemd_all)
STATE IS: $(systemd_service_shutdown[$(systemd_all)])"
ifvarclass => canonify("$(systemd_all)_service_shutdown_defined");

dump_systemd_state::
"$(global.execution_report) systemd_all: $(systemd_all)
systemd_unit_file_state: $(systemd_unit_file_state[$(systemd_all)])"
ifvarclass => canonify("$(systemd_all)_unit_file_state_defined");

"$(global.execution_report) systemd_all: $(systemd_all)
systemd_active_state: $(systemd_active_state[$(systemd_all)])"
ifvarclass => canonify("$(systemd_all)_active_state_defined");

"$(global.execution_report) systemd_all: $(systemd_all)
systemd_can_stop: $(systemd_can_stop[$(systemd_all)])"
ifvarclass => canonify("$(systemd_all)_can_stop_defined");

"$(global.execution_report) systemd_all: $(systemd_all)
systemd_can_start: $(systemd_can_start[$(systemd_all)])"
ifvarclass => canonify("$(systemd_all)_can_start_defined");

"$(global.execution_report) systemd_all: $(systemd_all)
systemd_can_reload: $(systemd_can_reload[$(systemd_all)])"
ifvarclass => canonify("$(systemd_all)_can_reload_defined");

"$(global.execution_report) systemd_all: $(systemd_all)
systemd_load_state: $(systemd_load_state[$(systemd_all)])"
ifvarclass => canonify("$(systemd_all)_load_state_defined");

cfengine_systemd_root_modified::
"$(global.execution_report) /etc/cfe.d/systemd_state was modified on
$(sys.host)";

list_bundles::
"$(global.execution_report) Sequences active. Executing top level
policy: $(systemd_administration.policy_name)";
"$(global.execution_report) Execution of bundle:
$(systemd_administration.bundle_root)/$(this.bundle).cf";
}

body contain no_shell_no_output {
no_output => true;
exec_owner => "root";
exec_group => "root";
useshell => false;
}


systemd_service_status.py
[root@lva1-cfe-guppy04 msvoboda]# cat
/var/cfengine/sequences/policies/systemd_administration/modules/systemd_service_status
#!/usr/bin/python

import subprocess
import json
import argparse
import sys
import os
import shutil
import tempfile
import time
import re

class MissingAtomicWriterRequiredData(Exception):
pass

class InstalledSystemdService(object):
def __init__(self, name='systemd_environment', outputdir = None):
self._workdir = outputdir
self._update_time = None
self._service_name = name
self._service_name_canonified = None
self._filename = "{0}.json".format(os.path.join(self._workdir,
self._service_name))
self._requiring_recovery = False
self._requiring_shutdown = False
self._service_information = {}
self._systemd_show_cmd = ['/usr/bin/systemctl', '--no-ask-password'
, '--global', '--system', '--all', 'show' ]

if self._filename is None or self._workdir is None:
raise MissingAtomicWriterRequiredData("We were missing either
the working directory {0} or filename {1}. Can not write data to disk,
aborting execution".format(self._workdir, self._filename))

@property
def name(self):
return self._service_name

def update_state_on_disk(self):
self._update_time = time.time()
temp_fh, temp_filename = tempfile.mkstemp(dir=self._workdir)
source_filename = os.path.join(self._workdir, temp_filename)
fh = os.fdopen(temp_fh, 'w')
json.dump(self.__dict__, fh, sort_keys=True, indent=3)
shutil.move(source_filename, self._filename)

def __repr__(self):
return json.dumps(self.__dict__, sort_keys=True, indent=3)

def populate(self):
if not self._service_name == 'systemd_environment':
self._systemd_show_cmd.append(self._service_name)
output,_ = subprocess.Popen(self._systemd_show_cmd, shell=False,
stdout=subprocess.PIPE).communicate()
for line in output.splitlines():
(key, value) = line.split('=', 1)
self._service_information[key] = value

@property
def unit_state(self):
return self._service_information['UnitFileState']

@property
def active_state(self):
return self._service_information['ActiveState']

def validate_service_state(self):
if self._service_name != 'systemd_environment':
if self._service_information['ActiveState'] == 'inactive' and
self._service_information['UnitFileState'] == 'enabled':
self._requiring_recovery = True
if self._service_information['ActiveState'] == 'active' and
self._service_information['UnitFileState'] == 'disabled':
self._requiring_shutdown = True

def raise_cfengine_variables(self):
canonified_regex = re.compile('[^a-zA-Z0-9_]')
self._service_name_canonified = canonified_regex.sub('_',
self._service_name)
print "=systemd_all[{0}]={1}".format(self._service_name_canonified,
self._service_name_canonified)

if self._requiring_recovery:
print "=systemd_service_recovery[{0}]={1}".format(self._service_name_canonified,
self._service_information['ActiveState'])

if self._requiring_shutdown:
print "=systemd_service_shutdown[{0}]={1}".format(self._service_name_canonified,
self._service_information['ActiveState'])

if self._service_information['UnitFileState']:
print "=systemd_unit_file_state[{0}]={1}".format(self._service_name_canonified,
self._service_information['UnitFileState'])

if self._service_information['LoadState']:
print '=systemd_load_state[{0}]={1}'.format(self._service_name_canonified,
self._service_information['LoadState'])

if self._service_information['ActiveState']:
print '=systemd_active_state[{0}]={1}'.format(self._service_name_canonified,
self._service_information['ActiveState'])

if self._service_information['LoadState']:
print '=systemd_load_state[{0}]={1}'.format(self._service_name_canonified,
self._service_information['LoadState'])

if self._service_information['CanStop']:
print '=systemd_can_stop[{0}]={1}'.format(self._service_name_canonified,
self._service_information['CanStop'])

if self._service_information['CanStart']:
print '=systemd_can_start[{0}]={1}'.format(self._service_name_canonified,
self._service_information['CanStart'])

if self._service_information['CanReload']:
print '=systemd_can_reload[{0}]={1}'.format(self._service_name_canonified,
self._service_information['CanReload'])

def parse_all_installed_unit_files():
parsed_unit_files = []
output,_ = subprocess.Popen(['/usr/bin/systemctl', '--no-ask-password',
'--global', '--system', 'list-unit-files', '--type=service', '--all'],
shell=False, stdout=subprocess.PIPE).communicate()
# remove empty lines and strip whitespace
output = [ line.strip() for line in output.splitlines() if line ]
for line in output:
if 'service' not in line:
continue
# if the service name contains @.service, strip the @ so we can
refer to it via systemctl
service_name = line.split()[0].replace('@.service', '.service')
parsed_unit_files.append(service_name)
return parsed_unit_files

def main():
parser = argparse.ArgumentParser()
parser.add_argument("--verbose", action="store_true", dest='verbose',
default=False, help="Display shit for debugging")
parser.add_argument("--probe-all", action="store_true", dest='probe_all'
, default=False, help="Probe all discovered systemd services and dump JSON
objects into /etc/cfe.d/systemd_state")
parser.add_argument("--service", action="store", dest='service', default=None,
help='Update systemd state on disk for a single service')

args = parser.parse_args()

if not args.probe_all and not args.service:
parser.print_help()
sys.exit(1)

output_dir = '/etc/cfe.d/systemd_state'
unit_files = []

if args.service:
unit_files.append(args.service)

if args.probe_all:
unit_files = parse_all_installed_unit_files()

for service_name in unit_files:
installed_service = InstalledSystemdService(name = service_name,
outputdir = output_dir)
installed_service.populate()
installed_service.validate_service_state()
installed_service.raise_cfengine_variables()
installed_service.update_state_on_disk()
systemd_environment = InstalledSystemdService(outputdir = output_dir)
systemd_environment.update_state_on_disk()

if __name__ == '__main__':
main()


systemd_administration_standard_services.cf
[root@lva1-cfe-guppy04 msvoboda]# cat
/var/cfengine/sequences/policies/systemd_administration/bundles/systemd_administration_standard_services.cf
bundle agent systemd_administration_standard_services(service, state) {
methods:
# we probe all loaded services in
systemd_administration_probe_all_services. we raise a class for each
service that we probe, saying that we've generated the json data for that
service.
# this namespace class is raised there. it allows us to not hit the
python utility a million times for every service. we probe all services at
the beginning of execution once, and then
# any new services that are being installed which haven't been probed
yet.
systemd::
"probe_service"
usebundle => systemd_administration_discover_current_state(
"$(service)"),
handle => "service_probed",
ifvarclass =>
unless(canonify(
"systemd_administration_$(canonified_service)_service_probed"));

systemd::
"correct_service"
usebundle => systemd_administration_adjust_service_state(
"$(service)", "$(state)"),
handle => "service_adjusted";
}


systemd_administration_unit.cf
[root@lva1-cfe-guppy04 msvoboda]# cat
/var/cfengine/sequences/policies/systemd_administration/bundles/systemd_administration_unit.cf

bundle agent systemd_administration_unit(service_json_file)
{
vars:
systemd::
"template_root" string => "/etc/cfe.d/systemd_unit_templates";
"unit_data" data => mergedata(
"systemd_administration_enforce_standards.unit_data");
"canonified_json_filename" string =>
"$(systemd_administration_enforce_standards.canonified_json_filename)";

classes:
systemd::
"service_administration_active" expression => regcmp(".+",
"$(unit_data[name])"),
ifvarclass => not(canonify(
"abort_unit_file_$(canonified_json_filename)"));

files:
systemd::
"$(template_root)/."
comment => "baseline directory used for template expansion",
create => "true",
perms => mog("0755", "root", "root");

service_administration_active::
"$(template_root)/$(unit_data[name])"
comment => "expand systemd template from passed in JSON data",
create => "true",
perms => mog("0644", "root", "root"),
edit_template =>
"$(systemd_administration.template_root)/unit-template.service";

service_administration_active::
"/etc/systemd/system/$(unit_data[name])"
comment => "install expanded template file into systemd production
directory",
create => "true",
perms => mog("0644", "root", "root"),
copy_from => no_backup_cp("$(template_root)/$(unit_data[name])"),
classes => if_repaired("modified_$(unit_data[name])");

services:
service_administration_active::
"$(unit_data[name])"
service_policy => "$(unit_data[state])",
comment => "enforce the systemd service to be online / offline /
etc",
service_method => systemd_method;

methods:
"enforce_service_unit_standards" usebundle =>
systemd_administration_enforce_standards("$(service_json_file)");

commands:
service_administration_active::
"/usr/bin/systemctl daemon-reload"
comment => "bounce systemd daemon if service was modified",
ifvarclass => canonify("modified_$(unit_data[name])");

reports:
systemd::
"$(global.execution_report) Skipping processing of
$(service_json_file) as it did not meet our requirements for mandatory data
needed to deploy the service"
ifvarclass => canonify("abort_unit_file_$(canonified_json_filename)"
);

service_administration_active::
"$(global.execution_report) Reloading systemd daemons"
ifvarclass => canonify("modified_$(unit_data[name])");
}


unit-template.service
[root@lva1-cfe-guppy04 msvoboda]# cat
/var/cfengine/sequences/policies/systemd_administration/templates/unit-template.service
# This file is Cfengine maintained and template expanded. Please see
/var/cfengine/sequences/policies/systemd_administration/bundles/systemd_administration_unit.cf
for details on how this systemd unit file was constructed.
# The data used to construct this template was passed from:
$(systemd_administration_unit.service_json_file)
# The state which was being requested by Cfengine was:
$(systemd_administration_unit.unit_data[state])

[Unit]
[%CFEngine BEGIN %]
[%CFEngine unit_After_populated:: %]
After=$(systemd_administration_unit.unit_data[Unit][After])
[%CFEngine unit_AllowIsolate_populated:: %]
AllowIsolate=$(systemd_administration_unit.unit_data[Unit][AllowIsolate])
[%CFEngine unit_AssertACPower_populated:: %]
AssertACPower=$(systemd_administration_unit.unit_data[Unit][AssertACPower])
[%CFEngine unit_AssertArchitecture_populated:: %]
AssertArchitecture=$(systemd_administration_unit.unit_data[Unit][AssertArchitecture])
[%CFEngine unit_AssertCapability_populated:: %]
AssertCapability=$(systemd_administration_unit.unit_data[Unit][AssertCapability])
[%CFEngine unit_AssertDirectoryNotEmpty_populated:: %]
AssertDirectoryNotEmpty=$(systemd_administration_unit.unit_data[Unit][AssertDirectoryNotEmpty])
[%CFEngine unit_AssertFileIsExecutable_populated:: %]
AssertFileIsExecutable=$(systemd_administration_unit.unit_data[Unit][AssertFileIsExecutable])
[%CFEngine unit_AssertFileNotEmpty_populated:: %]
AssertFileNotEmpty=$(systemd_administration_unit.unit_data[Unit][AssertFileNotEmpty])
[%CFEngine unit_AssertFirstBoot_populated:: %]
AssertFirstBoot=$(systemd_administration_unit.unit_data[Unit][AssertFirstBoot])
[%CFEngine unit_AssertHost_populated:: %]
AssertHost=$(systemd_administration_unit.unit_data[Unit][AssertHost])
[%CFEngine unit_AssertKernelCommandLine_populated:: %]
AssertKernelCommandLine=$(systemd_administration_unit.unit_data[Unit][AssertKernelCommandLine])
[%CFEngine unit_AssertNeedsUpdate_populated:: %]
AssertNeedsUpdate=$(systemd_administration_unit.unit_data[Unit][AssertNeedsUpdate])
[%CFEngine unit_AssertPathExists_populated:: %]
AssertPathExists=$(systemd_administration_unit.unit_data[Unit][AssertPathExists])
[%CFEngine unit_AssertPathExistsGlob_populated:: %]
AssertPathExistsGlob=$(systemd_administration_unit.unit_data[Unit][AssertPathExistsGlob])
[%CFEngine unit_AssertPathIsDirectory_populated:: %]
AssertPathIsDirectory=$(systemd_administration_unit.unit_data[Unit][AssertPathIsDirectory])
[%CFEngine unit_AssertPathIsMountPoint_populated:: %]
AssertPathIsMountPoint=$(systemd_administration_unit.unit_data[Unit][AssertPathIsMountPoint])
[%CFEngine unit_AssertPathIsReadWrite_populated:: %]
AssertPathIsReadWrite=$(systemd_administration_unit.unit_data[Unit][AssertPathIsReadWrite])
[%CFEngine unit_AssertPathIsSymbolicLink_populated:: %]
AssertPathIsSymbolicLink=$(systemd_administration_unit.unit_data[Unit][AssertPathIsSymbolicLink])
[%CFEngine unit_AssertSecurity_populated:: %]
AssertSecurity=$(systemd_administration_unit.unit_data[Unit][AssertSecurity])
[%CFEngine unit_AssertVirtualization_populated:: %]
AssertVirtualization=$(systemd_administration_unit.unit_data[Unit][AssertVirtualization])
[%CFEngine unit_Before_populated:: %]
Before=$(systemd_administration_unit.unit_data[Unit][Before])
[%CFEngine unit_BindsTo_populated:: %]
BindsTo=$(systemd_administration_unit.unit_data[Unit][BindsTo])
[%CFEngine unit_ConditionACPower_populated:: %]
ConditionACPower=$(systemd_administration_unit.unit_data[Unit][ConditionACPower])
[%CFEngine unit_ConditionArchitecture_populated:: %]
ConditionArchitecture=$(systemd_administration_unit.unit_data[Unit][ConditionArchitecture])
[%CFEngine unit_ConditionCapability_populated:: %]
ConditionCapability=$(systemd_administration_unit.unit_data[Unit][ConditionCapability])
[%CFEngine unit_ConditionDirectoryNotEmpty_populated:: %]
ConditionDirectoryNotEmpty=$(systemd_administration_unit.unit_data[Unit][ConditionDirectoryNotEmpty])
[%CFEngine unit_ConditionFileIsExecutable_populated:: %]
ConditionFileIsExecutable=$(systemd_administration_unit.unit_data[Unit][ConditionFileIsExecutable])
[%CFEngine unit_ConditionFileNotEmpty_populated:: %]
ConditionFileNotEmpty=$(systemd_administration_unit.unit_data[Unit][ConditionFileNotEmpty])
[%CFEngine unit_ConditionFirstBoot_populated:: %]
ConditionFirstBoot=$(systemd_administration_unit.unit_data[Unit][ConditionFirstBoot])
[%CFEngine unit_ConditionHost_populated:: %]
ConditionHost=$(systemd_administration_unit.unit_data[Unit][ConditionHost])
[%CFEngine unit_ConditionKernelCommandLine_populated:: %]
ConditionKernelCommandLine=$(systemd_administration_unit.unit_data[Unit][ConditionKernelCommandLine])
[%CFEngine unit_ConditionNeedsUpdate_populated:: %]
ConditionNeedsUpdate=$(systemd_administration_unit.unit_data[Unit][ConditionNeedsUpdate])
[%CFEngine unit_ConditionPathExists_populated:: %]
ConditionPathExists=$(systemd_administration_unit.unit_data[Unit][ConditionPathExists])
[%CFEngine unit_ConditionPathExistsGlob_populated:: %]
ConditionPathExistsGlob=$(systemd_administration_unit.unit_data[Unit][ConditionPathExistsGlob])
[%CFEngine unit_ConditionPathIsDirectory_populated:: %]
ConditionPathIsDirectory=$(systemd_administration_unit.unit_data[Unit][ConditionPathIsDirectory])
[%CFEngine unit_ConditionPathIsMountPoint_populated:: %]
ConditionPathIsMountPoint=$(systemd_administration_unit.unit_data[Unit][ConditionPathIsMountPoint])
[%CFEngine unit_ConditionPathIsReadWrite_populated:: %]
ConditionPathIsReadWrite=$(systemd_administration_unit.unit_data[Unit][ConditionPathIsReadWrite])
[%CFEngine unit_ConditionPathIsSymbolicLink_populated:: %]
ConditionPathIsSymbolicLink=$(systemd_administration_unit.unit_data[Unit][ConditionPathIsSymbolicLink])
[%CFEngine unit_ConditionSecurity_populated:: %]
ConditionSecurity=$(systemd_administration_unit.unit_data[Unit][ConditionSecurity])
[%CFEngine unit_ConditionVirtualization_populated:: %]
ConditionVirtualization=$(systemd_administration_unit.unit_data[Unit][ConditionVirtualization])
[%CFEngine unit_Conflicts_populated:: %]
Conflicts=$(systemd_administration_unit.unit_data[Unit][Conflicts])
[%CFEngine unit_DefaultDependencies_populated:: %]
DefaultDependencies=$(systemd_administration_unit.unit_data[Unit][DefaultDependencies])
[%CFEngine unit_Description_populated:: %]
Description=$(systemd_administration_unit.unit_data[Unit][Description])
[%CFEngine unit_Documentation_populated:: %]
Documentation=$(systemd_administration_unit.unit_data[Unit][Documentation])
[%CFEngine unit_IgnoreOnIsolate_populated:: %]
IgnoreOnIsolate=$(systemd_administration_unit.unit_data[Unit][IgnoreOnIsolate])
[%CFEngine unit_IgnoreOnSnapshot_populated:: %]
IgnoreOnSnapshot=$(systemd_administration_unit.unit_data[Unit][IgnoreOnSnapshot])
[%CFEngine unit_JobTimeoutAction_populated:: %]
JobTimeoutAction=$(systemd_administration_unit.unit_data[Unit][JobTimeoutAction])
[%CFEngine unit_JobTimeoutRebootArgument_populated:: %]
JobTimeoutRebootArgument=$(systemd_administration_unit.unit_data[Unit][JobTimeoutRebootArgument])
[%CFEngine unit_JobTimeoutSec_populated:: %]
JobTimeoutSec=$(systemd_administration_unit.unit_data[Unit][JobTimeoutSec])
[%CFEngine unit_JoinsNamespaceOf_populated:: %]
JoinsNamespaceOf=$(systemd_administration_unit.unit_data[Unit][JoinsNamespaceOf])
[%CFEngine unit_OnFailure_populated:: %]
OnFailure=$(systemd_administration_unit.unit_data[Unit][OnFailure])
[%CFEngine unit_OnFailureJobMode_populated:: %]
OnFailureJobMode=$(systemd_administration_unit.unit_data[Unit][OnFailureJobMode])
[%CFEngine unit_PartOf_populated:: %]
PartOf=$(systemd_administration_unit.unit_data[Unit][PartOf])
[%CFEngine unit_PropagatesReloadTo_populated:: %]
PropagatesReloadTo=$(systemd_administration_unit.unit_data[Unit][PropagatesReloadTo])
[%CFEngine unit_RefuseManualStart_populated:: %]
RefuseManualStart=$(systemd_administration_unit.unit_data[Unit][RefuseManualStart])
[%CFEngine unit_RefuseManualStop_populated:: %]
RefuseManualStop=$(systemd_administration_unit.unit_data[Unit][RefuseManualStop])
[%CFEngine unit_ReloadPropagatedFrom_populated:: %]
ReloadPropagatedFrom=$(systemd_administration_unit.unit_data[Unit][ReloadPropagatedFrom])
[%CFEngine unit_Requires_populated:: %]
Requires=$(systemd_administration_unit.unit_data[Unit][Requires])
[%CFEngine unit_RequiresMountsFor_populated:: %]
RequiresMountsFor=$(systemd_administration_unit.unit_data[Unit][RequiresMountsFor])
[%CFEngine unit_RequiresOverridable_populated:: %]
RequiresOverridable=$(systemd_administration_unit.unit_data[Unit][RequiresOverridable])
[%CFEngine unit_Requisite_populated:: %]
Requisite=$(systemd_administration_unit.unit_data[Unit][Requisite])
[%CFEngine unit_RequisiteOverridable_populated:: %]
RequisiteOverridable=$(systemd_administration_unit.unit_data[Unit][RequisiteOverridable])
[%CFEngine unit_SourcePath_populated:: %]
SourcePath=$(systemd_administration_unit.unit_data[Unit][SourcePath])
[%CFEngine unit_StopWhenUnneeded_populated:: %]
StopWhenUnneeded=$(systemd_administration_unit.unit_data[Unit][StopWhenUnneeded])
[%CFEngine unit_Wants_populated:: %]
Wants=$(systemd_administration_unit.unit_data[Unit][Wants])
[%CFEngine END %]

[Service]
[%CFEngine BEGIN %]
[%CFEngine service_BusName_populated:: %]
BusName=$(systemd_administration_unit.unit_data[Service][BusName])
[%CFEngine service_BusPolicy_populated:: %]
BusPolicy=$(systemd_administration_unit.unit_data[Service][BusPolicy])
[%CFEngine service_ExecReload_populated:: %]
ExecReload=$(systemd_administration_unit.unit_data[Service][ExecReload])
[%CFEngine service_ExecStart_populated:: %]
ExecStart=$(systemd_administration_unit.unit_data[Service][ExecStart])
[%CFEngine service_ExecStartPost_populated:: %]
ExecStartPost=$(systemd_administration_unit.unit_data[Service][ExecStartPost])
[%CFEngine service_ExecStartPre_populated:: %]
ExecStartPre=$(systemd_administration_unit.unit_data[Service][ExecStartPre])
[%CFEngine service_ExecStop_populated:: %]
ExecStop=$(systemd_administration_unit.unit_data[Service][ExecStop])
[%CFEngine service_ExecStopPost_populated:: %]
ExecStopPost=$(systemd_administration_unit.unit_data[Service][ExecStopPost])
[%CFEngine service_FailureAction_populated:: %]
FailureAction=$(systemd_administration_unit.unit_data[Service][FailureAction])
[%CFEngine service_FileDescriptorStoreMax_populated:: %]
FileDescriptorStoreMax=$(systemd_administration_unit.unit_data[Service][FileDescriptorStoreMax])
[%CFEngine service_Group_populated:: %]
Group=$(systemd_administration_unit.unit_data[Service][Group])
[%CFEngine service_GuessMainPID_populated:: %]
GuessMainPID=$(systemd_administration_unit.unit_data[Service][GuessMainPID])
[%CFEngine service_NonBlocking_populated:: %]
NonBlocking=$(systemd_administration_unit.unit_data[Service][NonBlocking])
[%CFEngine service_NotifyAccess_populated:: %]
NotifyAccess=$(systemd_administration_unit.unit_data[Service][NotifyAccess])
[%CFEngine service_PIDFile_populated:: %]
PIDFile=$(systemd_administration_unit.unit_data[Service][PIDFile])
[%CFEngine service_PermissionsStartOnly_populated:: %]
PermissionsStartOnly=$(systemd_administration_unit.unit_data[Service][PermissionsStartOnly])
[%CFEngine service_RebootArgument_populated:: %]
RebootArgument=$(systemd_administration_unit.unit_data[Service][RebootArgument])
[%CFEngine service_RemainAfterExit_populated:: %]
RemainAfterExit=$(systemd_administration_unit.unit_data[Service][RemainAfterExit])
[%CFEngine service_Restart_populated:: %]
Restart=$(systemd_administration_unit.unit_data[Service][Restart])
[%CFEngine service_RestartForceExitStatus_populated:: %]
RestartForceExitStatus=$(systemd_administration_unit.unit_data[Service][RestartForceExitStatus])
[%CFEngine service_RestartPreventExitStatus_populated:: %]
RestartPreventExitStatus=$(systemd_administration_unit.unit_data[Service][RestartPreventExitStatus])
[%CFEngine service_RestartSec_populated:: %]
RestartSec=$(systemd_administration_unit.unit_data[Service][RestartSec])
[%CFEngine service_RootDirectoryStartOnly_populated:: %]
RootDirectoryStartOnly=$(systemd_administration_unit.unit_data[Service][RootDirectoryStartOnly])
[%CFEngine service_Sockets_populated:: %]
Sockets=$(systemd_administration_unit.unit_data[Service][Sockets])
[%CFEngine service_StartLimitAction_populated:: %]
StartLimitAction=$(systemd_administration_unit.unit_data[Service][StartLimitAction])
[%CFEngine service_StartLimitBurst_populated:: %]
StartLimitBurst=$(systemd_administration_unit.unit_data[Service][StartLimitBurst])
[%CFEngine service_StartLimitInterval_populated:: %]
StartLimitInterval=$(systemd_administration_unit.unit_data[Service][StartLimitInterval])
[%CFEngine service_SuccessExitStatus_populated:: %]
SuccessExitStatus=$(systemd_administration_unit.unit_data[Service][SuccessExitStatus])
[%CFEngine service_TimeoutSec_populated:: %]
TimeoutSec=$(systemd_administration_unit.unit_data[Service][TimeoutSec])
[%CFEngine service_TimeoutStartSec_populated:: %]
TimeoutStartSec=$(systemd_administration_unit.unit_data[Service][TimeoutStartSec])
[%CFEngine service_TimeoutStopSec_populated:: %]
TimeoutStopSec=$(systemd_administration_unit.unit_data[Service][TimeoutStopSec])
[%CFEngine service_Type_populated:: %]
Type=$(systemd_administration_unit.unit_data[Service][Type])
[%CFEngine service_User_populated:: %]
User=$(systemd_administration_unit.unit_data[Service][User])
[%CFEngine service_WatchdogSec_populated:: %]
WatchdogSec=$(systemd_administration_unit.unit_data[Service][WatchdogSec])
[%CFEngine END %]

[Install]
[%CFEngine BEGIN %]
[%CFEngine install_Alias_populated:: %]
Alias=$(systemd_administration_unit.unit_data[Install][Alias])
[%CFEngine install_Also_populated:: %]
Also=$(systemd_administration_unit.unit_data[Install][Also])
[%CFEngine install_DefaultInstance_populated:: %]
DefaultInstance=$(systemd_administration_unit.unit_data[Install][DefaultInstance])
[%CFEngine install_RequiredBy_populated:: %]
RequiredBy=$(systemd_administration_unit.unit_data[Install][RequiredBy])
[%CFEngine install_WantedBy_populated:: %]
WantedBy=$(systemd_administration_unit.unit_data[Install][WantedBy])
[%CFEngine END %]


systemd_administration_adjust_service_state.cf
[root@lva1-cfe-guppy04 msvoboda]# cat
/var/cfengine/sequences/policies/systemd_administration/bundles/systemd_administration_adjust_service_state.cf
bundle agent systemd_administration_adjust_service_state(service, state) {
vars:
systemd::
"call_systemctl" string => "/usr/bin/systemctl --no-ask-password
--global --system -q";
"canonified_service" string => canonify("$(service)");
"cfengine_systemd_root"
string =>
"$(default:systemd_administration_discover_current_state.cfengine_systemd_root)"
;
"service_classes" slist => classesmatching("_$(canonified_service)_.*"
);
"service_classes_sorted" slist => sort("service_classes", "lex");

classes:
systemd::
"service_classes_sorted_populated" expression => reglist(
"@(service_classes_sorted)", ".+");

"_$(canonified_service)_service_enabled"
expression =>
strcmp("enabled",

"$(systemd_administration_discover_current_state.systemd_unit_file_state[$(canonified_service)])"
);
"_$(canonified_service)_service_indirect"
expression =>
strcmp("indirect",

"$(systemd_administration_discover_current_state.systemd_unit_file_state[$(canonified_service)])"
);
"_$(canonified_service)_service_static"
expression =>
strcmp("static",

"$(systemd_administration_discover_current_state.systemd_unit_file_state[$(canonified_service)])"
);
"_$(canonified_service)_service_active"
expression =>
strcmp("active",

"$(systemd_administration_discover_current_state.systemd_active_state[$(canonified_service)])"
);
"_$(canonified_service)_service_inactive"
expression =>
strcmp("inactive",

"$(systemd_administration_discover_current_state.systemd_active_state[$(canonified_service)])"
);
"_$(canonified_service)_service_failed"
expression =>
strcmp("failed",

"$(systemd_administration_discover_current_state.systemd_active_state[$(canonified_service)])"
);
"_$(canonified_service)_service_loaded"
expression =>
strcmp("loaded",

"$(systemd_administration_discover_current_state.systemd_load_state[$(canonified_service)])"
);

"_$(canonified_service)_can_stop_service"
expression =>
strcmp("yes",

"$(systemd_administration_discover_current_state.systemd_can_stop[$(canonified_service)])"
);
"_$(canonified_service)_can_start_service"
expression =>
strcmp("yes",

"$(systemd_administration_discover_current_state.systemd_can_start[$(canonified_service)])"
);
"_$(canonified_service)_can_reload_service"
expression =>
strcmp("yes",

"$(systemd_administration_discover_current_state.systemd_can_reload[$(canonified_service)])"
);

"_$(canonified_service)_request_start" expression => strcmp("start",
"$(state)");
"_$(canonified_service)_request_stop" expression => strcmp("stop",
"$(state)");
"_$(canonified_service)_request_reload" expression => strcmp("reload"
, "$(state)");
"_$(canonified_service)_request_restart" expression => strcmp(
"restart", "$(state)");

"_$(canonified_service)_action_known"
expression => "systemd",
ifvarclass => or(canonify("_$(canonified_service)_request_start"),
canonify("_$(canonified_service)_request_stop"),
canonify("_$(canonified_service)_request_reload"),
canonify("_$(canonified_service)_request_start"));

"_$(canonified_service)_action_custom"
expression => "systemd",
ifvarclass => not(canonify("_$(canonified_service)_action_known"));

"_$(canonified_service)_action_stop"
expression => "systemd",
ifvarclass => and(canonify("_$(canonified_service)_request_stop"),
canonify("_$(canonified_service)_service_active"),
canonify(
"_$(canonified_service)_can_start_service"));

"_$(canonified_service)_action_start"
expression => "systemd",
ifvarclass => and(canonify("_$(canonified_service)_request_start"),
not(canonify(
"_$(canonified_service)_service_active")),
canonify(
"_$(canonified_service)_can_start_service"));

"_$(canonified_service)_action_reload"
expression => "systemd",
ifvarclass => and(canonify("_$(canonified_service)_request_reload"),
canonify("_$(canonified_service)_service_active"),
canonify(
"_$(canonified_service)_can_reload_service"));

"_$(canonified_service)_action_restart"
expression => "systemd",
ifvarclass => and(canonify("_$(canonified_service)_request_restart"
),
canonify("_$(canonified_service)_service_active"
));

# Possibly undesirable... if a reload is requested, and the service
"can't" be reloaded, then we restart it instead.
"_$(canonified_service)_action_restart"
expression => "systemd",
ifvarclass => and(canonify("_$(canonified_service)_request_reload"),
not(canonify(
"_$(canonified_service)_can_reload_service")),
canonify("_$(canonified_service)_service_active"
));

# Starting a service implicitly enables it
"_$(canonified_service)_action_enable"
expression => "systemd",
ifvarclass => and(canonify("_$(canonified_service)_request_start"),
not(canonify(
"_$(canonified_service)_service_enabled")),
not(canonify(
"_$(canonified_service)_service_indirect")),
not(canonify(
"_$(canonified_service)_service_static")));

# Respectively, stopping it implicitly disables it
"_$(canonified_service)_action_disable"
expression => "systemd",
ifvarclass => and(canonify("_$(canonified_service)_request_stop"),
canonify("_$(canonified_service)_service_enabled"
));

files:
"$(cfengine_systemd_root)/service_classes_$(service).txt"
comment => "dump discovered classes from when we probed the service"
,
create => "true",
perms => mog("0644", "root", "root"),
edit_defaults => empty,
edit_line => append_if_no_line("@(service_classes_sorted)");

commands:
systemd::
"$(call_systemctl) reset-failed $(service)"
ifvarclass => and(canonify("_$(canonified_service)_service_loaded"),
canonify("_$(canonified_service)_service_failed"
)),
classes => if_repaired(
"_$(canonified_service)_reset_failed_executed");

systemd::
"$(call_systemctl) start $(service)"
ifvarclass => and(canonify("_$(canonified_service)_service_loaded"),
canonify("_$(canonified_service)_action_start")),
classes => if_repaired("_$(canonified_service)_start_executed");

systemd::
"$(call_systemctl) stop $(service)"
ifvarclass => and(canonify("_$(canonified_service)_service_loaded"),
canonify("_$(canonified_service)_action_stop")),
classes => if_repaired("_$(canonified_service)_stop_executed");

systemd::
"$(call_systemctl) reload $(service)"
ifvarclass => and(canonify("_$(canonified_service)_service_loaded"),
canonify("_$(canonified_service)_action_reload")),
classes => if_repaired("_$(canonified_service)_reload_executed");

systemd::
"$(call_systemctl) enable $(service)"
ifvarclass => and(canonify("_$(canonified_service)_service_loaded"),
canonify("_$(canonified_service)_action_enable")),
classes => if_repaired("_$(canonified_service)_enable_executed");

systemd::
"$(call_systemctl) disable $(service)"
ifvarclass => and(canonify("_$(canonified_service)_service_loaded"),
canonify("_$(canonified_service)_action_disable"
)),
classes => if_repaired("_$(canonified_service)_disable_executed");

systemd::
"$(call_systemctl) $(state) $(service)"
ifvarclass => and(canonify("_$(canonified_service)_service_loaded"),
canonify("_$(canonified_service)_action_custom")),
classes => if_repaired(
"_$(canonified_service)_custom_action_executed");

reports:
debug_systemd_state.systemd::
"$(global.execution_report) systemd state: $(service) enabled"
ifvarclass => canonify("_$(canonified_service)_service_enabled");

debug_systemd_state.systemd::
"$(global.execution_report) systemd state: $(service) loaded"
ifvarclass => canonify("_$(canonified_service)_service_loaded");

debug_systemd_state.systemd::
"$(global.execution_report) systemd state: $(service) can stop"
ifvarclass => canonify("_$(canonified_service)_service_can_stop");

debug_systemd_state.systemd::
"$(global.execution_report) systemd state: $(service) can start"
ifvarclass => canonify("_$(canonified_service)_service_can_start");

debug_systemd_state.systemd::
"$(global.execution_report) systemd state: $(service) can reload"
ifvarclass => canonify("_$(canonified_service)_service_can_reload");

systemd::
"$(global.execution_report) Requesting start of $(service) which was
found inactive."
ifvarclass => and(canonify("_$(canonified_service)_service_inactive"
),
canonify("_$(canonified_service)_request_start"));

systemd::
"$(global.execution_report) Requesting stop of $(service) which was
found active."
ifvarclass => and(canonify("_$(canonified_service)_service_active"),
canonify("_$(canonified_service)_request_stop"));

systemd::
"$(global.execution_report) Requesting restart of $(service)"
ifvarclass => canonify("_$(canonified_service)_request_restart");

systemd::
"$(global.execution_report) Requesting reload of $(service)"
ifvarclass => canonify("_$(canonified_service)_service_reload");

systemd::
"$(global.execution_report) systemd $(service) reset-failed was
executed at $(sys.date)"
ifvarclass => canonify(
"_$(canonified_service)_reset_failed_executed");

systemd::
"$(global.execution_report) systemd $(service) was started at
$(sys.date)"
ifvarclass => canonify("_$(canonified_service)_start_executed");

systemd::
"$(global.execution_report) systemd $(service) was stopped at
$(sys.date)"
ifvarclass => canonify("_$(canonified_service)_stop_executed");

systemd::
"$(global.execution_report) systemd $(service) was reloaded at
$(sys.date)"
ifvarclass => canonify("_$(canonified_service)_reload_executed");

systemd::
"$(global.execution_report) systemd $(service) was restarted at
$(sys.date)"
ifvarclass => canonify("_$(canonified_service)_restart_executed");

systemd::
"$(global.execution_report) systemd $(service) was enabled at
$(sys.date)"
ifvarclass => canonify("_$(canonified_service)_enable_executed");

systemd::
"$(global.execution_report) systemd $(service) was disabled at
$(sys.date)"
ifvarclass => canonify("_$(canonified_service)_disable_executed");

systemd::
"$(global.execution_report) systemd $(service) custom action $(state)
was executed at $(sys.date)"
ifvarclass => canonify(
"_$(canonified_service)_custom_action_executed");
}


systemd_administration_enforce_standards.cf
[root@lva1-cfe-guppy04 msvoboda]# cat
/var/cfengine/sequences/policies/systemd_administration/bundles/systemd_administration_enforce_standards.cf

bundle agent systemd_administration_enforce_standards(service_json_file)
{
vars:
systemd::
"canonified_json_filename" string => canonify("$(service_json_file)");
"systemd_json_deployment_directory" string =>
"$(systemd_administration_discover_deployables.systemd_json_deployment_directory)"
;
"systemd_user_deployments" slist => {
"@(systemd_administration_discover_deployables.systemd_user_deployments)" };
"service_json_dirname" string => dirname("$(service_json_file)");

# Default linkedin values for various attributes, class overwritable.
# These values are used to populate the systemd unit files with our
default values if not discovered in the JSON containers.
"Restart" string => "always";
"RestartSec" string => "5";

"unit_data" data => readjson("$(service_json_file)", "inf");

"unit_tunables" slist => {
"After",
"AllowIsolate",
"AssertACPower",
"AssertArchitecture",
"AssertCapability",
"AssertDirectoryNotEmpty",
"AssertFileIsExecutable",
"AssertFileNotEmpty",
"AssertFirstBoot",
"AssertHost",
"AssertKernelCommandLine",
"AssertNeedsUpdate",
"AssertPathExists",
"AssertPathExistsGlob",
"AssertPathIsDirectory",
"AssertPathIsMountPoint",
"AssertPathIsReadWrite",
"AssertPathIsSymbolicLink",
"AssertSecurity",
"AssertVirtualization",
"Before",
"BindsTo",
"ConditionACPower",
"ConditionArchitecture",
"ConditionCapability",
"ConditionDirectoryNotEmpty",
"ConditionFileIsExecutable",
"ConditionFileNotEmpty",
"ConditionFirstBoot",
"ConditionHost",
"ConditionKernelCommandLine",
"ConditionNeedsUpdate",
"ConditionPathExists",
"ConditionPathExistsGlob",
"ConditionPathIsDirectory",
"ConditionPathIsMountPoint",
"ConditionPathIsReadWrite",
"ConditionPathIsSymbolicLink",
"ConditionSecurity",
"ConditionVirtualization",
"Conflicts",
"DefaultDependencies",
"Description",
"Documentation",
"IgnoreOnIsolate",
"IgnoreOnSnapshot",
"JobTimeoutAction",
"JobTimeoutRebootArgument",
"JobTimeoutSec",
"JoinsNamespaceOf",
"OnFailure",
"OnFailureJobMode",
"PartOf",
"PropagatesReloadTo",
"RefuseManualStart",
"RefuseManualStop",
"ReloadPropagatedFrom",
"Requires",
"RequiresMountsFor",
"RequiresOverridable",
"Requisite",
"RequisiteOverridable",
"SourcePath",
"StopWhenUnneeded",
"Wants",
};

"service_tunables" slist => {
"BusName",
"BusPolicy",
"ExecReload",
"ExecStart",
"ExecStartPost",
"ExecStartPre",
"ExecStop",
"ExecStopPost",
"FailureAction",
"FileDescriptorStoreMax",
"Group",
"GuessMainPID",
"NonBlocking",
"NotifyAccess",
"PIDFile",
"PermissionsStartOnly",
"RebootArgument",
"RemainAfterExit",
"Restart",
"RestartForceExitStatus",
"RestartPreventExitStatus",
"RestartSec",
"RootDirectoryStartOnly",
"Sockets",
"StartLimitAction",
"StartLimitBurst",
"StartLimitInterval",
"SuccessExitStatus",
"TimeoutSec",
"TimeoutStartSec",
"TimeoutStopSec",
"Type",
"User",
"WatchdogSec",
};

"install_tunables" slist => {
"Alias",
"Also",
"DefaultInstance",
"RequiredBy",
"WantedBy",
};

# The following attributes have to be present, otherwise we abort
administration of the systemd service
"manditory_unit_attributes" slist => {"Description", };
"manditory_service_attributes" slist => {"Type", "ExecStart", };
"manditory_install_attributes" slist => {"WantedBy", };

# The following attributes, if not set, we enforce defaults so that
we mimic runit behavior (automatic restarts)
"linkedin_enforced_unit_attributes" slist => {};
"linkedin_enforced_service_attributes" slist => {"Restart",
"RestartSec", "User", "Group" };
"linkedin_enforced_install_attributes" slist => {};

modify_User_required::
"unit_data[Service][User]" string => "$(systemd_user_deployments)",
ifvarclass => canonify("enforce_user_$(systemd_user_deployments)");

modify_Group_required::
"unit_data[Service][Group]" string => "$(systemd_user_deployments)",
ifvarclass => canonify("enforce_user_$(systemd_user_deployments)");

modify_Restart_required::
"unit_data[Service][Restart]" string => "$(Restart)";

modify_RestartSec_required::
"unit_data[Service][RestartSec]" string => "$(RestartSec)";

service_state_missing::
"unit_data[state]" string => "start";

classes:
# raise classes for all attributes that we discovered in the JSON
container. These classes are used in template expansion.
systemd::
"unit_$(unit_tunables)_populated"
expression => regcmp(".+", "$(unit_data[Unit][$(unit_tunables)])"),
scope => "namespace";
systemd::
"service_$(service_tunables)_populated"
expression => regcmp(".+",
"$(unit_data[Service][$(service_tunables)])"),
scope => "namespace";
systemd::
"install_$(install_tunables)_populated"
expression => regcmp(".+",
"$(unit_data[Install][$(install_tunables)])"),
scope => "namespace";

# If we've come back and enforced default values, raise the necessary
"populated" classes so the template is able to expand our enforced values
correctly.
systemd::
"unit_$(linkedin_enforced_unit_attributes)_populated" expression =>
"systemd",
ifvarclass => canonify(
"modify_$(linkedin_enforced_unit_attributes)_required"),
scope => "namespace";

systemd::
"service_$(linkedin_enforced_service_attributes)_populated" expression
=> "systemd",
ifvarclass => canonify(
"modify_$(linkedin_enforced_service_attributes)_required"),
scope => "namespace";

systemd::
"install_$(linkedin_enforced_install_attributes)_populated" expression
=> "systemd",
ifvarclass => canonify(
"modify_$(linkedin_enforced_install_attributes)_required"),
scope => "namespace";

########################################### MANDITORY ATTRIBUTES FROM
USERS OR WE ABORT ################################################
########################################### MANDITORY ATTRIBUTES FROM
USERS OR WE ABORT ################################################
########################################### MANDITORY ATTRIBUTES FROM
USERS OR WE ABORT ################################################
# we require some basic attributes in the json contained to be
defined. if they aren't then we should refuse
# to do anything and complain loudly in report promises.
systemd::
"service_name_present" expression => regcmp(".+", "$(unit_data[name])"
);
"service_name_missing" not => "service_name_present";

systemd::
"required_unit_attribute_missing_$(manditory_unit_attributes)" expression
=> "systemd",
ifvarclass
=> not("unit_$(manditory_unit_attributes)_populated");

systemd::
"required_service_attribute_missing_$(manditory_service_attributes)" expression
=> "systemd",
ifvarclass
=> not("service_$(manditory_service_attributes)_populated");

systemd::
"required_install_attribute_missing_$(manditory_install_attributes)" expression
=> "systemd",
ifvarclass
=> not("install_$(manditory_install_attributes)_populated");

# this namespace class is used to communicate that its safe to go ahead
and administrate the service. if we hit this, we refuse to administrate it
# in systemd_administration_unit.cf
systemd::
"abort_unit_file_$(canonified_json_filename)" or => {
classmatch(
"required_(unit|service|install)_attribute_missing.*"),

"service_name_missing",
},
scope => "namespace";
########################################### MANDITORY ATTRIBUTES FROM
USERS OR WE ABORT ################################################
########################################### MANDITORY ATTRIBUTES FROM
USERS OR WE ABORT ################################################
########################################### MANDITORY ATTRIBUTES FROM
USERS OR WE ABORT ################################################




########################################## CFENGINE ENFORCED ATTRIBUTES
IF NOT DISCOVERED ##############################################
########################################## CFENGINE ENFORCED ATTRIBUTES
IF NOT DISCOVERED ##############################################
########################################## CFENGINE ENFORCED ATTRIBUTES
IF NOT DISCOVERED ##############################################
systemd::
"verify_user_group_execution" expression => regcmp(
"$(systemd_json_deployment_directory).*", "$(service_json_dirname)");

systemd.verify_user_group_execution::
# if the user= or group= is missing, we need a class to determine
which user and group to set to.
"enforce_user_$(systemd_user_deployments)" expression => strcmp(
"$(service_json_dirname)",
"$(systemd_json_deployment_directory)/$(systemd_user_deployments)");

systemd::
# the following three classes are used to determine if we're missing
attributes that we're gonna fill with default values.
"modify_$(linkedin_enforced_unit_attributes)_required" expression =>
"systemd",
ifvarclass =>
not("unit_$(linkedin_enforced_unit_attributes)_populated");

systemd::
"modify_$(linkedin_enforced_service_attributes)_required" expression
=> "systemd",
ifvarclass
=> not("service_$(linkedin_enforced_service_attributes)_populated");

systemd::
"modify_$(linkedin_enforced_install_attributes)_required" expression
=> "systemd",
ifvarclass
=> not("install_$(linkedin_enforced_install_attributes)_populated");

systemd::
"service_state_present" expression => regcmp(".+",
"$(unit_data[state])");
"service_state_missing" not => "service_state_present";

########################################## CFENGINE ENFORCED ATTRIBUTES
IF NOT DISCOVERED ##############################################
########################################## CFENGINE ENFORCED ATTRIBUTES
IF NOT DISCOVERED ##############################################
########################################## CFENGINE ENFORCED ATTRIBUTES
IF NOT DISCOVERED ##############################################

reports:
systemd.service_state_missing::
"$(global.execution_report) We did not find the service state for
$(unit_data[name]) in $(service_json_file). Defaulting to the start state";

systemd.verify_user_group_execution.debug_systemd_state::
"$(global.execution_report) Validating User and Group membership of
$(service_json_file)";

systemd.debug_systemd_state::
"$(global.execution_report) We are enforcing the user
$(systemd_user_deployments) on $(service_json_file)"
ifvarclass => canonify("enforce_user_$(systemd_user_deployments)");

systemd::
"$(global.execution_report) We discovered that the LinkedIn enforced
systemd unit attribute $(linkedin_enforced_unit_attributes) was not
populated in $(service_json_file) for service $(unit_data[name]). Cfengine
is going to enforce a default value."
ifvarclass => canonify(
"modify_$(linkedin_enforced_unit_attributes)_required");

systemd::
"$(global.execution_report) We discovered that the LinkedIn enforced
systemd service attribute $(linkedin_enforced_service_attributes) was not
populated in $(service_json_file) for service $(unit_data[name]). Cfengine
is going to enforce a default value."
ifvarclass => canonify(
"modify_$(linkedin_enforced_service_attributes)_required");

systemd::
"$(global.execution_report) We discovered that the LinkedIn enforced
systemd install attribute $(linkedin_enforced_install_attributes) was not
populated in $(service_json_file) for service $(unit_data[name]). Cfengine
is going to enforce a default value."
ifvarclass => canonify(
"modify_$(linkedin_enforced_install_attributes)_required");

systemd.service_name_missing::
"$(global.execution_report) The systemd service name was missing from
$(service_json_file)";

systemd::
"$(global.execution_report) WARNING WARNING WARNING!!! We hit a fatal
condition. Cfengine did not discover the required information in
$(service_json_file) to administrate the service. Processing is continuing
without administration of $(unit_data[name])"
ifvarclass => canonify("abort_unit_file_$(canonified_json_filename)"
);

systemd::
"$(global.execution_report) The required systemd Service attribute
$(manditory_service_attributes) was missing from $(service_json_file).
Cfengine is refusing to deploy this systemd service"
ifvarclass => canonify(
"required_service_attribute_missing_$(manditory_service_attributes)");

systemd::
"$(global.execution_report) The required systemd Install attribute
$(manditory_install_attributes) was missing from $(service_json_file).
Cfengine is refusing to deploy this systemd service"
ifvarclass => canonify(
"required_install_attribute_missing_$(manditory_install_attributes)");

systemd::
"$(global.execution_report) The required systemd Unit attribute
$(manditory_unit_attributes) was missing from $(service_json_file).
Cfengine is refusing to deploy this systemd service"
ifvarclass => canonify(
"required_unit_attribute_missing_$(manditory_unit_attributes)");
}
<https://iwww.corp.linkedin.com/wiki/cf/display/IEO/Cfengine+-+Systemd+Integration+and+Administration+--+Deprecating+runit>

Natxo Asenjo

unread,
Mar 11, 2016, 4:40:43 AM3/11/16
to help-cfengine
hi,

On Thu, Mar 10, 2016 at 9:27 PM, Mike Svoboda <michael....@gmail.com> wrote:

Those presentations of how you are dealing with systemd at linkedin are very very helpful.

Nice work! Thanks for sharing them. This will come in handy.

--
regards,
natxo

Shane McEwan

unread,
Mar 11, 2016, 5:00:32 AM3/11/16
to help-c...@googlegroups.com
+1

As always, a great writeup Mike. I always learn a lot from your posts.

Shane.

Tushar Vaghode

unread,
Mar 11, 2016, 2:23:41 PM3/11/16
to Mike Svoboda, help-cfengine

Just finished upgrading to CFE 3.7.2 – which works great.. and was investigating RHEL7/Systemd.. This is very helpful. Thanks for sharing.

 

 

From: help-c...@googlegroups.com [mailto:help-c...@googlegroups.com] On Behalf Of Mike Svoboda
Sent: Thursday, March 10, 2016 12:27 PM
To: help-cfengine <help-c...@googlegroups.com>
Subject: [help-cfengine] Part 3 - Systemd Integration and Administration

 

 

Part 3:  Source code

--
You received this message because you are subscribed to the Google Groups "help-cfengine" group.
To unsubscribe from this group and stop receiving emails from it, send an email to help-cfengin...@googlegroups.com.
To post to this group, send email to help-c...@googlegroups.com.
Visit this group at https://groups.google.com/group/help-cfengine.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages