Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MON 74111 allow to bypass notif inhibition for recovery notif #1349

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions engine/doc/engine-doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,30 @@ The main main job is done by whitelist class, it parses file and compares final
This class is a singleton witch is replace by another instance each time conf is reloaded.

Checkable class inherited by service and host classes keeps the last result of whitelist's check in cache in order to reduce CPU whitelist usage.

## Extended configuration
Users can pass an additional configuration file to engine. Gorgone is not aware of this file, so users can override centengine.cfg configuration.
Each entry found in additional json configuration file overrides its twin in `centengine.cfg`.

### examples of command line
```sh
/usr/sbin/centengine --config-file=/tmp/centengine_extend.json /etc/centreon-engine/centengine.cfg

/usr/sbin/centengine --c /tmp/file1.json --c /tmp/file2.json /etc/centreon-engine/centengine.cfg
```

In the second case, values of file1.json will override values of centengine.cfg and values of file2.json will override values of file1.json

### file format
```json
{
"send_recovery_notifications_anyways": true
}
```

### implementation detail
In `state.cc` all setters have two methods:
* `apply_from_cfg`
* `apply_from_json`.

On configuration update, we first parse the `centengine.cfg` and all the `*.cfg` files, and then we parse additional configuration files.
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ template <class file_path_iterator>
void extended_conf::load_all(file_path_iterator begin, file_path_iterator end) {
_confs.clear();
for (; begin != end; ++begin) {
_confs.emplace_back(std::make_unique<extended_conf>(*begin));
try {
_confs.emplace_back(std::make_unique<extended_conf>(*begin));
} catch (const std::exception&) {
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions engine/inc/com/centreon/engine/configuration/state.hh
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,8 @@ class state {
void use_timezone(std::string const& value);
bool use_true_regexp_matching() const noexcept;
void use_true_regexp_matching(bool value);
bool use_send_recovery_notifications_anyways() const;
void use_send_recovery_notifications_anyways(bool value);

using setter_map =
absl::flat_hash_map<std::string_view, std::unique_ptr<setter_base>>;
Expand Down Expand Up @@ -650,6 +652,7 @@ class state {
std::string _log_level_runtime;
std::string _use_timezone;
bool _use_true_regexp_matching;
bool _send_recovery_notifications_anyways;
};

} // namespace com::centreon::engine::configuration
Expand Down
2 changes: 2 additions & 0 deletions engine/src/configuration/applier/state.cc
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,8 @@ void applier::state::_apply(configuration::state const& new_cfg) {
config->log_level_comments(new_cfg.log_level_comments());
config->log_level_macros(new_cfg.log_level_macros());
config->use_true_regexp_matching(new_cfg.use_true_regexp_matching());
config->use_send_recovery_notifications_anyways(
new_cfg.use_send_recovery_notifications_anyways());
config->user(new_cfg.user());

// Set this variable just the first time.
Expand Down
2 changes: 2 additions & 0 deletions engine/src/configuration/extended_conf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ std::list<std::unique_ptr<extended_conf>> extended_conf::_confs;
extended_conf::extended_conf(const std::string& path) : _path(path) {
if (::stat(_path.c_str(), &_file_info)) {
SPDLOG_LOGGER_ERROR(log_v2::config(), "can't access to {}", _path);
throw exceptions::msg_fmt("can't access to {}", _path);
}
try {
_content = common::rapidjson_helper::read_from_file(_path);
Expand All @@ -42,6 +43,7 @@ extended_conf::extended_conf(const std::string& path) : _path(path) {
log_v2::config(),
"extended_conf::extended_conf : fail to read json content from {}: {}",
_path, e.what());
throw;
}
}

Expand Down
42 changes: 40 additions & 2 deletions engine/src/configuration/state.cc
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,8 @@ void state::_init_setter() {
SETTER(bool, use_true_regexp_matching, "use_true_regexp_matching");
SETTER(std::string const&, _set_comment_file, "xcddefault_comment_file");
SETTER(std::string const&, _set_downtime_file, "xdddefault_downtime_file");
SETTER(bool, use_send_recovery_notifications_anyways,
"send_recovery_notifications_anyways");
}

// Default values.
Expand Down Expand Up @@ -581,7 +583,8 @@ state::state()
_log_level_process(default_log_level_process),
_log_level_runtime(default_log_level_runtime),
_use_timezone(default_use_timezone),
_use_true_regexp_matching(default_use_true_regexp_matching) {
_use_true_regexp_matching(default_use_true_regexp_matching),
_send_recovery_notifications_anyways(false) {
static absl::once_flag _init_call_once;
absl::call_once(_init_call_once, _init_setter);
}
Expand Down Expand Up @@ -764,6 +767,8 @@ state& state::operator=(state const& right) {
_log_level_runtime = right._log_level_runtime;
_use_timezone = right._use_timezone;
_use_true_regexp_matching = right._use_true_regexp_matching;
_send_recovery_notifications_anyways =
right._send_recovery_notifications_anyways;
}
return *this;
}
Expand Down Expand Up @@ -928,7 +933,9 @@ bool state::operator==(state const& right) const noexcept {
_log_level_process == right._log_level_process &&
_log_level_runtime == right._log_level_runtime &&
_use_timezone == right._use_timezone &&
_use_true_regexp_matching == right._use_true_regexp_matching);
_use_true_regexp_matching == right._use_true_regexp_matching &&
_send_recovery_notifications_anyways ==
right._send_recovery_notifications_anyways);
}

/**
Expand Down Expand Up @@ -4815,6 +4822,37 @@ void state::enable_macros_filter(bool value) {
_enable_macros_filter = value;
}

/**
* @brief Get _send_recovery_notifications_anyways
*
* Having a resource that has entered a non-OK state during a notification
* period and goes back to an OK state out of a notification period, then only
* if send_recovery_notifications_anyways is set to 1, the recovery notification
* must be sent to all users that have previously received the alert
* notification.
*
* @return true
* @return false
*/
bool state::use_send_recovery_notifications_anyways() const {
return _send_recovery_notifications_anyways;
}

/**
* @brief
*
* Having a resource that has entered a non-OK state during a notification
* period and goes back to an OK state out of a notification period, then only
* if send_recovery_notifications_anyways is set to 1, the recovery notification
* must be sent to all users that have previously received the alert
* notification.
*
* @param value true if have to nitify anyway
*/
void state::use_send_recovery_notifications_anyways(bool value) {
_send_recovery_notifications_anyways = value;
}

/**
* @brief modify state according json passed in parameter
*
Expand Down
4 changes: 2 additions & 2 deletions engine/src/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ int main(int argc, char* argv[]) {
bool display_license(false);
bool error(false);
bool diagnose(false);
std::set<std::string> extended_conf_file;
std::vector<std::string> extended_conf_file;

// Process all command line arguments.
int c;
Expand Down Expand Up @@ -161,7 +161,7 @@ int main(int argc, char* argv[]) {
break;
case 'c':
if (optarg)
extended_conf_file.insert(optarg);
extended_conf_file.emplace_back(optarg);
break;
default:
error = true;
Expand Down
27 changes: 19 additions & 8 deletions engine/src/notifier.cc
Original file line number Diff line number Diff line change
Expand Up @@ -458,16 +458,27 @@ bool notifier::_is_notification_viable_recovery(reason_type type
std::time_t now;
std::time(&now);

// if use_send_recovery_notifications_anyways flag is set, we don't take
// timeperiod into account for recovery
if (!check_time_against_period_for_notif(now, tp)) {
engine_logger(dbg_notifications, more)
<< "This notifier shouldn't have notifications sent out "
"at this time.";
SPDLOG_LOGGER_DEBUG(log_v2::notifications(),
"This notifier shouldn't have notifications sent out "
"at this time.");
retval = false;
send_later = true;
if (config->use_send_recovery_notifications_anyways()) {
SPDLOG_LOGGER_DEBUG(log_v2::notifications(),
"send_recovery_notifications_anyways flag enabled, "
"recovery notification is viable even if we are "
"out of timeperiod at this time.");
} else {
engine_logger(dbg_notifications, more)
<< "This notifier shouldn't have notifications sent out "
"at this time.";
SPDLOG_LOGGER_DEBUG(
log_v2::notifications(),
"This notifier shouldn't have notifications sent out "
"at this time.");
retval = false;
send_later = true;
}
}

/* if this notifier is currently in a scheduled downtime period, don't send
* the notification */
else if (is_in_downtime()) {
Expand Down
12 changes: 2 additions & 10 deletions tests/engine/extended_conf.robot
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,7 @@ EXT_CONF1
Ctn Config Broker module ${1}
Create File /tmp/centengine_extend.json {"log_level_checks": "trace", "log_level_comments": "debug"}
${start} Get Current Date
Start Process
... /usr/sbin/centengine
... --config-file\=/tmp/centengine_extend.json
... ${EtcRoot}/centreon-engine/config0/centengine.cfg
... alias=e0
Ctn Start Engine With Extend Conf
Ctn Wait For Engine To Be Ready ${start} ${1}
${level} Ctn Get Engine Log Level 50001 checks
Should Be Equal ${level} trace log_level_checks must be the extended conf value
Expand All @@ -38,11 +34,7 @@ EXT_CONF2
Ctn Config Broker module ${1}
Create File /tmp/centengine_extend.json {}
${start} Get Current Date
Start Process
... /usr/sbin/centengine
... --config-file\=/tmp/centengine_extend.json
... ${EtcRoot}/centreon-engine/config0/centengine.cfg
... alias=e0
Ctn Start Engine With Extend Conf
Ctn Wait For Engine To Be Ready ${start} ${1}
Create File /tmp/centengine_extend.json {"log_level_checks": "trace", "log_level_comments": "debug"}

Expand Down
32 changes: 32 additions & 0 deletions tests/resources/Engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import engine_pb2
import engine_pb2_grpc
from array import array
from dateutil import parser
import datetime
from os import makedirs, chmod
from os.path import exists, dirname
from robot.api import logger
Expand Down Expand Up @@ -3180,3 +3182,33 @@ def ctn_get_engine_log_level(port, log, timeout=TIMEOUT):

except:
logger.console("gRPC server not ready")



def ctn_create_single_day_time_period(idx: int, time_period_name: str, date, minute_duration: int):
"""
Create a single day time period with a single time range from date to date + minute_duration
Args
idx: poller index
time_period_name: must be unique
date: time range start
minute_duration: time range length in minutes
"""
try:
my_date = parser.parse(date)
except:
my_date = datetime.fromtimestamp(date)

filename = f"{ETC_ROOT}/centreon-engine/config{idx}/timeperiods.cfg"

begin = my_date.time()
end = my_date + datetime.timedelta(minutes=minute_duration)

with open(filename, "a+") as f:
f.write(f"""
define timeperiod {{
timeperiod_name {time_period_name}
alias {time_period_name}
{my_date.date().isoformat()} {begin.strftime("%H:%M")}-{end.time().strftime("%H:%M")}
}}
""")
21 changes: 21 additions & 0 deletions tests/resources/resources.robot
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,27 @@ Ctn Start Engine
Start Process /usr/sbin/centengine ${conf} alias=${alias}
END

Ctn Start Engine With Extend Conf
${count} Ctn Get Engines Count
FOR ${idx} IN RANGE 0 ${count}
${alias} Catenate SEPARATOR= e ${idx}
${conf} Catenate SEPARATOR= ${EtcRoot} /centreon-engine/config ${idx} /centengine.cfg
${log} Catenate SEPARATOR= ${VarRoot} /log/centreon-engine/config ${idx}
${lib} Catenate SEPARATOR= ${VarRoot} /lib/centreon-engine/config ${idx}
Create Directory ${log}
Create Directory ${lib}
TRY
Remove File ${lib}/rw/centengine.cmd
EXCEPT
Log can't remove ${lib}/rw/centengine.cmd don't worry
END
Start Process
... /usr/sbin/centengine
... --config-file\=/tmp/centengine_extend.json
... ${conf}
... alias=${alias}
END

Ctn Restart Engine
Ctn Stop Engine
Ctn Start Engine
Expand Down
Loading