diff --git a/README.md b/README.md index 1340b02..20b7eef 100644 --- a/README.md +++ b/README.md @@ -49,11 +49,11 @@ Create your own "check_mk.user.yml.j2" and override `checkmk_agent_win_config_sr | CheckMK Raw Edition Version | Role Version/Tag | | --------------------------- | ---------------- | +| 2.2.0p12 | 1.0.75 | | 2.2.0p11 | 1.0.74 | | 2.2.0p10 | 1.0.73 | | 2.2.0p9 | 1.0.72 | | 2.2.0p8 | 1.0.71 | -| 2.2.0p7 | 1.0.69 - 1.0.70 | ## Requirements @@ -158,7 +158,7 @@ Some of these may be seem redundant but are specified so future users can overri | checkmk_agent_sudo_src | Filename of the "sudoers.d" file template | `"99_cmkagent.j2"` | | checkmk_agent_sudo_validate | Command used to validate the "sudoers.d" file; %s will be filled in with `checkmk_agent_sudo_dest` | `'visudo -cf %s'` | | checkmk_agent_user | Login name of the CheckMK Agent user | `"cmkagent"` | -| checkmk_agent_version | Version of CheckMK Agent to install | `"2.2.0p11"` | +| checkmk_agent_version | Version of CheckMK Agent to install | `"2.2.0p12"` | | checkmk_agent_win_config_dest | Full pathname of configuration file | `"{{ checkmk_agent_win_data_folder }}check_mk.user.yml"` | | checkmk_agent_win_config_src | Filename of the configuration file template | `"check_mk.user.yml.j2"` | | checkmk_agent_win_data_folder | Full pathname of the CheckMK Agent data folder | `"C:\\ProgramData\\checkmk\\agent\\"` | diff --git a/defaults/main.yml b/defaults/main.yml index 9e12dd3..4ea593f 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -88,7 +88,7 @@ checkmk_agent_sudo_owner: "root" checkmk_agent_sudo_src: "99_cmkagent.j2" checkmk_agent_sudo_validate: 'visudo -cf %s' checkmk_agent_user: "cmkagent" -checkmk_agent_version: "2.2.0p11" +checkmk_agent_version: "2.2.0p12" checkmk_agent_win_config_dest: "{{ checkmk_agent_win_data_folder }}check_mk.user.yml" checkmk_agent_win_config_src: "check_mk.user.yml.j2" checkmk_agent_win_data_folder: "C:\\ProgramData\\checkmk\\agent\\" diff --git a/files/check_mk_agent.msi b/files/check_mk_agent.msi index d1c52fb..9aa6dd5 100644 Binary files a/files/check_mk_agent.msi and b/files/check_mk_agent.msi differ diff --git a/templates/check_mk_agent.linux.j2 b/templates/check_mk_agent.linux.j2 index d1e5d84..0360bcd 100755 --- a/templates/check_mk_agent.linux.j2 +++ b/templates/check_mk_agent.linux.j2 @@ -1620,17 +1620,19 @@ run_cached() { fi # ideally, these should be independent parameters: - TIMEOUT=$((MAXAGE * 2)) + CREATION_TIMEOUT=$((MAXAGE * 2)) + OUTPUT_TIMEOUT=$((MAXAGE * 3)) [ -d "${MK_VARDIR}/cache" ] || mkdir -p "${MK_VARDIR}/cache" CACHEFILE="${MK_VARDIR}/cache/${NAME}.cache" + FAIL_REPORT_FILE="${SPOOLDIR}/${NAME}.cachefail" NOW="$(get_epoch)" MTIME="$(get_file_mtime "${CACHEFILE}" 2>/dev/null)" || MTIME=0 if ${MK_RUN_SYNC_PARTS}; then - if [ -s "${CACHEFILE}" ]; then - # Output the file (even if it is outdated) + if [ -s "${CACHEFILE}" ] && [ $((NOW - MTIME)) -le "${OUTPUT_TIMEOUT}" ]; then + # Output the file (if it is not too outdated) CACHE_INFO="cached(${MTIME},${MAXAGE})" # prefix or insert cache info, unless already present. # WATCH OUT: AIX does not allow us to pass this as a single '-e' option! @@ -1641,33 +1643,32 @@ run_cached() { fi fi - # Error information about plugin, if available. - # Output independent of cachefile existance - [ -s "${CACHEFILE}.fail" ] && cat "${CACHEFILE}.fail" fi if ${MK_RUN_ASYNC_PARTS}; then - # Kill the process if it is running too long (cache file not accessed for more than TIMEOUT seconds). + # Kill the process if it is running too long (cache file not accessed for more than CREATION_TIMEOUT seconds). # If killing succeeds, remove CACHFILE.new.PID. - # Remove CACHEFILE unconditionally. - # Write info about the timed out process and the kill attempt to CACHEFILE.fail. - # It will be reported to the Check_MK agent service later on, by the sync part. - # CACHEFILE.fail will be deleted as soon as the plugin/local check is functional again. + # Write info about the timed out process and the kill attempt to the SPOOLDIR. + # It will be reported to the server in the next (synchronous) agent execution. + # The file will be deleted as soon as the plugin/local check is functional again. + # Do not output the file here, it will interrupt the local and mrpe sections, as well as any other + # partially cached section. for cfile in "${CACHEFILE}.new."*; do [ -e "${cfile}" ] || break # no match - if [ $((NOW - $(get_file_atime "${cfile}"))) -ge "${TIMEOUT}" ]; then + TRYING_SINCE="$(get_file_atime "${cfile}")" + [ -n "${TRYING_SINCE}" ] || break # race condition: file vanished + if [ $((NOW - TRYING_SINCE)) -ge "${CREATION_TIMEOUT}" ]; then { - echo "<<>>" + printf "<<>>\n" pid="${cfile##*.new.}" - printf "timeout|%s|%s|%s\n" "${NAME}" "${TIMEOUT}" "${pid}" + printf "timeout|%s|%s|%s\n" "${NAME}" "${CREATION_TIMEOUT}" "${pid}" kill -9 "${pid}" >/dev/null 2>&1 && sleep 2 # TODO: what about child processes? if [ -n "$(ps -o args= -p "${pid}")" ]; then - printf "killfailed|%s|%s|%s\n" "${NAME}" "${TIMEOUT}" "${pid}" + printf "killfailed|%s|%s|%s\n" "${NAME}" "${CREATION_TIMEOUT}" "${pid}" else rm -f "${cfile}" fi - rm -f "${CACHEFILE}" - } >"${CACHEFILE}".fail 2>&1 + } >"${FAIL_REPORT_FILE}" 2>&1 fi done @@ -1685,13 +1686,13 @@ run_cached() { cat </dev/null 2>&1 & eval '${MK_DEFINE_LOG_SECTION_TIME}' exec > "${CACHEFILE}.new.\$\$" || exit 1 -$* && mv -f "${CACHEFILE}.new.\$\$" "${CACHEFILE}" && rm -f "${CACHEFILE}.fail" || rm -f "${CACHEFILE}" "${CACHEFILE}.new.\$\$" +$* && mv -f "${CACHEFILE}.new.\$\$" "${CACHEFILE}" && rm -f "${FAIL_REPORT_FILE}" || rm -f "${CACHEFILE}.new.\$\$" HERE fi fi - unset NAME MAXAGE TIMEOUT REFRESH_INTERVAL CACHEFILE NOW MTIME CACHE_INFO + unset NAME MAXAGE CREATION_TIMEOUT REFRESH_INTERVAL CACHEFILE NOW MTIME CACHE_INFO TRYING_SINCE OUTPUT_TIMEOUT } run_local_checks() { diff --git a/templates/mk_postgres.py.j2 b/templates/mk_postgres.py.j2 index 1fc3c6b..39dc9dd 100644 --- a/templates/mk_postgres.py.j2 +++ b/templates/mk_postgres.py.j2 @@ -14,9 +14,8 @@ Example for postgres.cfg file: -----postgres.cfg----------------------------------------- DBUSER=postgres -INSTANCE=/home/postgres/db1.env:USER_NAME:/PATH/TO/.pgpass -INSTANCE=/home/postgres/db2.env:USER_NAME:/PATH/TO/.pgpass -INSTANCE=... +INSTANCE=/home/postgres/db1.env:USER_NAME:/PATH/TO/.pgpass: +INSTANCE=/home/postgres/db2.env:USER_NAME:/PATH/TO/.pgpass: ---------------------------------------------------------- """ @@ -1199,6 +1198,18 @@ def parse_env_file(env_file): return pg_database, pg_port, pg_version +def _parse_INSTANCE_value(value, config_separator): + # type: (str, str) -> tuple[str, str, str, str] + keys = value.split(config_separator) + if len(keys) == 3: + # Old format (deprecated in Werk 16016), but we don't force updates unless there is + # a substantial benefit. + keys = keys + [""] + env_file, pg_user, pg_passfile, instance_name = keys + env_file = env_file.strip() + return env_file, pg_user, pg_passfile, instance_name or env_file.split(os.sep)[-1].split(".")[0] + + def parse_postgres_cfg(postgres_cfg, config_separator): # type: (List[str], str) -> Tuple[str, List[Dict[str, Optional[str]]]] """ @@ -1215,13 +1226,9 @@ def parse_postgres_cfg(postgres_cfg, config_separator): if key == "DBUSER": dbuser = value.rstrip() if key == "INSTANCE": - env_file, pg_user, pg_passfile, instance_name = value.split(config_separator) - env_file = env_file.strip() - instance_name = instance_name or env_file.split(os.sep)[-1].split(".")[0] - if not instance_name: - raise ValueError( - "Instance name can not be inferred from .env file, instance name should be specified explicitly" - ) + env_file, pg_user, pg_passfile, instance_name = _parse_INSTANCE_value( + value, config_separator + ) pg_database, pg_port, pg_version = parse_env_file(env_file) instances.append( {