##################################################################################### # Copyright 2011 Normation SAS ##################################################################################### # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, Version 3. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # ##################################################################################### # Enforce the defined services parameters bundle agent services_management { vars: &SERVICE_MANAGED_NAME:{name |"service[&i&][name]" string => "&name&"; }& &SERVICE_MANAGED_NAME:{name |"service[&i&][canon_name]" string => canonify("&name&"); }& &PROCESS_MANAGED_NAME:{process |"service[&i&][process]" string => "&process&"; }& &PROCESS_MANAGED_RUNNING:{running |"service[&i&][running]" string => "&running&"; }& &PROCESS_MANAGED_KILLING_METHOD:{kill |"service[&i&][killMethod]" string => "&kill&"; }& &PROCESS_MANAGED_MIN_INSTANCES:{min_instance |"service[&i&][min_instance]" string => "&min_instance&"; }& &PROCESS_MANAGED_MAX_INSTANCES:{max_instance |"service[&i&][max_instance]" string => "&max_instance&"; }& &TRACKINGKEY:{piuuid |"service[&i&][uuid]" string => "&piuuid&"; }& "index" slist => getindices("service"); classes: &PROCESS_MANAGED_NAME:{name |"defined_process_name_&i&" not => strcmp("&name&", ""); }& &PROCESS_MANAGED_CHECK_RANGE:{check |"check_process_range_&i&" expression => strcmp("&check&", "true"); }& &PROCESS_MANAGED_RUNNING:{running |"start_process_&i&" expression => strcmp("&running&", "true"); }& &PROCESS_MANAGED_RUNNING:{running |"stop_process_&i&" expression => strcmp("&running&", "false"); }& &PROCESS_MANAGED_KILLING_METHOD:{kill |"graceful_stop_process_&i&" expression => strcmp("&kill&", "graceful"); }& &PROCESS_MANAGED_KILLING_METHOD:{kill |"term_stop_process_&i&" expression => strcmp("&kill&", "term"); }& &PROCESS_MANAGED_KILLING_METHOD:{kill |"kill_stop_process_&i&" expression => strcmp("&kill&", "kill"); }& &PROCESS_MANAGED_BOOTSTART:{bootstart |"bootstart_process_&i&" expression => strcmp("&bootstart&", "true"); }& &PROCESS_MANAGED_BOOTSTART:{bootstart |"bootstart_prevent_process_&i&" expression => strcmp("&bootstart&", "false"); }& any:: "pass3" expression => "pass2"; "pass2" expression => "pass1"; "pass1" expression => "any"; files: debian:: "/etc/rc2.d/S.*${service[${index}][name]}.*" create => "true", action => WarnOnly, classes => if_else("service_${index}_bootstarted", "service_${index}_unbootstarted"); methods: pass2:: "bootstart_process" usebundle => service_ensure_started_at_boot("${service[${index}][name]}"), ifvarclass => "bootstart_process_${index}"; "unbootstart_process" usebundle => service_ensure_stopped("${service[${index}][name]}"), ifvarclass => "bootstart_prevent_process_${index}|stop_process_${index}"; # On Windows, we can't use processes: promises to detect the current status, so # we just call the service_{start,stop} bundles to ensure service state "start_process" usebundle => service_start("${service[${index}][name]}"), ifvarclass => "(process_${index}_restart|windows).start_process_${index}"; "stop_process" usebundle => service_stop("${service[${index}][name]}"), ifvarclass => "(!process_${index}_restart|windows).stop_process_${index}"; "restart_process" usebundle => service_restart("${service[${index}][name]}"), ifvarclass => canonify("${service[${index}][name]}_out_of_range"); pass3:: "any" usebundle => rudder_common_report("ServicesManagement", "result_success", "${service[${index}][uuid]}", "Process", "${service[${index}][name]}", "${service[${index}][name]} didn't need to have its process checked"), ifvarclass => "!start_process_${index}.!stop_process_${index}"; # On windows, we don't use processes promises type to check if process are running, as we rely directly on services !windows:: "any" usebundle => rudder_common_report("ServicesManagement", "result_error", "${service[${index}][uuid]}", "Process", "${service[${index}][name]}", "Cannot check the status of ${service[${index}][name]}: the process name is not filed"), ifvarclass => "!defined_process_name_${index}.(start_process_${index}|stop_process_${index})"; "any" usebundle => rudder_common_report("ServicesManagement", "result_success", "${service[${index}][uuid]}", "Process", "${service[${index}][name]}", "Process of ${service[${index}][name]} is running"), ifvarclass => "service_${index}_running.!service_${index}_anomaly.!process_${index}_restart.start_process_${index}"; "any" usebundle => rudder_common_report("ServicesManagement", "result_repaired", "${service[${index}][uuid]}", "Process", "${service[${index}][name]}", "Process of ${service[${index}][name]} was not running and has been restarted"), ifvarclass => concat("process_${index}_restart", ".", "start_process_${index}", ".", canonify("service_start_${service[${index}][name]}_repaired"); "any" usebundle => rudder_common_report("ServicesManagement", "result_error", "${service[${index}][uuid]}", "Process", "${service[${index}][name]}", "${service[${index}][name]}: the process couldn't be started"), ifvarclass => canonify("service_start_${service[${index}][name]}_not_ok"); "any" usebundle => rudder_common_report("ServicesManagement", "result_success", "${service[${index}][uuid]}", "Process", "${service[${index}][name]}", "Process of ${service[${index}][name]} is not running"), ifvarclass => "stop_process_${index}.process_${index}_restart.graceful_stop_process_${index}"; "any" usebundle => rudder_common_report("ServicesManagement", "result_repaired", "${service[${index}][uuid]}", "Process", "${service[${index}][name]}", "Process of ${service[${index}][name]} was stopped"), ifvarclass => concat("stop_process_${index}", ".!", "process_${index}_restart", ".", canonify("service_stop_${service[${index}][name]}_repaired"), ".", "graceful_stop_process_${index}"); "any" usebundle => rudder_common_report("ServicesManagement", "result_error", "${service[${index}][uuid]}", "Process", "${service[${index}][name]}", "${service[${index}][name]}: the process could't be stopped"), ifvarclass => concat("stop_process_${index}", ".!", "process_${index}_restart", ".", canonify("service_stop_${service[${index}][name]}_not_ok")); "any" usebundle => rudder_common_report("ServicesManagement", "result_success", "${service[${index}][uuid]}", "Process", "${service[${index}][name]}", "Process of ${service[${index}][name]} is not running"), ifvarclass => "stop_process_${index}.service_${index}_already_stopped.!service_${index}_stopped.!graceful_stop_process_${index}"; "any" usebundle => rudder_common_report("ServicesManagement", "result_repaired", "${service[${index}][uuid]}", "Process", "${service[${index}][name]}", "Process of ${service[${index}][name]} was stopped"), ifvarclass => "stop_process_${index}.service_${index}_stopped.!graceful_stop_process_${index}"; "any" usebundle => rudder_common_report("ServicesManagement", "result_error", "${service[${index}][uuid]}", "Process", "${service[${index}][name]}", "${service[${index}][name]}: the process count could't be stopped"), ifvarclass => "stop_process_${index}.service_${index}_error.!graceful_stop_process_${index}"; # on windows, the generic methods are directly defining the correct classes, without relying on the process check before hand windows:: "any" usebundle => rudder_common_reports_generic("ServicesManagement", "service_start_${service[${index}][canon_name]}", "${service[${index}][uuid]}", "Process", "${service[${index}][name]}", "Service ${service[${index}][name]} start" ), ifvarclass => "start_process_${index}"; "any" usebundle => rudder_common_reports_generic("ServicesManagement", "service_stop_${service[${index}][canon_name]}", "${service[${index}][uuid]}", "Process", "${service[${index}][name]}", "Service ${service[${index}][name]} stop" ), ifvarclass => "stop_process_${index}"; any:: "any" usebundle => rudder_common_report("ServicesManagement", "result_na", "${service[${index}][uuid]}", "Advanced options", "${service[${index}][name]}", "The process range is not to be checked for service ${service[${index}][name]}"), ifvarclass => "!check_process_range_${index}"; # The number of process range is not checked on windows !windows:: "any" usebundle => rudder_common_report("ServicesManagement", "result_error", "${service[${index}][uuid]}", "Advanced options", "${service[${index}][name]}", "The process range for service ${service[${index}][name]} cannot to be checked, for the process name is not set"), ifvarclass => "check_process_range_${index}.!defined_process_name_${index}"; "any" usebundle => rudder_common_report("ServicesManagement", "result_success", "${service[${index}][uuid]}", "Advanced options", "${service[${index}][name]}", "The process range for service ${service[${index}][name]} is correct"), ifvarclass => concat("check_process_range_${index}", ".", "defined_process_name_${index}", ".!", canonify("${service[${index}][canon_name]}_out_of_range")); "any" usebundle => rudder_common_report("ServicesManagement", "result_repaired", "${service[${index}][uuid]}", "Advanced options", "${service[${index}][name]}", "The process range for service ${service[${index}][name]} was not correct, but was repaired"), ifvarclass => concat("check_process_range_${index}", ".", "defined_process_name_${index}", ".", canonify("${service[${index}][canon_name]}_out_of_range"), ".", canonify("service_restart_${service[${index}][name]}_repaired")); "any" usebundle => rudder_common_report("ServicesManagement", "result_error", "${service[${index}][uuid]}", "Advanced options", "${service[${index}][name]}", "The process range for service ${service[${index}][name]} was not correct, but was repaired"), ifvarclass => concat("check_process_range_${index}", ".", "defined_process_name_${index}", ".", canonify("${service[${index}][canon_name]}_out_of_range"), ".", canonify("service_restart_${service[${index}][name]}_not_ok")); windows:: "any" usebundle => rudder_common_report("ServicesManagement", "result_na", "${service[${index}][uuid]}", "Advanced options", "${service[${index}][name]}", "Checking the number of processes within a range is not implemened on Windows"), ifvarclass => "check_process_range_${index}"; # Service boot starting parameters any:: "any" usebundle => rudder_common_report("ServicesManagement", "result_na", "${service[${index}][uuid]}", "Service starting parameters", "${service[${index}][name]}", "${service[${index}][name]} starting parameters check not required"), ifvarclass => "!bootstart_process_${index}.!bootstart_prevent_process_${index}"; "any" usebundle => rudder_common_report_generic("ServicesManagement", "service_ensure_started_at_boot_${service[${index}][name]}", "${service[${index}][uuid]}", "Service starting parameters", "${service[${index}][name]}", "The ${service[${index}][name]} boot starting configuration"), ifvarclass => canonify("bootstart_process_${index}"); "any" usebundle => rudder_common_report_generic("ServicesManagement", "service_ensure_stopped_${service[${index}][name]}", "${service[${index}][uuid]}", "Service starting parameters", "${service[${index}][name]}", "The ${service[${index}][name]} boot starting configuration"), ifvarclass => canonify("bootstart_prevent_process_${index}"); processes: !windows:: # check the service status "${service[${index}][process]}" comment => "Check the process status", restart_class => "process_${index}_restart", classes => kept_if_else("service_${index}_running", "service_${index}_anomaly", "service_${index}_error"), ifvarclass => "defined_process_name_${index}.(start_process_${index}|(stop_process_${index}.graceful_stop_process_${index}))"; # enforce that the process is stopped not so gracefully "${service[${index}][process]}" comment => "Stop not so gracefully the process", signals => { "${service[${index}][killMethod]}" }, classes => kept_if_else("service_${index}_already_stopped", "service_${index}_stopped", "service_${index}_error"), ifvarclass => "defined_process_name_${index}.stop_process_${index}.(term_stop_process_${index}|kill_stop_process_${index})"; # check the range "${service[${index}][process]}" comment => "Check the range of process", process_count => check_range("${service[${index}][name]}", "${service[${index}][min_instance]}", "${service[${index}][max_instance]}"), ifvarclass => "defined_process_name_${index}.check_process_range_${index}"; }