diff --git a/.gitignore b/.gitignore index 9bb05dfd5f2..d2a12d53eb6 100644 --- a/.gitignore +++ b/.gitignore @@ -47,6 +47,7 @@ test-coverage test/python/*.crt test/python/*.key ut +tests/failed ### apps/ build/* diff --git a/bbdo/CMakeLists.txt b/bbdo/CMakeLists.txt index f61c9d6b855..332722a5c79 100644 --- a/bbdo/CMakeLists.txt +++ b/bbdo/CMakeLists.txt @@ -106,18 +106,6 @@ macro(get_protobuf_files name) "${CMAKE_SOURCE_DIR}/bbdo/${name}.pb.h") endmacro() -macro(get_protobuf_accessor name) - set(proto_file "${name}.proto") - set(full_proto_file "${CMAKE_SOURCE_DIR}/bbdo/${name}.proto") - add_custom_command(OUTPUT "${CMAKE_SOURCE_DIR}/bbdo/${name}_accessor.hh" - DEPENDS ${full_proto_file} - COMMENT "Generating accessor to protobuf message ${proto_file}" - COMMAND python3 - ARGS ${full_proto_file} - VERBATIM - ) -endmacro() - include_directories("${CMAKE_SOURCE_DIR}/broker/core/inc") add_library( diff --git a/bbdo/events.hh b/bbdo/events.hh index 025dd3ae355..3dc1d880008 100644 --- a/bbdo/events.hh +++ b/bbdo/events.hh @@ -128,9 +128,9 @@ enum data_element { de_pb_severity = 33, de_pb_tag = 34, de_pb_comment = 35, + de_pb_downtime = 36, de_pb_custom_variable = 37, de_pb_custom_variable_status = 38, - }; } // namespace neb namespace storage { diff --git a/bbdo/neb_proto.proto b/bbdo/neb_proto.proto index b89ce23e8c3..f8690a29313 100644 --- a/bbdo/neb_proto.proto +++ b/bbdo/neb_proto.proto @@ -24,61 +24,91 @@ package com.centreon.broker; message Comment { - BBDOHeader header = 1; + BBDOHeader header = 1; - enum Src { - INTERNAL = 0; - EXTERNAL = 1; - } + enum Src { + INTERNAL = 0; + EXTERNAL = 1; + } - enum Type { - NO_TYPE = 0; - HOST = 1; - SERVICE = 2; - } + enum Type { + NO_TYPE = 0; + HOST = 1; + SERVICE = 2; + } - enum EntryType { - NO_ENTRY_TYPE = 0; - USER = 1; - DOWNTIME = 2; - FLAPPING = 3; - ACKNOWLEDGMENT = 4; - } + enum EntryType { + NO_ENTRY_TYPE = 0; + USER = 1; + DOWNTIME = 2; + FLAPPING = 3; + ACKNOWLEDGMENT = 4; + } - string author = 2; - Type type = 3; - string data = 4; - uint64 deletion_time = 5; - uint64 entry_time = 6; - EntryType entry_type = 7; - uint64 expire_time = 8; - bool expires = 9; - uint64 host_id = 10; - uint64 internal_id = 11; - bool persistent = 12; - uint64 instance_id = 13; - uint64 service_id = 14; - Src source = 15; - + string author = 2; + Type type = 3; + string data = 4; + uint64 deletion_time = 5; + uint64 entry_time = 6; + EntryType entry_type = 7; + uint64 expire_time = 8; + bool expires = 9; + uint64 host_id = 10; + uint64 internal_id = 11; + bool persistent = 12; + uint64 instance_id = 13; + uint64 service_id = 14; + Src source = 15; +} + +/** + * @brief A downtime is applied on a resource when we don't want notifications + * concerning bad states on this resource. + */ +message Downtime { + enum DowntimeType { + NOT_USED = 0; + SERVICE = 1; + HOST = 2; + ANY = 3; + }; + uint64 id = 1; + uint64 instance_id = 2; + uint64 host_id = 3; + uint64 service_id = 4; + string author = 5; + string comment_data = 6; + DowntimeType type = 7; + uint32 duration = 8; + uint64 triggered_by = 9; + int64 entry_time = 10; + uint64 actual_start_time = 11; + uint64 actual_end_time = 12; + uint64 start_time = 13; + uint64 deletion_time = 14; + uint64 end_time = 15; + bool started = 16; + bool cancelled = 17; + bool fixed = 18; } message CustomVariable { - enum VarType { - HOST = 0; - SERVICE = 1; - } + enum VarType { + HOST = 0; + SERVICE = 1; + } - BBDOHeader header = 1; - uint64 host_id = 2; - uint64 service_id = 3; - bool modified = 4; - string name = 5; - uint64 update_time = 6; - string value = 7; - string default_value = 8; - bool enabled = 9; - bool password = 10; - VarType var_type = 11; + BBDOHeader header = 1; + uint64 host_id = 2; + uint64 service_id = 3; + bool modified = 4; + string name = 5; + uint64 update_time = 6; + string value = 7; + string default_value = 8; + bool enabled = 9; + bool password = 10; + VarType var_type = 11; } diff --git a/broker/bam/inc/com/centreon/broker/bam/ba.hh b/broker/bam/inc/com/centreon/broker/bam/ba.hh index 0ba23fe9f62..cc66eccd6b7 100644 --- a/broker/bam/inc/com/centreon/broker/bam/ba.hh +++ b/broker/bam/inc/com/centreon/broker/bam/ba.hh @@ -145,6 +145,8 @@ class ba : public computable, public service_listener { void visit(io::stream* visitor); void service_update(std::shared_ptr const& dt, io::stream* visitor) override; + void service_update(std::shared_ptr const& dt, + io::stream* visitor) override; void save_inherited_downtime(persistent_cache& cache) const; void set_inherited_downtime(inherited_downtime const& dwn); void set_level_critical(double level); diff --git a/broker/bam/inc/com/centreon/broker/bam/kpi_service.hh b/broker/bam/inc/com/centreon/broker/bam/kpi_service.hh index 38f8434390e..284e4e23b5a 100644 --- a/broker/bam/inc/com/centreon/broker/bam/kpi_service.hh +++ b/broker/bam/inc/com/centreon/broker/bam/kpi_service.hh @@ -1,5 +1,5 @@ /* -** Copyright 2014-2015, 2021 Centreon +** Copyright 2014-2015, 2021-2022 Centreon ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -80,13 +80,15 @@ class kpi_service : public service_listener, public kpi { bool in_downtime() const; bool is_acknowledged() const; void service_update(std::shared_ptr const& status, - io::stream* visitor = nullptr); + io::stream* visitor = nullptr) override; void service_update(const std::shared_ptr& status, - io::stream* visitor = nullptr); + io::stream* visitor = nullptr) override; void service_update(std::shared_ptr const& ack, - io::stream* visitor = nullptr); + io::stream* visitor = nullptr) override; void service_update(std::shared_ptr const& dt, - io::stream* visitor = nullptr); + io::stream* visitor = nullptr) override; + void service_update(const std::shared_ptr& dt, + io::stream* visitor = nullptr) override; void set_acknowledged(bool acknowledged); void set_downtimed(bool downtimed); void set_impact_critical(double impact); diff --git a/broker/bam/inc/com/centreon/broker/bam/service_book.hh b/broker/bam/inc/com/centreon/broker/bam/service_book.hh index faa735d3447..01eeaf769bd 100644 --- a/broker/bam/inc/com/centreon/broker/bam/service_book.hh +++ b/broker/bam/inc/com/centreon/broker/bam/service_book.hh @@ -60,6 +60,8 @@ class service_book { io::stream* visitor = nullptr); void update(const std::shared_ptr& t, io::stream* visitor = nullptr); + void update(const std::shared_ptr& t, + io::stream* visitor = nullptr); void update(const std::shared_ptr& t, io::stream* visitor = nullptr); void update(const std::shared_ptr& t, diff --git a/broker/bam/inc/com/centreon/broker/bam/service_listener.hh b/broker/bam/inc/com/centreon/broker/bam/service_listener.hh index 64f8450eaf3..c691f66a243 100644 --- a/broker/bam/inc/com/centreon/broker/bam/service_listener.hh +++ b/broker/bam/inc/com/centreon/broker/bam/service_listener.hh @@ -59,6 +59,8 @@ class service_listener { io::stream* visitor = nullptr); virtual void service_update(std::shared_ptr const& dt, io::stream* visitor = nullptr); + virtual void service_update(const std::shared_ptr& dt, + io::stream* visitor = nullptr); }; } // namespace bam diff --git a/broker/bam/src/ba.cc b/broker/bam/src/ba.cc index 410b17dd8ba..8b4d48aecf7 100644 --- a/broker/bam/src/ba.cc +++ b/broker/bam/src/ba.cc @@ -39,6 +39,10 @@ double ba::_normalize(double d) { return d; }; +static bool time_is_undefined(uint64_t t) { + return t == 0 || t == static_cast(-1); +} + /** * Constructor. * @@ -375,6 +379,42 @@ void ba::service_update(const std::shared_ptr& dt, _id, _name, dt->host_id, dt->service_id, _host_id, _service_id); } +/** + * @brief Notify BA of a downtime (protobuf) + * + * Used to watch for downtime. + * + * @param dt Downtime of the service. + * @param visitor Visitor that will receive events. + */ +void ba::service_update(const std::shared_ptr& dt, + io::stream* visitor) { + (void)visitor; + auto& downtime = dt->obj(); + assert(downtime.host_id() == _host_id && + downtime.service_id() == _service_id); + + // Log message. + log_v2::bam()->debug( + "BAM: BA {} '{}' is getting notified of a downtime (pb) on its service " + "({}, {})", + _id, _name, _host_id, _service_id); + + // Check if there was a change. + bool in_downtime(downtime.started() && + time_is_undefined(downtime.actual_end_time())); + if (_in_downtime != in_downtime) { + log_v2::bam()->trace("ba: service_update downtime: {}", _in_downtime); + _in_downtime = in_downtime; + + // Generate status event. + visit(visitor); + + // Propagate change. + propagate_update(visitor); + } +} + /** * Save the inherited downtime to the cache. * diff --git a/broker/bam/src/kpi.cc b/broker/bam/src/kpi.cc index 529efbf8fef..5cbd36eb951 100644 --- a/broker/bam/src/kpi.cc +++ b/broker/bam/src/kpi.cc @@ -19,6 +19,7 @@ #include "com/centreon/broker/bam/kpi.hh" #include "com/centreon/broker/bam/ba.hh" +#include "com/centreon/broker/log_v2.hh" using namespace com::centreon::broker; using namespace com::centreon::broker::bam; @@ -63,6 +64,7 @@ timestamp kpi::get_last_state_change() const { * @param[in] e The kpi event. */ void kpi::set_initial_event(const kpi_event& e) { + log_v2::bam()->trace("bam: kpi::set_initial_event"); if (!_event) { _event = std::make_shared(e); impact_values impacts; @@ -74,13 +76,13 @@ void kpi::set_initial_event(const kpi_event& e) { if (std::abs(new_impact_level - _event->impact_level) >= eps && _event->impact_level != -1) { time_t now = ::time(nullptr); - std::shared_ptr new_event = std::make_shared(e); + auto new_event = std::make_shared(e); new_event->end_time = now; _initial_events.push_back(new_event); new_event = std::make_shared(e); new_event->start_time = now; _initial_events.push_back(new_event); - _event = new_event; + _event = std::move(new_event); } else _initial_events.push_back(_event); ; @@ -99,8 +101,8 @@ void kpi::commit_initial_events(io::stream* visitor) { if (visitor) { for (std::vector >::const_iterator - it(_initial_events.begin()), - end(_initial_events.end()); + it = _initial_events.begin(), + end = _initial_events.end(); it != end; ++it) visitor->write(std::make_shared(**it)); } diff --git a/broker/bam/src/kpi_service.cc b/broker/bam/src/kpi_service.cc index 8d0165c36ae..8effab770de 100644 --- a/broker/bam/src/kpi_service.cc +++ b/broker/bam/src/kpi_service.cc @@ -32,6 +32,10 @@ using namespace com::centreon::exceptions; using namespace com::centreon::broker; using namespace com::centreon::broker::bam; +static bool time_is_undefined(uint64_t t) { + return t == 0 || t == static_cast(-1); +} + /** * Default constructor. */ @@ -272,24 +276,22 @@ void kpi_service::service_update( * @param[out] visitor Object that will receive events. */ void kpi_service::service_update( - std::shared_ptr const& ack, + const std::shared_ptr& ack, io::stream* visitor) { - if (ack && ack->host_id == _host_id && ack->service_id == _service_id) { - // Log message. - log_v2::bam()->debug( - "BAM: KPI {} is getting an acknowledgement event for service ({}, {}) " - "entry_time {} ; deletion_time {}", - _id, _host_id, _service_id, ack->entry_time, ack->deletion_time); + // Log message. + log_v2::bam()->debug( + "BAM: KPI {} is getting an acknowledgement event for service ({}, {}) " + "entry_time {} ; deletion_time {}", + _id, _host_id, _service_id, ack->entry_time, ack->deletion_time); - // Update information. - _acknowledged = ack->deletion_time.is_null(); + // Update information. + _acknowledged = ack->deletion_time.is_null(); - // Generate status event. - visit(visitor); + // Generate status event. + visit(visitor); - // Propagate change. - propagate_update(visitor); - } + // Propagate change. + propagate_update(visitor); } /** @@ -342,6 +344,59 @@ void kpi_service::service_update(const std::shared_ptr& dt, propagate_update(visitor); } +/** + * Service got a downtime (protobuf). + * + * @param[in] dt + * @param[out] visitor Object that will receive events. + */ +void kpi_service::service_update(const std::shared_ptr& dt, + io::stream* visitor) { + auto& downtime = dt->obj(); + // Update information. + bool downtimed = + downtime.started() && time_is_undefined(downtime.actual_end_time()); + if (!_downtimed && downtimed) + _downtimed = true; + + if (_downtime_ids.contains(downtime.id()) && + time_is_undefined(downtime.deletion_time())) { + log_v2::bam()->trace("Downtime {} already handled in this kpi service", + downtime.id()); + return; + } + + if (downtimed) { + log_v2::bam()->trace("adding in kpi service the impacting downtime {}", + downtime.id()); + _downtime_ids.insert(downtime.id()); + } else { + log_v2::bam()->trace("removing from kpi service the impacting downtime {}", + downtime.id()); + _downtime_ids.erase(downtime.id()); + _downtimed = !_downtime_ids.empty(); + } + + if (!_event || _event->in_downtime != _downtimed) { + _last_check = + _downtimed ? downtime.actual_start_time() : downtime.actual_end_time(); + log_v2::bam()->trace("kpi service {} update, last check set to {}", _id, + _last_check); + } + + // Log message. + log_v2::bam()->debug( + "BAM: KPI {} is getting notified of a downtime ({}) on its service ({}, " + "{}), in downtime: {} at {}", + _id, downtime.id(), _host_id, _service_id, _downtimed, _last_check); + + // Generate status event. + visit(visitor); + + // Propagate change. + propagate_update(visitor); +} + /** * Set service as acknowledged. * diff --git a/broker/bam/src/monitoring_stream.cc b/broker/bam/src/monitoring_stream.cc index be511e6561c..dd8232a67d8 100644 --- a/broker/bam/src/monitoring_stream.cc +++ b/broker/bam/src/monitoring_stream.cc @@ -36,6 +36,7 @@ #include "com/centreon/broker/neb/internal.hh" #include "com/centreon/broker/neb/service.hh" #include "com/centreon/broker/neb/service_status.hh" +#include "com/centreon/broker/pool.hh" #include "com/centreon/broker/timestamp.hh" #include "com/centreon/exceptions/msg_fmt.hh" @@ -259,6 +260,20 @@ int monitoring_stream::write(std::shared_ptr const& data) { _applier.book_service().update(dt, &ev_cache); ev_cache.commit_to(pblshr); } break; + case neb::pb_downtime::static_type(): { + std::shared_ptr dt( + std::static_pointer_cast(data)); + auto& downtime = dt->obj(); + log_v2::bam()->trace( + "BAM: processing downtime (pb) ({}) on service ({}, {}) started: {}, " + "stopped: {}", + downtime.id(), downtime.host_id(), downtime.service_id(), + downtime.started(), downtime.cancelled()); + multiplexing::publisher pblshr; + event_cache_visitor ev_cache; + _applier.book_service().update(dt, &ev_cache); + ev_cache.commit_to(pblshr); + } break; case bam::ba_status::static_type(): { ba_status* status(static_cast(data.get())); log_v2::bam()->trace( diff --git a/broker/bam/src/service_book.cc b/broker/bam/src/service_book.cc index d05c41d2e9b..df6c3b779a5 100644 --- a/broker/bam/src/service_book.cc +++ b/broker/bam/src/service_book.cc @@ -96,6 +96,24 @@ void service_book::update(const std::shared_ptr& t, } } +/** + * @brief Propagate events of type neb::pb_downtime to the concerned services + * and then to the corresponding kpi. + * + * @param t The event to handle. + * @param visitor The stream to write into. + */ +void service_book::update(const std::shared_ptr& t, + io::stream* visitor) { + auto& downtime = t->obj(); + std::pair range{_book.equal_range( + std::make_pair(downtime.host_id(), downtime.service_id()))}; + while (range.first != range.second) { + range.first->second->service_update(t, visitor); + ++range.first; + } +} + /** * @brief Propagate events of type neb::service_status to the concerned services * and then to the corresponding kpi. diff --git a/broker/bam/src/service_listener.cc b/broker/bam/src/service_listener.cc index 012eec4c47d..4bcdbdf0e64 100644 --- a/broker/bam/src/service_listener.cc +++ b/broker/bam/src/service_listener.cc @@ -114,3 +114,16 @@ void service_listener::service_update(std::shared_ptr const& dt, (void)dt; (void)visitor; } + +/** + * Notify of a downtime (protobuf). + * + * @param[in] dt Downtime. + * @param[out] visitor Visitor. + */ +void service_listener::service_update( + const std::shared_ptr& dt, + io::stream* visitor) { + (void)dt; + (void)visitor; +} diff --git a/broker/bam/test/ba/kpi_ba.cc b/broker/bam/test/ba/kpi_ba.cc index da10ee63af7..ebcca256e35 100644 --- a/broker/bam/test/ba/kpi_ba.cc +++ b/broker/bam/test/ba/kpi_ba.cc @@ -459,12 +459,13 @@ TEST_F(KpiBA, KpiBaDtPb) { kpis[0]->service_update(ss, _visitor.get()); /* Let's put a downtime on the service. */ - auto dt = std::make_shared(); - dt->host_id = 3; - dt->service_id = 1; - dt->entry_time = now + 12; - dt->actual_start_time = now + 12; - dt->was_started = true; + auto dt = std::make_shared(); + auto& dt_obj = dt->mut_obj(); + dt_obj.set_host_id(3); + dt_obj.set_service_id(1); + dt_obj.set_entry_time(now + 12); + dt_obj.set_actual_start_time(now + 12); + dt_obj.set_started(true); kpis[0]->service_update(dt, _visitor.get()); auto events = _visitor->queue(); @@ -688,25 +689,31 @@ TEST_F(KpiBA, KpiBaDtOffPb) { kpis[0]->service_update(ss, _visitor.get()); /* Let's put a downtime on the service. */ - auto dt = std::make_shared(); - dt->host_id = 3; - dt->service_id = 1; - dt->entry_time = now + 12; - dt->actual_start_time = now + 12; - dt->actual_end_time = -1; - dt->was_started = true; - kpis[0]->service_update(dt, _visitor.get()); + auto dt = std::make_shared(); + { + auto& dt_obj = dt->mut_obj(); + dt_obj.set_host_id(3); + dt_obj.set_service_id(1); + dt_obj.set_entry_time(now + 12); + dt_obj.set_actual_start_time(now + 12); + dt_obj.set_actual_end_time(-1); + dt_obj.set_started(true); + kpis[0]->service_update(dt, _visitor.get()); + } /* Let's remove the downtime from the service. */ - dt = std::make_shared(); - dt->host_id = 3; - dt->service_id = 1; - dt->entry_time = now + 12; - dt->actual_end_time = now + 20; - dt->deletion_time = now + 20; - dt->was_started = true; - dt->was_cancelled = true; - kpis[0]->service_update(dt, _visitor.get()); + dt = std::make_shared(); + { + auto& dt_obj = dt->mut_obj(); + dt_obj.set_host_id(3); + dt_obj.set_service_id(1); + dt_obj.set_entry_time(now + 12); + dt_obj.set_actual_end_time(now + 20); + dt_obj.set_deletion_time(now + 20); + dt_obj.set_started(true); + dt_obj.set_cancelled(true); + kpis[0]->service_update(dt, _visitor.get()); + } ASSERT_TRUE(!test_ba->get_in_downtime()); auto events = _visitor->queue(); @@ -907,26 +914,32 @@ TEST_F(KpiBA, KpiBaOkDtOffPb) { ss->mut_obj().set_service_id(1); /* Let's put a downtime on the service. */ - auto dt = std::make_shared(); - dt->host_id = 3; - dt->service_id = 1; - dt->entry_time = now + 12; - dt->actual_start_time = now + 12; - dt->actual_end_time = -1; - dt->was_started = true; - kpis[0]->service_update(dt, _visitor.get()); + auto dt = std::make_shared(); + { + auto& dt_obj = dt->mut_obj(); + dt_obj.set_host_id(3); + dt_obj.set_service_id(1); + dt_obj.set_entry_time(now + 12); + dt_obj.set_actual_start_time(now + 12); + dt_obj.set_actual_end_time(-1); + dt_obj.set_started(true); + kpis[0]->service_update(dt, _visitor.get()); + } ASSERT_FALSE(test_ba->get_in_downtime()); /* Let's remove the downtime from the service. */ - dt = std::make_shared(); - dt->host_id = 3; - dt->service_id = 1; - dt->entry_time = now + 12; - dt->actual_end_time = now + 20; - dt->deletion_time = now + 20; - dt->was_started = true; - dt->was_cancelled = true; - kpis[0]->service_update(dt, _visitor.get()); + dt = std::make_shared(); + { + auto& dt_obj = dt->mut_obj(); + dt_obj.set_host_id(3); + dt_obj.set_service_id(1); + dt_obj.set_entry_time(now + 12); + dt_obj.set_actual_end_time(now + 20); + dt_obj.set_deletion_time(now + 20); + dt_obj.set_started(true); + dt_obj.set_cancelled(true); + kpis[0]->service_update(dt, _visitor.get()); + } ASSERT_FALSE(test_ba->get_in_downtime()); } diff --git a/broker/bam/test/ba/kpi_service.cc b/broker/bam/test/ba/kpi_service.cc index d85bc3596ad..4e690dc9aef 100644 --- a/broker/bam/test/ba/kpi_service.cc +++ b/broker/bam/test/ba/kpi_service.cc @@ -453,12 +453,7 @@ TEST_F(BamBA, KpiServiceRatioPercent) { test_ba->set_level_warning(75); std::vector> kpis; - std::stack results; - - results.push(2); - results.push(1); - results.push(0); - results.push(0); + std::stack results({2, 1, 0, 0}); for (int i = 0; i < 4; i++) { auto s = std::make_shared(i + 1, 1, i + 1, 1); @@ -499,12 +494,7 @@ TEST_F(BamBA, KpiServiceDtInheritAllCritical) { test_ba->set_downtime_behaviour(bam::configuration::ba::dt_inherit); std::vector> kpis; - std::stack results; - - results.push(true); - results.push(false); - results.push(false); - results.push(false); + std::stack results({true, false, false, false}); for (int i = 0; i < 4; i++) { auto s = std::make_shared(i + 1, 1, i + 1, 1); @@ -520,8 +510,8 @@ TEST_F(BamBA, KpiServiceDtInheritAllCritical) { // for the test to be correct. time_t now(time(nullptr)); - std::shared_ptr ss(new neb::service_status); - std::shared_ptr dt(new neb::downtime); + auto ss{std::make_shared()}; + auto dt{std::make_shared()}; ss->service_id = 1; for (size_t j = 0; j < kpis.size(); j++) { @@ -543,6 +533,55 @@ TEST_F(BamBA, KpiServiceDtInheritAllCritical) { } } +TEST_F(BamBA, KpiServiceDtInheritAllCriticalPb) { + std::shared_ptr test_ba{ + std::make_shared(1, 1, 4, true)}; + test_ba->set_level_critical(100); + test_ba->set_level_warning(75); + test_ba->set_downtime_behaviour(bam::configuration::ba::dt_inherit); + + std::vector> kpis; + std::stack results({true, false, false, false}); + + for (int i = 0; i < 4; i++) { + auto s = std::make_shared(i + 1, 1, i + 1, 1); + s->set_state_hard(bam::state_critical); + s->set_state_soft(s->get_state_hard()); + test_ba->add_impact(s); + s->add_parent(test_ba); + kpis.push_back(s); + } + + // Change KPI state as much time as needed to trigger a + // recomputation. Note that the loop must terminate on a odd number + // for the test to be correct. + time_t now(time(nullptr)); + + auto ss{std::make_shared()}; + auto dt{std::make_shared()}; + auto& downtime = dt->mut_obj(); + + ss->service_id = 1; + + for (size_t j = 0; j < kpis.size(); j++) { + ss->last_check = now + 1; + ss->host_id = j + 1; + ss->last_hard_state = 2; + kpis[j]->service_update(ss, _visitor.get()); + + downtime.set_host_id(ss->host_id); + downtime.set_service_id(1); + downtime.set_started(true); + downtime.set_actual_start_time(now + 2); + downtime.set_actual_end_time(0); + kpis[j]->service_update(dt, _visitor.get()); + + short val = results.top(); + ASSERT_EQ(test_ba->get_in_downtime(), val); + results.pop(); + } +} + TEST_F(BamBA, KpiServiceDtInheritOneOK) { std::shared_ptr test_ba{ std::make_shared(1, 1, 4, true)}; @@ -551,12 +590,7 @@ TEST_F(BamBA, KpiServiceDtInheritOneOK) { test_ba->set_downtime_behaviour(bam::configuration::ba::dt_inherit); std::vector> kpis; - std::stack results; - - results.push(false); - results.push(false); - results.push(false); - results.push(false); + std::stack results({false, false, false, false}); for (int i = 0; i < 4; i++) { auto s = std::make_shared(i + 1, 1, i + 1, 1); @@ -603,6 +637,63 @@ TEST_F(BamBA, KpiServiceDtInheritOneOK) { ASSERT_EQ(events.size(), 13u); } +TEST_F(BamBA, KpiServiceDtInheritOneOKPb) { + std::shared_ptr test_ba{ + std::make_shared(1, 1, 4, true)}; + test_ba->set_level_critical(100); + test_ba->set_level_warning(90); + test_ba->set_downtime_behaviour(bam::configuration::ba::dt_inherit); + + std::vector> kpis; + std::stack results({false, false, false, false}); + + for (int i = 0; i < 4; i++) { + auto s = std::make_shared(i + 1, 1, i + 1, 1); + if (i == 0) + s->set_state_hard(bam::state_ok); + else + s->set_state_hard(bam::state_critical); + s->set_state_soft(s->get_state_hard()); + test_ba->add_impact(s); + s->add_parent(test_ba); + kpis.push_back(s); + } + + time_t now = time(nullptr); + + auto ss = std::make_shared(); + auto dt = std::make_shared(); + auto& ss_obj = ss->mut_obj(); + auto& dt_obj = dt->mut_obj(); + ss_obj.set_service_id(1); + + for (size_t j = 0; j < kpis.size(); j++) { + ss_obj.set_last_check(now + 1); + ss_obj.set_host_id(j + 1); + ss_obj.set_service_id(1); + if (j == 0) + ss_obj.set_last_hard_state(ServiceStatus_State_OK); + else + ss_obj.set_last_hard_state(ServiceStatus_State_CRITICAL); + kpis[j]->service_update(ss, _visitor.get()); + + dt_obj.set_host_id(ss_obj.host_id()); + dt_obj.set_service_id(1); + dt_obj.set_started(true); + dt_obj.set_actual_start_time(now + 2); + dt_obj.set_actual_end_time(0); + kpis[j]->service_update(dt, _visitor.get()); + + short val = results.top(); + ASSERT_EQ(test_ba->get_in_downtime(), val); + results.pop(); + } + + auto events = _visitor->queue(); + _visitor->print_events(); + ASSERT_EQ(events.size(), 13u); +} + TEST_F(BamBA, KpiServiceIgnoreDt) { std::shared_ptr test_ba{ std::make_shared(1, 1, 4, true)}; @@ -611,12 +702,7 @@ TEST_F(BamBA, KpiServiceIgnoreDt) { test_ba->set_downtime_behaviour(bam::configuration::ba::dt_ignore); std::vector> kpis; - std::stack results; - - results.push(false); - results.push(false); - results.push(false); - results.push(false); + std::stack results({false, false, false, false}); for (int i = 0; i < 4; i++) { auto s = std::make_shared(i + 1, 1, i + 1, 1); @@ -632,8 +718,8 @@ TEST_F(BamBA, KpiServiceIgnoreDt) { // for the test to be correct. time_t now(time(nullptr)); - std::shared_ptr ss(new neb::service_status); - std::shared_ptr dt(new neb::downtime); + auto ss{std::make_shared()}; + auto dt{std::make_shared()}; ss->service_id = 1; for (size_t j = 0; j < kpis.size(); j++) { @@ -655,6 +741,56 @@ TEST_F(BamBA, KpiServiceIgnoreDt) { } } +TEST_F(BamBA, KpiServiceIgnoreDtPb) { + std::shared_ptr test_ba{ + std::make_shared(1, 1, 4, true)}; + test_ba->set_level_critical(100); + test_ba->set_level_warning(75); + test_ba->set_downtime_behaviour(bam::configuration::ba::dt_ignore); + + std::vector> kpis; + std::stack results({false, false, false, false}); + + for (int i = 0; i < 4; i++) { + auto s = std::make_shared(i + 1, 1, i + 1, 1); + s->set_state_hard(bam::state_critical); + s->set_state_soft(s->get_state_hard()); + test_ba->add_impact(s); + s->add_parent(test_ba); + kpis.push_back(s); + } + + // Change KPI state as much time as needed to trigger a + // recomputation. Note that the loop must terminate on a odd number + // for the test to be correct. + time_t now(time(nullptr)); + + auto ss{std::make_shared()}; + auto dt{std::make_shared()}; + auto& ss_obj = ss->mut_obj(); + auto& dt_obj = dt->mut_obj(); + + ss_obj.set_service_id(1); + + for (size_t j = 0; j < kpis.size(); j++) { + ss_obj.set_last_check(now + 1); + ss_obj.set_host_id(j + 1); + ss_obj.set_last_hard_state(ServiceStatus_State_CRITICAL); + kpis[j]->service_update(ss, _visitor.get()); + + dt_obj.set_host_id(ss_obj.host_id()); + dt_obj.set_service_id(1); + dt_obj.set_actual_start_time(now + 2); + dt_obj.set_started(true); + dt_obj.set_actual_end_time(0); + kpis[j]->service_update(dt, _visitor.get()); + + short val = results.top(); + ASSERT_EQ(test_ba->get_in_downtime(), val); + results.pop(); + } +} + TEST_F(BamBA, KpiServiceDtIgnoreKpi) { std::shared_ptr test_ba{ std::make_shared(1, 1, 4, true)}; @@ -663,12 +799,7 @@ TEST_F(BamBA, KpiServiceDtIgnoreKpi) { test_ba->set_downtime_behaviour(bam::configuration::ba::dt_ignore_kpi); std::vector> kpis; - std::stack results; - - results.push(false); - results.push(false); - results.push(false); - results.push(false); + std::stack results({false, false, false, false}); for (int i = 0; i < 4; i++) { auto s = std::make_shared(i + 1, 1, i + 1, 1); @@ -684,8 +815,8 @@ TEST_F(BamBA, KpiServiceDtIgnoreKpi) { // for the test to be correct. time_t now(time(nullptr)); - std::shared_ptr ss(new neb::service_status); - std::shared_ptr dt(new neb::downtime); + auto ss{std::make_shared()}; + auto dt{std::make_shared()}; ss->service_id = 1; for (size_t j = 0; j < kpis.size(); j++) { @@ -707,6 +838,56 @@ TEST_F(BamBA, KpiServiceDtIgnoreKpi) { } } +TEST_F(BamBA, KpiServiceDtIgnoreKpiPb) { + std::shared_ptr test_ba{ + std::make_shared(1, 1, 4, true)}; + test_ba->set_level_critical(100); + test_ba->set_level_warning(75); + test_ba->set_downtime_behaviour(bam::configuration::ba::dt_ignore_kpi); + + std::vector> kpis; + std::stack results({false, false, false, false}); + + for (int i = 0; i < 4; i++) { + auto s = std::make_shared(i + 1, 1, i + 1, 1); + s->set_state_hard(bam::state_critical); + s->set_state_soft(s->get_state_hard()); + test_ba->add_impact(s); + s->add_parent(test_ba); + kpis.push_back(s); + } + + // Change KPI state as much time as needed to trigger a + // recomputation. Note that the loop must terminate on a odd number + // for the test to be correct. + time_t now(time(nullptr)); + + auto ss{std::make_shared()}; + auto dt{std::make_shared()}; + auto& ss_obj = ss->mut_obj(); + auto& dt_obj = dt->mut_obj(); + + ss_obj.set_service_id(1); + + for (size_t j = 0; j < kpis.size(); j++) { + ss_obj.set_last_check(now + 1); + ss_obj.set_host_id(j + 1); + ss_obj.set_last_hard_state(ServiceStatus_State_CRITICAL); + kpis[j]->service_update(ss, _visitor.get()); + + dt_obj.set_host_id(ss_obj.host_id()); + dt_obj.set_service_id(1); + dt_obj.set_actual_start_time(now + 2); + dt_obj.set_started(true); + dt_obj.set_actual_end_time(0); + kpis[j]->service_update(dt, _visitor.get()); + + short val = results.top(); + ASSERT_EQ(test_ba->get_in_downtime(), val); + results.pop(); + } +} + TEST_F(BamBA, KpiServiceDtIgnoreKpiImpact) { std::shared_ptr test_ba{ std::make_shared(1, 1, 4, true)}; @@ -715,7 +896,7 @@ TEST_F(BamBA, KpiServiceDtIgnoreKpiImpact) { test_ba->set_downtime_behaviour(bam::configuration::ba::dt_ignore_kpi); std::vector> kpis; - std::stack results; + std::stack results({0, 0, 1, 2}); results.push(0); results.push(0); @@ -740,8 +921,8 @@ TEST_F(BamBA, KpiServiceDtIgnoreKpiImpact) { // for the test to be correct. time_t now(time(nullptr)); - std::shared_ptr ss(new neb::service_status); - std::shared_ptr dt(new neb::downtime); + auto ss{std::make_shared()}; + auto dt{std::make_shared()}; ss->service_id = 1; for (size_t j = 0; j < kpis.size(); j++) { @@ -766,34 +947,24 @@ TEST_F(BamBA, KpiServiceDtIgnoreKpiImpact) { } } -TEST_F(BamBA, KpiServiceDtIgnoreKpiBest) { +TEST_F(BamBA, KpiServiceDtIgnoreKpiImpactPb) { std::shared_ptr test_ba{ - std::make_shared(1, 1, 4, true)}; + std::make_shared(1, 1, 4, true)}; + test_ba->set_level_critical(50); + test_ba->set_level_warning(75); test_ba->set_downtime_behaviour(bam::configuration::ba::dt_ignore_kpi); std::vector> kpis; - std::stack results; - - results.push(0); - results.push(2); - results.push(1); - results.push(0); + std::stack results({0, 0, 1, 2}); for (int i = 0; i < 4; i++) { auto s = std::make_shared(i + 1, 1, i + 1, 1); - switch (i) { - case 0: - case 1: - s->set_state_hard(bam::state_ok); - break; - case 2: - s->set_state_hard(bam::state_warning); - break; - case 3: - s->set_state_hard(bam::state_critical); - break; - } + if (i == 3) + s->set_state_hard(bam::state_ok); + else + s->set_state_hard(bam::state_critical); s->set_state_soft(s->get_state_hard()); + s->set_impact_critical(25); test_ba->add_impact(s); s->add_parent(test_ba); kpis.push_back(s); @@ -804,21 +975,27 @@ TEST_F(BamBA, KpiServiceDtIgnoreKpiBest) { // for the test to be correct. time_t now(time(nullptr)); - std::shared_ptr ss(new neb::service_status); - std::shared_ptr dt(new neb::downtime); - ss->service_id = 1; + auto ss{std::make_shared()}; + auto dt{std::make_shared()}; + auto& ss_obj = ss->mut_obj(); + auto& dt_obj = dt->mut_obj(); + + ss_obj.set_service_id(1); for (size_t j = 0; j < kpis.size(); j++) { - ss->last_check = now + 1; - ss->host_id = j + 1; - ss->last_hard_state = kpis[j]->get_state_hard(); + ss_obj.set_last_check(now + 1); + ss_obj.set_host_id(j + 1); + if (j == 3) + ss_obj.set_last_hard_state(ServiceStatus_State_OK); + else + ss_obj.set_last_hard_state(ServiceStatus_State_CRITICAL); kpis[j]->service_update(ss, _visitor.get()); - dt->host_id = ss->host_id; - dt->service_id = 1; - dt->actual_start_time = now + 2; - dt->was_started = true; - dt->actual_end_time = 0; + dt_obj.set_host_id(ss_obj.host_id()); + dt_obj.set_service_id(1); + dt_obj.set_actual_start_time(now + 2); + dt_obj.set_started(true); + dt_obj.set_actual_end_time(0); kpis[j]->service_update(dt, _visitor.get()); short val = results.top(); @@ -827,31 +1004,26 @@ TEST_F(BamBA, KpiServiceDtIgnoreKpiBest) { } } -TEST_F(BamBA, KpiServiceDtIgnoreKpiWorst) { +TEST_F(BamBA, KpiServiceDtIgnoreKpiBest) { std::shared_ptr test_ba{ - std::make_shared(1, 1, 4, true)}; + std::make_shared(1, 1, 4, true)}; test_ba->set_downtime_behaviour(bam::configuration::ba::dt_ignore_kpi); std::vector> kpis; - std::stack results; - - results.push(0); - results.push(0); - results.push(1); - results.push(2); + std::stack results({0, 2, 1, 0}); for (int i = 0; i < 4; i++) { auto s = std::make_shared(i + 1, 1, i + 1, 1); switch (i) { case 0: case 1: - s->set_state_hard(bam::state_critical); + s->set_state_hard(bam::state_ok); break; case 2: s->set_state_hard(bam::state_warning); break; case 3: - s->set_state_hard(bam::state_ok); + s->set_state_hard(bam::state_critical); break; } s->set_state_soft(s->get_state_hard()); @@ -865,8 +1037,8 @@ TEST_F(BamBA, KpiServiceDtIgnoreKpiWorst) { // for the test to be correct. time_t now(time(nullptr)); - std::shared_ptr ss(new neb::service_status); - std::shared_ptr dt(new neb::downtime); + auto ss(std::make_shared()); + auto dt(std::make_shared()); ss->service_id = 1; for (size_t j = 0; j < kpis.size(); j++) { @@ -877,8 +1049,8 @@ TEST_F(BamBA, KpiServiceDtIgnoreKpiWorst) { dt->host_id = ss->host_id; dt->service_id = 1; - dt->was_started = true; dt->actual_start_time = now + 2; + dt->was_started = true; dt->actual_end_time = 0; kpis[j]->service_update(dt, _visitor.get()); @@ -888,24 +1060,28 @@ TEST_F(BamBA, KpiServiceDtIgnoreKpiWorst) { } } -TEST_F(BamBA, KpiServiceDtIgnoreKpiRatio) { +TEST_F(BamBA, KpiServiceDtIgnoreKpiBestPb) { std::shared_ptr test_ba{ - std::make_shared(1, 1, 4, true)}; + std::make_shared(1, 1, 4, true)}; test_ba->set_downtime_behaviour(bam::configuration::ba::dt_ignore_kpi); - test_ba->set_level_warning(1); - test_ba->set_level_critical(2); std::vector> kpis; - std::stack results; - - results.push(0); - results.push(1); - results.push(2); - results.push(2); + std::stack results({0, 2, 1, 0}); for (int i = 0; i < 4; i++) { auto s = std::make_shared(i + 1, 1, i + 1, 1); - s->set_state_hard(bam::state_critical); + switch (i) { + case 0: + case 1: + s->set_state_hard(bam::state_ok); + break; + case 2: + s->set_state_hard(bam::state_warning); + break; + case 3: + s->set_state_hard(bam::state_critical); + break; + } s->set_state_soft(s->get_state_hard()); test_ba->add_impact(s); s->add_parent(test_ba); @@ -917,20 +1093,186 @@ TEST_F(BamBA, KpiServiceDtIgnoreKpiRatio) { // for the test to be correct. time_t now(time(nullptr)); - std::shared_ptr ss(new neb::service_status); - std::shared_ptr dt(new neb::downtime); - ss->service_id = 1; + auto ss{std::make_shared()}; + auto dt{std::make_shared()}; + auto& ss_obj = ss->mut_obj(); + auto& dt_obj = dt->mut_obj(); + + ss_obj.set_service_id(1); for (size_t j = 0; j < kpis.size(); j++) { - ss->last_check = now + 1; - ss->host_id = j + 1; - ss->last_hard_state = kpis[j]->get_state_hard(); + ss_obj.set_last_check(now + 1); + ss_obj.set_host_id(j + 1); + ss_obj.set_last_hard_state( + static_cast(kpis[j]->get_state_hard())); kpis[j]->service_update(ss, _visitor.get()); - dt->host_id = ss->host_id; - dt->service_id = 1; - dt->actual_start_time = now + 2; - dt->was_started = true; + dt_obj.set_host_id(ss_obj.host_id()); + dt_obj.set_service_id(1); + dt_obj.set_actual_start_time(now + 2); + dt_obj.set_started(true); + dt_obj.set_actual_end_time(0); + kpis[j]->service_update(dt, _visitor.get()); + + short val = results.top(); + ASSERT_EQ(test_ba->get_state_hard(), val); + results.pop(); + } +} + +TEST_F(BamBA, KpiServiceDtIgnoreKpiWorst) { + std::shared_ptr test_ba{ + std::make_shared(1, 1, 4, true)}; + test_ba->set_downtime_behaviour(bam::configuration::ba::dt_ignore_kpi); + + std::vector> kpis; + std::stack results({0, 0, 1, 2}); + + for (int i = 0; i < 4; i++) { + auto s = std::make_shared(i + 1, 1, i + 1, 1); + switch (i) { + case 0: + case 1: + s->set_state_hard(bam::state_critical); + break; + case 2: + s->set_state_hard(bam::state_warning); + break; + case 3: + s->set_state_hard(bam::state_ok); + break; + } + s->set_state_soft(s->get_state_hard()); + test_ba->add_impact(s); + s->add_parent(test_ba); + kpis.push_back(s); + } + + // Change KPI state as much time as needed to trigger a + // recomputation. Note that the loop must terminate on a odd number + // for the test to be correct. + time_t now(time(nullptr)); + + auto ss{std::make_shared()}; + auto dt{std::make_shared()}; + ss->service_id = 1; + + for (size_t j = 0; j < kpis.size(); j++) { + ss->last_check = now + 1; + ss->host_id = j + 1; + ss->last_hard_state = kpis[j]->get_state_hard(); + kpis[j]->service_update(ss, _visitor.get()); + + dt->host_id = ss->host_id; + dt->service_id = 1; + dt->was_started = true; + dt->actual_start_time = now + 2; + dt->actual_end_time = 0; + kpis[j]->service_update(dt, _visitor.get()); + + short val = results.top(); + ASSERT_EQ(test_ba->get_state_hard(), val); + results.pop(); + } +} + +TEST_F(BamBA, KpiServiceDtIgnoreKpiWorstPb) { + std::shared_ptr test_ba{ + std::make_shared(1, 1, 4, true)}; + test_ba->set_downtime_behaviour(bam::configuration::ba::dt_ignore_kpi); + + std::vector> kpis; + std::stack results({0, 0, 1, 2}); + + for (int i = 0; i < 4; i++) { + auto s = std::make_shared(i + 1, 1, i + 1, 1); + switch (i) { + case 0: + case 1: + s->set_state_hard(bam::state_critical); + break; + case 2: + s->set_state_hard(bam::state_warning); + break; + case 3: + s->set_state_hard(bam::state_ok); + break; + } + s->set_state_soft(s->get_state_hard()); + test_ba->add_impact(s); + s->add_parent(test_ba); + kpis.push_back(s); + } + + // Change KPI state as much time as needed to trigger a + // recomputation. Note that the loop must terminate on a odd number + // for the test to be correct. + time_t now(time(nullptr)); + + auto ss{std::make_shared()}; + auto dt{std::make_shared()}; + auto& ss_obj = ss->mut_obj(); + auto& dt_obj = dt->mut_obj(); + ss_obj.set_service_id(1); + + for (size_t j = 0; j < kpis.size(); j++) { + ss_obj.set_last_check(now + 1); + ss_obj.set_host_id(j + 1); + ss_obj.set_last_hard_state( + static_cast(kpis[j]->get_state_hard())); + kpis[j]->service_update(ss, _visitor.get()); + + dt_obj.set_host_id(ss_obj.host_id()); + dt_obj.set_service_id(1); + dt_obj.set_started(true); + dt_obj.set_actual_start_time(now + 2); + dt_obj.set_actual_end_time(0); + kpis[j]->service_update(dt, _visitor.get()); + + short val = results.top(); + ASSERT_EQ(test_ba->get_state_hard(), val); + results.pop(); + } +} + +TEST_F(BamBA, KpiServiceDtIgnoreKpiRatio) { + std::shared_ptr test_ba{ + std::make_shared(1, 1, 4, true)}; + test_ba->set_downtime_behaviour(bam::configuration::ba::dt_ignore_kpi); + test_ba->set_level_warning(1); + test_ba->set_level_critical(2); + + std::vector> kpis; + std::stack results({0, 1, 2, 2}); + + for (int i = 0; i < 4; i++) { + auto s = std::make_shared(i + 1, 1, i + 1, 1); + s->set_state_hard(bam::state_critical); + s->set_state_soft(s->get_state_hard()); + test_ba->add_impact(s); + s->add_parent(test_ba); + kpis.push_back(s); + } + + // Change KPI state as much time as needed to trigger a + // recomputation. Note that the loop must terminate on a odd number + // for the test to be correct. + time_t now(time(nullptr)); + + auto ss{std::make_shared()}; + auto dt{std::make_shared()}; + ss->service_id = 1; + + for (size_t j = 0; j < kpis.size(); j++) { + ss->last_check = now + 1; + ss->host_id = j + 1; + ss->last_hard_state = kpis[j]->get_state_hard(); + kpis[j]->service_update(ss, _visitor.get()); + + dt->host_id = ss->host_id; + dt->service_id = 1; + dt->actual_start_time = now + 2; + dt->was_started = true; dt->actual_end_time = 0; kpis[j]->service_update(dt, _visitor.get()); @@ -940,6 +1282,57 @@ TEST_F(BamBA, KpiServiceDtIgnoreKpiRatio) { } } +TEST_F(BamBA, KpiServiceDtIgnoreKpiRatioPb) { + std::shared_ptr test_ba{ + std::make_shared(1, 1, 4, true)}; + test_ba->set_downtime_behaviour(bam::configuration::ba::dt_ignore_kpi); + test_ba->set_level_warning(1); + test_ba->set_level_critical(2); + + std::vector> kpis; + std::stack results({0, 1, 2, 2}); + + for (int i = 0; i < 4; i++) { + auto s = std::make_shared(i + 1, 1, i + 1, 1); + s->set_state_hard(bam::state_critical); + s->set_state_soft(s->get_state_hard()); + test_ba->add_impact(s); + s->add_parent(test_ba); + kpis.push_back(s); + } + + // Change KPI state as much time as needed to trigger a + // recomputation. Note that the loop must terminate on a odd number + // for the test to be correct. + time_t now(time(nullptr)); + + auto ss{std::make_shared()}; + auto dt{std::make_shared()}; + auto& ss_obj = ss->mut_obj(); + auto& dt_obj = dt->mut_obj(); + + ss_obj.set_service_id(1); + + for (size_t j = 0; j < kpis.size(); j++) { + ss_obj.set_last_check(now + 1); + ss_obj.set_host_id(j + 1); + ss_obj.set_last_hard_state( + static_cast(kpis[j]->get_state_hard())); + kpis[j]->service_update(ss, _visitor.get()); + + dt_obj.set_host_id(ss_obj.host_id()); + dt_obj.set_service_id(1); + dt_obj.set_actual_start_time(now + 2); + dt_obj.set_started(true); + dt_obj.set_actual_end_time(0); + kpis[j]->service_update(dt, _visitor.get()); + + short val = results.top(); + ASSERT_EQ(test_ba->get_state_hard(), val); + results.pop(); + } +} + TEST_F(BamBA, KpiServiceDt) { std::shared_ptr test_ba{ std::make_shared(1, 1, 4, true)}; @@ -964,11 +1357,10 @@ TEST_F(BamBA, KpiServiceDt) { // for the test to be correct. time_t now(time(nullptr)); - std::shared_ptr ss(new neb::service_status); + auto ss{std::make_shared()}; + auto dt{std::make_shared()}; ss->service_id = 1; - std::shared_ptr dt(std::make_shared()); - auto it = results.begin(); for (size_t j = 0; j < kpis.size(); j++) { ss->last_check = now + 1; @@ -1101,6 +1493,169 @@ TEST_F(BamBA, KpiServiceDt) { ASSERT_FALSE(test_ba->get_in_downtime()); } +TEST_F(BamBA, KpiServiceDtPb) { + std::shared_ptr test_ba{ + std::make_shared(1, 1, 4, true)}; + test_ba->set_level_critical(100); + test_ba->set_level_warning(75); + test_ba->set_downtime_behaviour(bam::configuration::ba::dt_inherit); + + std::vector> kpis; + std::vector results{false, false, false, true}; + + for (int i = 0; i < 4; i++) { + auto s = std::make_shared(i + 1, 1, i + 1, 1); + s->set_state_hard(bam::state_critical); + s->set_state_soft(s->get_state_hard()); + test_ba->add_impact(s); + s->add_parent(test_ba); + kpis.push_back(s); + } + + // Change KPI state as much time as needed to trigger a + // recomputation. Note that the loop must terminate on a odd number + // for the test to be correct. + time_t now(time(nullptr)); + + auto ss{std::make_shared()}; + auto dt{std::make_shared()}; + auto& ss_obj = ss->mut_obj(); + auto& dt_obj = dt->mut_obj(); + + ss_obj.set_service_id(1); + + auto it = results.begin(); + for (size_t j = 0; j < kpis.size(); j++) { + ss_obj.set_last_check(now + 1); + ss_obj.set_host_id(j + 1); + ss_obj.set_last_hard_state(ServiceStatus_State_CRITICAL); + kpis[j]->service_update(ss, _visitor.get()); + + dt_obj.set_host_id(ss_obj.host_id()); + dt_obj.set_service_id(1); + dt_obj.set_started(true); + dt_obj.set_actual_start_time(now + 1); + dt_obj.set_actual_end_time(0); + kpis[j]->service_update(dt, _visitor.get()); + + short val = *it; + ASSERT_EQ(test_ba->get_in_downtime(), val); + ++it; + } + + for (int i = 0; i < 3; i++) { + dt_obj.set_host_id(1); + dt_obj.set_service_id(1); + dt_obj.set_actual_start_time(now + 2 + 10 * i); + dt_obj.set_actual_end_time(0); + dt_obj.set_started(true); + std::cout << "service_update 1" << std::endl; + kpis[0]->service_update(dt, _visitor.get()); + + dt_obj.set_deletion_time(now + 2 + 10 * i + 5); + dt_obj.set_actual_end_time(now + 2 + 10 * i + 5); + dt_obj.set_cancelled(true); + std::cout << "service_update 2" << std::endl; + kpis[0]->service_update(dt, _visitor.get()); + } + auto events = _visitor->queue(); + + _visitor->print_events(); + + ASSERT_EQ(events.size(), 41u); + { + auto it = events.begin(); + /* For each kpi... */ + for (int i = 0; i < 4; i++) { + /* the kpi is set to hard critical and not in downtime */ + ASSERT_EQ(it->start_time, now + 1); + ASSERT_EQ(it->end_time, -1); + ASSERT_EQ(it->in_downtime, false); + do { + ++it; + } while (it->typ != test_visitor::test_event::kpi); + + /* the kpi is set in downtime */ + /* The previous event is closed */ + ASSERT_EQ(it->start_time, now + 1); + ASSERT_EQ(it->end_time, now + 1); + ASSERT_EQ(it->in_downtime, false); + do { + ++it; + } while (it->typ != test_visitor::test_event::kpi); + + /* The new event on downtime is added and open */ + ASSERT_EQ(it->start_time, now + 1); + ASSERT_EQ(it->end_time, -1); + ASSERT_EQ(it->in_downtime, true); + do { + ++it; + } while (it->typ != test_visitor::test_event::kpi); + } + + //////////////////////////////////////////////////////////////// + + /* We set the downtime to true for the kpi1, but it is already in downtime, + * the event is skipped. Then we remove the downtime. + * 1. closure of the event concerning the downtime open + * 2. new event for downtime. + * 3. closure of the downtime event. + * 4. new event with downtime set to false. + */ + + ASSERT_EQ(it->start_time, now + 1); + ASSERT_EQ(it->end_time, now + 7); + ASSERT_TRUE(it->in_downtime); + do { + ++it; + } while (it->typ != test_visitor::test_event::kpi); + + ASSERT_EQ(it->start_time, now + 7); + ASSERT_EQ(it->end_time, -1); + ASSERT_FALSE(it->in_downtime); + do { + ++it; + } while (it->typ != test_visitor::test_event::kpi); + + /* New downtime: + * 1. closure of the event concerning the downtime off. + * 2. new event with downtime on. + */ + ASSERT_EQ(it->start_time, now + 7); + ASSERT_EQ(it->end_time, now + 12); + ASSERT_FALSE(it->in_downtime); + do { + ++it; + } while (it->typ != test_visitor::test_event::kpi); + + ASSERT_EQ(it->start_time, now + 12); + ASSERT_EQ(it->end_time, -1); + ASSERT_TRUE(it->in_downtime); + do { + ++it; + } while (it->typ != test_visitor::test_event::kpi); + + /* New downtime: + * 1. closure of the event concerning the downtime on. + * 2. new event with downtime on. + */ + ASSERT_EQ(it->start_time, now + 12); + ASSERT_EQ(it->end_time, now + 17); + ASSERT_TRUE(it->in_downtime); + do { + ++it; + } while (it->typ != test_visitor::test_event::kpi); + + ASSERT_EQ(it->start_time, now + 17); + ASSERT_EQ(it->end_time, -1); + ASSERT_FALSE(it->in_downtime); + do { + ++it; + } while (it->typ != test_visitor::test_event::kpi); + } + ASSERT_FALSE(test_ba->get_in_downtime()); +} + TEST_F(BamBA, KpiServiceDtInherited_set) { std::shared_ptr test_ba{ std::make_shared(1, 1, 4, true)}; @@ -1125,11 +1680,10 @@ TEST_F(BamBA, KpiServiceDtInherited_set) { // for the test to be correct. time_t now(time(nullptr)); - std::shared_ptr ss(new neb::service_status); + auto ss{std::make_shared()}; + auto dt{std::make_shared()}; ss->service_id = 1; - std::shared_ptr dt(std::make_shared()); - auto it = results.begin(); for (size_t j = 0; j < kpis.size(); j++) { ss->last_check = now + 1; @@ -1160,6 +1714,67 @@ TEST_F(BamBA, KpiServiceDtInherited_set) { ASSERT_TRUE(test_ba->get_in_downtime()); } +TEST_F(BamBA, KpiServiceDtInherited_setPb) { + std::shared_ptr test_ba{ + std::make_shared(1, 1, 4, true)}; + test_ba->set_level_critical(100); + test_ba->set_level_warning(75); + test_ba->set_downtime_behaviour(bam::configuration::ba::dt_inherit); + + std::vector> kpis; + std::vector results{false, false, false, true}; + + for (int i = 0; i < 4; i++) { + auto s = std::make_shared(i + 1, 1, i + 1, 1); + s->set_state_hard(bam::state_critical); + s->set_state_soft(s->get_state_hard()); + test_ba->add_impact(s); + s->add_parent(test_ba); + kpis.push_back(s); + } + + // Change KPI state as much time as needed to trigger a + // recomputation. Note that the loop must terminate on a odd number + // for the test to be correct. + time_t now(time(nullptr)); + + auto ss{std::make_shared()}; + auto dt{std::make_shared()}; + auto& ss_obj = ss->mut_obj(); + auto& dt_obj = dt->mut_obj(); + + ss_obj.set_service_id(1); + + auto it = results.begin(); + for (size_t j = 0; j < kpis.size(); j++) { + ss_obj.set_last_check(now + 1); + ss_obj.set_host_id(j + 1); + ss_obj.set_last_hard_state(ServiceStatus_State_CRITICAL); + kpis[j]->service_update(ss, _visitor.get()); + + dt_obj.set_host_id(ss_obj.host_id()); + dt_obj.set_service_id(1); + dt_obj.set_started(true); + dt_obj.set_actual_start_time(now + 1); + dt_obj.set_actual_end_time(0); + kpis[j]->service_update(dt, _visitor.get()); + + short val = *it; + ASSERT_EQ(test_ba->get_in_downtime(), val); + ++it; + } + + for (int i = 0; i < 3; i++) { + dt_obj.set_host_id(1); + dt_obj.set_service_id(1); + dt_obj.set_actual_start_time(now + 2 + 10 * i); + dt_obj.set_actual_end_time(0); + dt_obj.set_started(true); + kpis[0]->service_update(dt, _visitor.get()); + } + ASSERT_TRUE(test_ba->get_in_downtime()); +} + TEST_F(BamBA, KpiServiceDtInherited_unset) { std::shared_ptr test_ba{ std::make_shared(1, 2, 4, true)}; @@ -1183,10 +1798,10 @@ TEST_F(BamBA, KpiServiceDtInherited_unset) { // for the test to be correct. time_t now(time(nullptr)); - std::shared_ptr ss(new neb::service_status); - ss->service_id = 1; + auto ss{std::make_shared()}; + auto dt{std::make_shared()}; - std::shared_ptr dt(std::make_shared()); + ss->service_id = 1; for (size_t j = 0; j < kpis.size(); j++) { ss->last_check = now + 1; @@ -1205,6 +1820,52 @@ TEST_F(BamBA, KpiServiceDtInherited_unset) { ASSERT_FALSE(test_ba->get_in_downtime()); } +TEST_F(BamBA, KpiServiceDtInherited_unsetPb) { + std::shared_ptr test_ba{ + std::make_shared(1, 2, 4, true)}; + test_ba->set_level_critical(100); + test_ba->set_level_warning(75); + test_ba->set_downtime_behaviour(bam::configuration::ba::dt_inherit); + + std::vector> kpis; + + for (int i = 0; i < 4; i++) { + auto s = std::make_shared(i + 1, 1, i + 1, 1); + s->set_state_hard(bam::state_critical); + s->set_state_soft(s->get_state_hard()); + test_ba->add_impact(s); + s->add_parent(test_ba); + kpis.push_back(s); + } + + // Change KPI state as much time as needed to trigger a + // recomputation. Note that the loop must terminate on a odd number + // for the test to be correct. + time_t now(time(nullptr)); + + auto ss{std::make_shared()}; + auto dt{std::make_shared()}; + auto& ss_obj = ss->mut_obj(); + auto& dt_obj = dt->mut_obj(); + ss_obj.set_service_id(1); + + for (size_t j = 0; j < kpis.size(); j++) { + ss_obj.set_last_check(now + 1); + ss_obj.set_host_id(j + 1); + ss_obj.set_last_hard_state(ServiceStatus_State_CRITICAL); + kpis[j]->service_update(ss, _visitor.get()); + + dt_obj.set_host_id(ss_obj.host_id()); + dt_obj.set_service_id(1); + dt_obj.set_started(false); + dt_obj.set_actual_start_time(0); + dt_obj.set_actual_end_time(0); + kpis[j]->service_update(dt, _visitor.get()); + } + + ASSERT_FALSE(test_ba->get_in_downtime()); +} + TEST_F(BamBA, KpiServiceAcknowledgement) { std::shared_ptr test_ba{ std::make_shared(1, 2, 4, true)}; @@ -1228,12 +1889,10 @@ TEST_F(BamBA, KpiServiceAcknowledgement) { // for the test to be correct. time_t now(time(nullptr)); - std::shared_ptr ss(new neb::service_status); + auto ss{std::make_shared()}; + auto ack{std::make_shared()}; ss->service_id = 1; - std::shared_ptr ack( - std::make_shared()); - for (size_t j = 0; j < kpis.size(); j++) { ss->last_check = now + 1; ss->host_id = j + 1; @@ -1253,3 +1912,52 @@ TEST_F(BamBA, KpiServiceAcknowledgement) { _visitor->print_events(); } + +TEST_F(BamBA, KpiServiceAcknowledgementPb) { + std::shared_ptr test_ba{ + std::make_shared(1, 2, 4, true)}; + test_ba->set_level_critical(100); + test_ba->set_level_warning(75); + test_ba->set_downtime_behaviour(bam::configuration::ba::dt_inherit); + + std::vector> kpis; + + for (int i = 0; i < 4; i++) { + auto s = std::make_shared(i + 1, 1, i + 1, 1); + s->set_state_hard(bam::state_critical); + s->set_state_soft(s->get_state_hard()); + test_ba->add_impact(s); + s->add_parent(test_ba); + kpis.push_back(std::move(s)); + } + + // Change KPI state as much time as needed to trigger a + // recomputation. Note that the loop must terminate on a odd number + // for the test to be correct. + time_t now(time(nullptr)); + + auto ss{std::make_shared()}; + auto ack{std::make_shared()}; + auto& ss_obj = ss->mut_obj(); + + ss_obj.set_service_id(1); + + for (size_t j = 0; j < kpis.size(); j++) { + ss_obj.set_last_check(now + 1); + ss_obj.set_host_id(j + 1); + ss_obj.set_last_hard_state(ServiceStatus_State_CRITICAL); + kpis[j]->service_update(ss, _visitor.get()); + + ack->poller_id = 1; + ack->host_id = ss_obj.host_id(); + ack->service_id = 1; + ack->entry_time = now + 2; + ack->deletion_time = -1; + kpis[j]->service_update(ack, _visitor.get()); + } + + auto events = _visitor->queue(); + ASSERT_EQ(events.size(), 5u); + + _visitor->print_events(); +} diff --git a/broker/core/inc/com/centreon/broker/stats/center.hh b/broker/core/inc/com/centreon/broker/stats/center.hh index 409e80df3e7..61b4e56e7fc 100644 --- a/broker/core/inc/com/centreon/broker/stats/center.hh +++ b/broker/core/inc/com/centreon/broker/stats/center.hh @@ -20,7 +20,7 @@ #define CCB_STATS_CENTER_HH #include "broker.pb.h" -#include "com/centreon/broker/pool.hh" +#include "com/centreon/broker/namespace.hh" CCB_BEGIN() @@ -51,8 +51,8 @@ namespace stats { */ class center { static center* _instance; - asio::io_context::strand _strand; BrokerStats _stats; + std::mutex _stats_m; int _json_stats_file_creation; center(); @@ -66,7 +66,7 @@ class center { EngineStats* register_engine(); ConflictManagerStats* register_conflict_manager(); - bool unregister_muxer(const std::string& name); + void unregister_muxer(const std::string& name); void update_muxer(std::string name, std::string queue_file, uint32_t size, @@ -98,7 +98,8 @@ class center { */ template void update(T* ptr, T value) { - _strand.post([ptr, value = std::move(value)] { *ptr = value; }); + std::lock_guard lck(_stats_m); + *ptr = std::move(value); } /** @@ -128,17 +129,19 @@ class center { */ template void update(void (U::*f)(T), U* ptr, T value) { - _strand.post([ptr, f, value] { (ptr->*f)(value); }); + std::lock_guard lck(_stats_m); + (ptr->*f)(value); } - void execute(std::function f) { _strand.post(f); } + void execute(std::function f) { + std::lock_guard lck(_stats_m); + f(); + } template const T& get(T (U::*f)() const, const U* ptr) { - std::promise p; - std::future retval = p.get_future(); - _strand.post([&p, ptr, f] { p.set_value((ptr->*f)()); }); - return retval.get(); + std::lock_guard lck(_stats_m); + return (ptr->*f)(); } }; diff --git a/broker/core/src/stats/center.cc b/broker/core/src/stats/center.cc index 20a2681ac81..37e5d1a8452 100644 --- a/broker/core/src/stats/center.cc +++ b/broker/core/src/stats/center.cc @@ -1,5 +1,5 @@ /* -** Copyright 2020-2021 Centreon +** Copyright 2020-2022 Centreon ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ #include "com/centreon/broker/config/applier/state.hh" #include "com/centreon/broker/log_v2.hh" #include "com/centreon/broker/misc/filesystem.hh" +#include "com/centreon/broker/pool.hh" #include "com/centreon/broker/version.hh" using namespace com::centreon::broker; @@ -49,7 +50,7 @@ void center::unload() { _instance = nullptr; } -center::center() : _strand(pool::instance().io_context()) { +center::center() { *_stats.mutable_version() = version::string; *_stats.mutable_asio_version() = fmt::format("{}.{}.{}", ASIO_VERSION / 100000, ASIO_VERSION / 100 % 1000, @@ -79,12 +80,6 @@ center::center() : _strand(pool::instance().io_context()) { * @brief The destructor. */ center::~center() { - /* Before destroying the strand, we have to wait it is really empty. We post - * a last action and wait it is over. */ - std::promise p; - std::future f{p.get_future()}; - _strand.post([&p] { p.set_value(true); }); - f.get(); pool::instance().stop_stats(); } @@ -99,39 +94,24 @@ center::~center() { * @return A pointer to the engine statistics. */ EngineStats* center::register_engine() { - std::promise p; - std::future retval = p.get_future(); - _strand.post([this, &p] { - auto eng = _stats.mutable_processing()->mutable_engine(); - p.set_value(eng); - }); - return retval.get(); + std::lock_guard lck(_stats_m); + return _stats.mutable_processing()->mutable_engine(); } SqlConnectionStats* center::add_connection() { - std::promise p; - std::future retval = p.get_future(); - _strand.post([this, &p] { - auto m = _stats.mutable_sql_manager()->add_connections(); - p.set_value(m); - }); - return retval.get(); + std::lock_guard lck(_stats_m); + return _stats.mutable_sql_manager()->add_connections(); } void center::remove_connection(SqlConnectionStats* stats) { - std::promise p; - _strand.post([this, stats, &p] { - auto* mc = _stats.mutable_sql_manager()->mutable_connections(); - for (auto it = mc->begin(); it != mc->end(); ++it) { - if (&(*it) == stats) { - mc->erase(it); - p.set_value(); - return; - } + std::lock_guard lck(_stats_m); + auto* c = _stats.mutable_sql_manager()->mutable_connections(); + for (auto it = c->begin(); it != c->end(); ++it) { + if (&*it == stats) { + c->erase(it); + break; } - p.set_value(); - }); - return p.get_future().wait(); + } } /** @@ -143,14 +123,9 @@ void center::remove_connection(SqlConnectionStats* stats) { * * @return true on success (it never fails). */ -bool center::unregister_muxer(const std::string& name) { - std::promise p; - std::future retval = p.get_future(); - _strand.post([this, &p, name] { - _stats.mutable_processing()->mutable_muxers()->erase(name); - p.set_value(true); - }); - return retval.get(); +void center::unregister_muxer(const std::string& name) { + std::lock_guard lck(_stats_m); + _stats.mutable_processing()->mutable_muxers()->erase(name); } /** @@ -165,29 +140,26 @@ void center::update_muxer(std::string name, std::string queue_file, uint32_t size, uint32_t unack) { - _strand.post([this, name = std::move(name), queue = std::move(queue_file), - size, unack] { - auto ms = &(*_stats.mutable_processing()->mutable_muxers())[name]; - if (ms) { - ms->mutable_queue_file()->set_name(std::move(queue)); - ms->set_total_events(size); - ms->set_unacknowledged_events(unack); - } - }); + std::lock_guard lck(_stats_m); + auto ms = &(*_stats.mutable_processing()->mutable_muxers())[std::move(name)]; + if (ms) { + ms->mutable_queue_file()->set_name(std::move(queue_file)); + ms->set_total_events(size); + ms->set_unacknowledged_events(unack); + } } void center::init_queue_file(std::string muxer, std::string queue_file, uint32_t max_file_size) { - _strand.post([this, name = std::move(muxer), queue = std::move(queue_file), - max_file_size] { - auto qfs = (&(*_stats.mutable_processing()->mutable_muxers())[name]) - ->mutable_queue_file(); - if (qfs) { - qfs->set_name(std::move(queue)); - qfs->set_max_file_size(max_file_size); - } - }); + std::lock_guard lck(_stats_m); + auto qfs = + (&(*_stats.mutable_processing()->mutable_muxers())[std::move(muxer)]) + ->mutable_queue_file(); + if (qfs) { + qfs->set_name(std::move(queue_file)); + qfs->set_max_file_size(max_file_size); + } } /** @@ -304,13 +276,8 @@ void center::init_queue_file(std::string muxer, * @return A pointer to the conflict_manager statistics. */ ConflictManagerStats* center::register_conflict_manager() { - std::promise p; - std::future retval = p.get_future(); - _strand.post([this, &p] { - auto cm = _stats.mutable_conflict_manager(); - p.set_value(cm); - }); - return retval.get(); + std::lock_guard lck(_stats_m); + return _stats.mutable_conflict_manager(); } /** @@ -337,55 +304,30 @@ ConflictManagerStats* center::register_conflict_manager() { * @return a string with the object in json format. */ std::string center::to_string() { - std::promise p; - std::future retval = p.get_future(); - _strand.post( - [&s = this->_stats, &p, &tmpnow = this->_json_stats_file_creation] { - const JsonPrintOptions options; - std::string retval; - std::time_t now; - time(&now); - tmpnow = (int)now; - s.set_now(now); - MessageToJsonString(s, &retval, options); - p.set_value(std::move(retval)); - }); - - return retval.get(); + const JsonPrintOptions options; + std::string retval; + std::time_t now; + time(&now); + std::lock_guard lck(_stats_m); + _json_stats_file_creation = now; + _stats.set_now(now); + MessageToJsonString(_stats, &retval, options); + return retval; } void center::get_sql_manager_stats(SqlManagerStats* response) { - std::promise p; - _strand.post([&s = this->_stats, &p, response] { - *response = s.sql_manager(); - p.set_value(); - }); - - // We wait for the response. - p.get_future().wait(); + std::lock_guard lck(_stats_m); + *response = _stats.sql_manager(); } void center::get_sql_connection_size(GenericSize* response) { - std::promise p; - _strand.post([&s = this->_stats, &p, response] { - response->set_size(s.sql_manager().connections().size()); - p.set_value(); - }); - - // We wait for the response. - p.get_future().wait(); + std::lock_guard lck(_stats_m); + response->set_size(_stats.sql_manager().connections().size()); } void center::get_conflict_manager_stats(ConflictManagerStats* response) { - std::promise p; - std::future done = p.get_future(); - _strand.post([&s = this->_stats, &p, response] { - *response = s.conflict_manager(); - p.set_value(true); - }); - - // We wait for the response. - done.get(); + std::lock_guard lck(_stats_m); + *response = _stats.conflict_manager(); } int center::get_json_stats_file_creation(void) { @@ -393,47 +335,31 @@ int center::get_json_stats_file_creation(void) { } bool center::muxer_stats(const std::string& name, MuxerStats* response) { - std::promise p; - std::future done = p.get_future(); - _strand.post([&s = this->_stats, &p, name, response] { - if (!s.processing().muxers().contains(name)) - p.set_value(false); - else { - *response = s.processing().muxers().at(name); - p.set_value(true); - } - }); - return done.get(); + std::lock_guard lck(_stats_m); + if (!_stats.processing().muxers().contains(name)) + return false; + else { + *response = _stats.processing().muxers().at(name); + return true; + } } MuxerStats* center::muxer_stats(const std::string& name) { - std::promise p; - _strand.post([&s = this->_stats, &p, &name] { - MuxerStats* ms = &(*s.mutable_processing()->mutable_muxers())[name]; - p.set_value(ms); - }); - return p.get_future().get(); + std::lock_guard lck(_stats_m); + return &(*_stats.mutable_processing()->mutable_muxers())[name]; } void center::get_processing_stats(ProcessingStats* response) { - std::promise p; - _strand.post([&s = this->_stats, &p, response] { - *response = s.processing(); - p.set_value(); - }); - p.get_future().get(); + std::lock_guard lck(_stats_m); + *response = _stats.processing(); } void center::clear_muxer_queue_file(const std::string& name) { - std::promise p; - _strand.post([&s = this->_stats, &p, &name] { - if (s.processing().muxers().contains(name)) - s.mutable_processing() - ->mutable_muxers() - ->at(name) - .mutable_queue_file() - ->Clear(); - p.set_value(); - }); - p.get_future().wait(); + std::lock_guard lck(_stats_m); + if (_stats.processing().muxers().contains(name)) + _stats.mutable_processing() + ->mutable_muxers() + ->at(name) + .mutable_queue_file() + ->Clear(); } diff --git a/broker/core/test/processing/feeder.cc b/broker/core/test/processing/feeder.cc index a820ea72a8b..736ba29d15b 100644 --- a/broker/core/test/processing/feeder.cc +++ b/broker/core/test/processing/feeder.cc @@ -24,6 +24,7 @@ #include "com/centreon/broker/io/events.hh" #include "com/centreon/broker/io/protocols.hh" #include "com/centreon/broker/multiplexing/engine.hh" +#include "com/centreon/broker/pool.hh" #include "com/centreon/broker/stats/center.hh" using namespace com::centreon::broker; diff --git a/broker/lua/test/lua.cc b/broker/lua/test/lua.cc index 5e601b3d049..56bd4affa1e 100644 --- a/broker/lua/test/lua.cc +++ b/broker/lua/test/lua.cc @@ -4504,3 +4504,73 @@ TEST_F(LuaTest, HostStatusObjectMatchBetweenBbdoVersions) { RemoveFile(filename); RemoveFile("/tmp/log"); } + +// When a pb_downtime event arrives +// Then the stream is able to understand it. +TEST_F(LuaTest, PbDowntime) { + config::applier::modules modules; + modules.load_file("./lib/10-neb.so"); + std::map conf; + std::string filename("/tmp/cache_test.lua"); + auto dt{std::make_shared()}; + + auto& downtime = dt->mut_obj(); + downtime.set_id(1u); + downtime.set_host_id(2u); + downtime.set_service_id(3u); + downtime.set_type(Downtime_DowntimeType_SERVICE); + + CreateScript(filename, + "broker_api_version = 1\n" + "function init(conf)\n" + " broker_log:set_parameters(3, '/tmp/log')\n" + "end\n\n" + "function write(d)\n" + " broker_log:info(1, 'downtime is ' .. broker.json_encode(d))\n" + "end\n"); + auto binding{std::make_unique(filename, conf, *_cache)}; + binding->write(dt); + std::string lst(ReadFile("/tmp/log")); + std::cout << lst << std::endl; + ASSERT_NE(lst.find("\"id\":1"), std::string::npos); + ASSERT_NE(lst.find("\"host_id\":2"), std::string::npos); + ASSERT_NE(lst.find("\"service_id\":3"), std::string::npos); + ASSERT_NE(lst.find("\"type\":1"), std::string::npos); + RemoveFile(filename); + RemoveFile("/tmp/log"); +} + +// When a pb_downtime event arrives +// Then the stream is able to understand it. +TEST_F(LuaTest, PbDowntimeV2) { + config::applier::modules modules; + modules.load_file("./lib/10-neb.so"); + std::map conf; + std::string filename("/tmp/cache_test.lua"); + auto dt{std::make_shared()}; + + auto& downtime = dt->mut_obj(); + downtime.set_id(1u); + downtime.set_host_id(2u); + downtime.set_service_id(3u); + downtime.set_type(Downtime_DowntimeType_SERVICE); + + CreateScript(filename, + "broker_api_version = 2\n" + "function init(conf)\n" + " broker_log:set_parameters(3, '/tmp/log')\n" + "end\n\n" + "function write(d)\n" + " broker_log:info(1, 'downtime is ' .. broker.json_encode(d))\n" + "end\n"); + auto binding{std::make_unique(filename, conf, *_cache)}; + binding->write(dt); + std::string lst(ReadFile("/tmp/log")); + std::cout << lst << std::endl; + ASSERT_NE(lst.find("\"id\":1"), std::string::npos); + ASSERT_NE(lst.find("\"host_id\":2"), std::string::npos); + ASSERT_NE(lst.find("\"service_id\":3"), std::string::npos); + ASSERT_NE(lst.find("\"type\":1"), std::string::npos); + RemoveFile(filename); + RemoveFile("/tmp/log"); +} diff --git a/broker/neb/CMakeLists.txt b/broker/neb/CMakeLists.txt index 523f79f6832..6a7f455b8f3 100644 --- a/broker/neb/CMakeLists.txt +++ b/broker/neb/CMakeLists.txt @@ -1,20 +1,12 @@ -# # -# # Copyright 2009-2013,2015 Centreon -# # -# # Licensed under the Apache License, Version 2.0 (the "License"); -# # you may not use this file except in compliance with the License. -# # You may obtain a copy of the License at -# # -# # http://www.apache.org/licenses/LICENSE-2.0 -# # -# # Unless required by applicable law or agreed to in writing, software -# # distributed under the License is distributed on an "AS IS" BASIS, -# # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# # See the License for the specific language governing permissions and -# # limitations under the License. -# # -# # For more information : contact@centreon.com -# # +# # # Copyright 2009-2013,2015 Centreon # # Licensed under the Apache License, +# Version 2.0 (the "License"); # you may not use this file except in compliance +# with the License. # You may obtain a copy of the License at # # +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable +# law or agreed to in writing, software # distributed under the License is +# distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. # See the License for the specific language +# governing permissions and # limitations under the License. # # For more +# information : contact@centreon.com # # Global options. set(INC_DIR "${PROJECT_SOURCE_DIR}/neb/inc") @@ -24,86 +16,93 @@ include_directories("${INC_DIR}") # NEB sources. set(NEB_SOURCES - - # Sources. - # Headers. - ${SRC_DIR}/acknowledgement.cc - ${SRC_DIR}/check.cc - ${SRC_DIR}/comment.cc - ${SRC_DIR}/custom_variable.cc - ${SRC_DIR}/custom_variable_status.cc - ${SRC_DIR}/dependency.cc - ${SRC_DIR}/downtime.cc - ${SRC_DIR}/event_handler.cc - ${SRC_DIR}/flapping_status.cc - ${SRC_DIR}/group.cc - ${SRC_DIR}/group_member.cc - ${SRC_DIR}/host.cc - ${SRC_DIR}/host_check.cc - ${SRC_DIR}/host_dependency.cc - ${SRC_DIR}/host_group.cc - ${SRC_DIR}/host_group_member.cc - ${SRC_DIR}/host_parent.cc - ${SRC_DIR}/host_service.cc - ${SRC_DIR}/host_service_status.cc - ${SRC_DIR}/host_status.cc - ${SRC_DIR}/instance.cc - ${SRC_DIR}/instance_configuration.cc - ${SRC_DIR}/instance_status.cc - ${SRC_DIR}/log_entry.cc - ${SRC_DIR}/module.cc - ${SRC_DIR}/responsive_instance.cc - ${SRC_DIR}/service.cc - ${SRC_DIR}/service_check.cc - ${SRC_DIR}/service_dependency.cc - ${SRC_DIR}/service_group.cc - ${SRC_DIR}/service_group_member.cc - ${SRC_DIR}/service_status.cc - ${SRC_DIR}/status.cc - ${INC_DIR}/com/centreon/broker/neb/acknowledgement.hh - ${INC_DIR}/com/centreon/broker/neb/check.hh - ${INC_DIR}/com/centreon/broker/neb/comment.hh - ${INC_DIR}/com/centreon/broker/neb/custom_variable.hh - ${INC_DIR}/com/centreon/broker/neb/custom_variable_status.hh - ${INC_DIR}/com/centreon/broker/neb/dependency.hh - ${INC_DIR}/com/centreon/broker/neb/downtime.hh - ${INC_DIR}/com/centreon/broker/neb/event_handler.hh - ${INC_DIR}/com/centreon/broker/neb/events.hh - ${INC_DIR}/com/centreon/broker/neb/flapping_status.hh - ${INC_DIR}/com/centreon/broker/neb/group.hh - ${INC_DIR}/com/centreon/broker/neb/group_member.hh - ${INC_DIR}/com/centreon/broker/neb/host.hh - ${INC_DIR}/com/centreon/broker/neb/host_check.hh - ${INC_DIR}/com/centreon/broker/neb/host_dependency.hh - ${INC_DIR}/com/centreon/broker/neb/host_group.hh - ${INC_DIR}/com/centreon/broker/neb/host_group_member.hh - ${INC_DIR}/com/centreon/broker/neb/host_parent.hh - ${INC_DIR}/com/centreon/broker/neb/host_service.hh - ${INC_DIR}/com/centreon/broker/neb/host_service_status.hh - ${INC_DIR}/com/centreon/broker/neb/host_status.hh - ${INC_DIR}/com/centreon/broker/neb/instance.hh - ${INC_DIR}/com/centreon/broker/neb/instance_configuration.hh - ${INC_DIR}/com/centreon/broker/neb/instance_status.hh - ${INC_DIR}/com/centreon/broker/neb/internal.hh - ${INC_DIR}/com/centreon/broker/neb/log_entry.hh - ${INC_DIR}/com/centreon/broker/neb/module.hh - ${INC_DIR}/com/centreon/broker/neb/responsive_instance.hh - ${INC_DIR}/com/centreon/broker/neb/service.hh - ${INC_DIR}/com/centreon/broker/neb/service_check.hh - ${INC_DIR}/com/centreon/broker/neb/service_dependency.hh - ${INC_DIR}/com/centreon/broker/neb/service_group.hh - ${INC_DIR}/com/centreon/broker/neb/service_group_member.hh - ${INC_DIR}/com/centreon/broker/neb/service_status.hh - ${INC_DIR}/com/centreon/broker/neb/status.hh -) + # Sources. + # Headers. + ${SRC_DIR}/acknowledgement.cc + ${SRC_DIR}/check.cc + ${SRC_DIR}/comment.cc + ${SRC_DIR}/custom_variable.cc + ${SRC_DIR}/custom_variable_status.cc + ${SRC_DIR}/dependency.cc + ${SRC_DIR}/downtime.cc + ${SRC_DIR}/event_handler.cc + ${SRC_DIR}/flapping_status.cc + ${SRC_DIR}/group.cc + ${SRC_DIR}/group_member.cc + ${SRC_DIR}/host.cc + ${SRC_DIR}/host_check.cc + ${SRC_DIR}/host_dependency.cc + ${SRC_DIR}/host_group.cc + ${SRC_DIR}/host_group_member.cc + ${SRC_DIR}/host_parent.cc + ${SRC_DIR}/host_service.cc + ${SRC_DIR}/host_service_status.cc + ${SRC_DIR}/host_status.cc + ${SRC_DIR}/instance.cc + ${SRC_DIR}/instance_configuration.cc + ${SRC_DIR}/instance_status.cc + ${SRC_DIR}/log_entry.cc + ${SRC_DIR}/module.cc + ${SRC_DIR}/responsive_instance.cc + ${SRC_DIR}/service.cc + ${SRC_DIR}/service_check.cc + ${SRC_DIR}/service_dependency.cc + ${SRC_DIR}/service_group.cc + ${SRC_DIR}/service_group_member.cc + ${SRC_DIR}/service_status.cc + ${SRC_DIR}/status.cc + ${INC_DIR}/com/centreon/broker/neb/acknowledgement.hh + ${INC_DIR}/com/centreon/broker/neb/check.hh + ${INC_DIR}/com/centreon/broker/neb/comment.hh + ${INC_DIR}/com/centreon/broker/neb/custom_variable.hh + ${INC_DIR}/com/centreon/broker/neb/custom_variable_status.hh + ${INC_DIR}/com/centreon/broker/neb/dependency.hh + ${INC_DIR}/com/centreon/broker/neb/downtime.hh + ${INC_DIR}/com/centreon/broker/neb/event_handler.hh + ${INC_DIR}/com/centreon/broker/neb/events.hh + ${INC_DIR}/com/centreon/broker/neb/flapping_status.hh + ${INC_DIR}/com/centreon/broker/neb/group.hh + ${INC_DIR}/com/centreon/broker/neb/group_member.hh + ${INC_DIR}/com/centreon/broker/neb/host.hh + ${INC_DIR}/com/centreon/broker/neb/host_check.hh + ${INC_DIR}/com/centreon/broker/neb/host_dependency.hh + ${INC_DIR}/com/centreon/broker/neb/host_group.hh + ${INC_DIR}/com/centreon/broker/neb/host_group_member.hh + ${INC_DIR}/com/centreon/broker/neb/host_parent.hh + ${INC_DIR}/com/centreon/broker/neb/host_service.hh + ${INC_DIR}/com/centreon/broker/neb/host_service_status.hh + ${INC_DIR}/com/centreon/broker/neb/host_status.hh + ${INC_DIR}/com/centreon/broker/neb/instance.hh + ${INC_DIR}/com/centreon/broker/neb/instance_configuration.hh + ${INC_DIR}/com/centreon/broker/neb/instance_status.hh + ${INC_DIR}/com/centreon/broker/neb/internal.hh + ${INC_DIR}/com/centreon/broker/neb/log_entry.hh + ${INC_DIR}/com/centreon/broker/neb/module.hh + ${INC_DIR}/com/centreon/broker/neb/responsive_instance.hh + ${INC_DIR}/com/centreon/broker/neb/service.hh + ${INC_DIR}/com/centreon/broker/neb/service_check.hh + ${INC_DIR}/com/centreon/broker/neb/service_dependency.hh + ${INC_DIR}/com/centreon/broker/neb/service_group.hh + ${INC_DIR}/com/centreon/broker/neb/service_group_member.hh + ${INC_DIR}/com/centreon/broker/neb/service_status.hh + ${INC_DIR}/com/centreon/broker/neb/status.hh) # Static library. add_library(nebbase STATIC ${NEB_SOURCES}) -add_dependencies(nebbase table_max_size target_service target_host target_severity target_tag) -target_link_libraries(nebbase +add_dependencies( + nebbase + table_max_size + target_neb_proto + target_host + target_service + target_severity + target_tag) + +target_link_libraries( + nebbase CONAN_PKG::protobuf - pb_service_lib pb_host_lib + pb_service_lib pb_severity_lib pb_tag_lib pb_neb_proto_lib @@ -115,17 +114,13 @@ target_precompile_headers(nebbase PRIVATE precomp_inc/precomp.hpp) # Centreon Broker module. set(NEB "10-neb") -set(NEB "${NEB}" PARENT_SCOPE) -add_library("${NEB}" SHARED - +set(NEB + "${NEB}" + PARENT_SCOPE) +add_library( + "${NEB}" SHARED # Main source. - "${SRC_DIR}/broker.cc" - "${SRC_DIR}/node_id.cc" - "${SRC_DIR}/downtime_map.cc" - - # Inc - "${INC_DIR}/com/centreon/broker/neb/node_id.hh" - "${INC_DIR}/com/centreon/broker/neb/downtime_map.hh" + "${SRC_DIR}/broker.cc" # Inc ) # Flags needed to include all symbols in binary. @@ -134,14 +129,12 @@ target_link_libraries(${NEB} nebbase CONAN_PKG::spdlog) # "-Wl,--whole-archive" nebbase "-Wl,--no-whole-archive") set_target_properties("${NEB}" PROPERTIES PREFIX "") target_precompile_headers(${NEB} REUSE_FROM nebbase) -install(TARGETS "${NEB}" - LIBRARY DESTINATION "${PREFIX_MODULES}" -) +install(TARGETS "${NEB}" LIBRARY DESTINATION "${PREFIX_MODULES}") # Centreon Engine/Nagios module. set(CBMOD "cbmod") -add_library("${CBMOD}" SHARED - +add_library( + "${CBMOD}" SHARED # Sources. "${PROJECT_SOURCE_DIR}/core/src/config/applier/init.cc" "${SRC_DIR}/callback.cc" @@ -150,27 +143,32 @@ add_library("${CBMOD}" SHARED "${SRC_DIR}/internal.cc" "${SRC_DIR}/neb.cc" "${SRC_DIR}/set_log_data.cc" - # Headers. "${INC_DIR}/com/centreon/broker/neb/callback.hh" "${INC_DIR}/com/centreon/broker/neb/callbacks.hh" "${INC_DIR}/com/centreon/broker/neb/initial.hh" "${INC_DIR}/com/centreon/broker/neb/internal.hh" - "${INC_DIR}/com/centreon/broker/neb/set_log_data.hh" -) -get_property(CBMOD_DEFINES + "${INC_DIR}/com/centreon/broker/neb/set_log_data.hh") +get_property( + CBMOD_DEFINES TARGET "${CBMOD}" PROPERTY COMPILE_DEFINITIONS) list(APPEND CBMOD_DEFINES CBMOD) -set_property(TARGET "${CBMOD}" - PROPERTY COMPILE_DEFINITIONS "${CBMOD_DEFINES}") +set_property(TARGET "${CBMOD}" PROPERTY COMPILE_DEFINITIONS "${CBMOD_DEFINES}") if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") # Flags needed to include all symbols in shared library. - target_link_libraries("${CBMOD}" - "-Wl,--whole-archive" "rokerbase" "-Wl,--no-whole-archive" CONAN_PKG::nlohmann_json CONAN_PKG::spdlog CONAN_PKG::asio) + target_link_libraries( + "${CBMOD}" + "-Wl,--whole-archive" + "rokerbase" + "-Wl,--no-whole-archive" + CONAN_PKG::nlohmann_json + CONAN_PKG::spdlog + CONAN_PKG::asio) else() - target_link_libraries("${CBMOD}" "rokerbase" CONAN_PKG::nlohmann_json CONAN_PKG::spdlog CONAN_PKG::asio) + target_link_libraries("${CBMOD}" "rokerbase" CONAN_PKG::nlohmann_json + CONAN_PKG::spdlog CONAN_PKG::asio) endif() set_target_properties("${CBMOD}" PROPERTIES PREFIX "") @@ -178,43 +176,35 @@ target_precompile_headers(${CBMOD} REUSE_FROM nebbase) # Testing. if(WITH_TESTING) - set( - TESTS_SOURCES - ${TESTS_SOURCES} - ${SRC_DIR}/set_log_data.cc - - # Actual tests - ${TEST_DIR}/custom_variable.cc - ${TEST_DIR}/custom_variable_status.cc - ${TEST_DIR}/event_handler.cc - ${TEST_DIR}/flapping_status.cc - ${TEST_DIR}/host.cc - ${TEST_DIR}/host_check.cc - ${TEST_DIR}/host_dependency.cc - ${TEST_DIR}/host_parent.cc - ${TEST_DIR}/host_status.cc - ${TEST_DIR}/instance.cc - ${TEST_DIR}/instance_status.cc - ${TEST_DIR}/log_entry.cc - ${TEST_DIR}/module.cc - ${TEST_DIR}/randomize.cc - ${TEST_DIR}/randomize.hh - ${TEST_DIR}/service.cc - ${TEST_DIR}/service_check.cc - ${TEST_DIR}/service_dependency.cc - ${TEST_DIR}/service_status.cc - ${TEST_DIR}/set_log_data.cc - PARENT_SCOPE - ) - set( - TESTS_LIBRARIES - ${TESTS_LIBRARIES} - ${NEB} - PARENT_SCOPE - ) + set(TESTS_SOURCES + ${TESTS_SOURCES} + ${SRC_DIR}/set_log_data.cc + # Actual tests + ${TEST_DIR}/custom_variable.cc + ${TEST_DIR}/custom_variable_status.cc + ${TEST_DIR}/event_handler.cc + ${TEST_DIR}/flapping_status.cc + ${TEST_DIR}/host.cc + ${TEST_DIR}/host_check.cc + ${TEST_DIR}/host_dependency.cc + ${TEST_DIR}/host_parent.cc + ${TEST_DIR}/host_status.cc + ${TEST_DIR}/instance.cc + ${TEST_DIR}/instance_status.cc + ${TEST_DIR}/log_entry.cc + ${TEST_DIR}/module.cc + ${TEST_DIR}/randomize.cc + ${TEST_DIR}/randomize.hh + ${TEST_DIR}/service.cc + ${TEST_DIR}/service_check.cc + ${TEST_DIR}/service_dependency.cc + ${TEST_DIR}/service_status.cc + ${TEST_DIR}/set_log_data.cc + PARENT_SCOPE) + set(TESTS_LIBRARIES + ${TESTS_LIBRARIES} ${NEB} + PARENT_SCOPE) endif() # Install rules. -install(TARGETS "${CBMOD}" - LIBRARY DESTINATION "${PREFIX_CBMOD}" -) +install(TARGETS "${CBMOD}" LIBRARY DESTINATION "${PREFIX_CBMOD}") diff --git a/broker/neb/inc/com/centreon/broker/neb/callbacks.hh b/broker/neb/inc/com/centreon/broker/neb/callbacks.hh index cd176029aea..e694983d948 100644 --- a/broker/neb/inc/com/centreon/broker/neb/callbacks.hh +++ b/broker/neb/inc/com/centreon/broker/neb/callbacks.hh @@ -34,6 +34,7 @@ int callback_custom_variable(int callback_type, void* data); int callback_pb_custom_variable(int callback_type, void* data); int callback_dependency(int callback_type, void* data); int callback_downtime(int callback_type, void* data); +int callback_pb_downtime(int callback_type, void* data); int callback_event_handler(int callback_type, void* data); int callback_external_command(int callback_type, void* data); int callback_pb_external_command(int callback_type, void* data); diff --git a/broker/neb/inc/com/centreon/broker/neb/downtime_map.hh b/broker/neb/inc/com/centreon/broker/neb/downtime_map.hh deleted file mode 100644 index efdbdbe060b..00000000000 --- a/broker/neb/inc/com/centreon/broker/neb/downtime_map.hh +++ /dev/null @@ -1,63 +0,0 @@ -/* -** Copyright 2009-2013 Centreon -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -** -** For more information : contact@centreon.com -*/ - -#ifndef CCB_NEB_DOWNTIME_MAP_HH -#define CCB_NEB_DOWNTIME_MAP_HH - -#include "com/centreon/broker/namespace.hh" -#include "com/centreon/broker/neb/downtime.hh" -#include "com/centreon/broker/neb/node_id.hh" - -CCB_BEGIN() - -namespace neb { -/** - * @class downtime_map downtime_map.hh - * "com/centreon/broker/neb/downtime_map.hh" - * @brief Map of downtimes. - */ -class downtime_map { - public: - downtime_map(); - downtime_map(downtime_map const& other); - downtime_map& operator=(downtime_map const& other); - virtual ~downtime_map(); - - uint32_t get_new_downtime_id(); - std::list get_all_downtimes_of_node(node_id id) const; - std::list get_all_recurring_downtimes_of_node(node_id id) const; - void delete_downtime(downtime const& dwn); - void add_downtime(downtime const& dwn); - downtime* get_downtime(uint32_t internal_id); - bool is_recurring(uint32_t internal_id) const; - std::list get_all_recurring_downtimes() const; - std::list get_all_downtimes() const; - bool spawned_downtime_exist(uint32_t parent_id) const; - - private: - uint32_t _actual_downtime_id; - std::unordered_map _downtimes; - std::unordered_multimap _downtime_id_by_nodes; - std::unordered_map _recurring_downtimes; - std::unordered_multimap _recurring_downtime_id_by_nodes; -}; -} // namespace neb - -CCB_END() - -#endif // !CCB_NEB_DOWNTIME_MAP_HH diff --git a/broker/neb/inc/com/centreon/broker/neb/internal.hh b/broker/neb/inc/com/centreon/broker/neb/internal.hh index 070fad70253..f0b0d277401 100644 --- a/broker/neb/inc/com/centreon/broker/neb/internal.hh +++ b/broker/neb/inc/com/centreon/broker/neb/internal.hh @@ -52,6 +52,15 @@ extern std::unordered_map, absl::Hash>> gl_acknowledgements; +using pb_downtime = + io::protobuf; + +using pb_host_status = + io::protobuf; +using pb_host = io::protobuf; +using pb_adaptive_host = + io::protobuf; + using pb_service = io::protobuf; using pb_adaptive_service = @@ -61,14 +70,9 @@ using pb_adaptive_service = using pb_service_status = io::protobuf; -using pb_host_status = - io::protobuf; -using pb_host = io::protobuf; -using pb_adaptive_host = - io::protobuf; - using pb_severity = io::protobuf; + using pb_tag = io::protobuf; using pb_comment = diff --git a/broker/neb/inc/com/centreon/broker/neb/node_events_stream.hh b/broker/neb/inc/com/centreon/broker/neb/node_events_stream.hh deleted file mode 100644 index 4d037cb93c7..00000000000 --- a/broker/neb/inc/com/centreon/broker/neb/node_events_stream.hh +++ /dev/null @@ -1,117 +0,0 @@ -/* -** Copyright 2015 Centreon -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -** -** For more information : contact@centreon.com -*/ - -#ifndef CCB_NEB_NODE_EVENTS_STREAM_HH -#define CCB_NEB_NODE_EVENTS_STREAM_HH - -#include "com/centreon/broker/extcmd/command_request.hh" -#include "com/centreon/broker/io/stream.hh" -#include "com/centreon/broker/namespace.hh" -#include "com/centreon/broker/neb/acknowledgement.hh" -#include "com/centreon/broker/neb/downtime.hh" -#include "com/centreon/broker/neb/downtime_map.hh" -#include "com/centreon/broker/neb/downtime_scheduler.hh" -#include "com/centreon/broker/neb/host.hh" -#include "com/centreon/broker/neb/node_cache.hh" -#include "com/centreon/broker/neb/node_id.hh" -#include "com/centreon/broker/neb/service.hh" -#include "com/centreon/broker/persistent_cache.hh" -#include "com/centreon/broker/time/timeperiod.hh" - -CCB_BEGIN() - -namespace neb { -/** - * @class node_events_stream node_events_stream.hh - * "com/centreon/broker/neb/node_events_stream.hh" - * @brief Node events stream. - * - * Manage node events: downtime, acks, etc. - */ -class node_events_stream : public io::stream { - public: - node_events_stream(std::string const& name, - std::shared_ptr cache, - std::string const& config_file); - ~node_events_stream(); - bool read(std::shared_ptr& d, time_t deadline); - void update(); - int write(std::shared_ptr const& d); - void parse_command(extcmd::command_request const& exc, io::stream& stream); - void set_timeperiods( - std::unordered_map const& tps); - - private: - node_events_stream(node_events_stream const& other); - node_events_stream& operator=(node_events_stream const& other); - - std::shared_ptr _cache; - std::string _config_file; - std::string _name; - - // Timeperiods. - std::unordered_map _timeperiods; - - // Host/Service caches. - node_cache _node_cache; - - void _process_host_status(neb::host_status const& hst); - void _process_service_status(neb::service_status const& sst); - void _update_downtime(neb::downtime const& dwn); - void _remove_expired_acknowledgement(node_id node, - timestamp check_time, - short prev_state, - short state); - void _trigger_floating_downtime(node_id node, short state); - - // Acks and downtimes caches. - std::unordered_map _acknowledgements; - std::vector _incomplete_downtime; - downtime_map _downtimes; - downtime_scheduler _downtime_scheduler; - - // Parsing methods. - enum ack_type { ack_host = 0, ack_service }; - - enum down_type { down_service = 1, down_host = 2, down_host_service = 3 }; - void _parse_ack(ack_type type, const char* args, io::stream& stream); - void _parse_remove_ack(ack_type type, const char* args, io::stream& stream); - void _parse_downtime(down_type type, const char* args, io::stream& stream); - void _parse_remove_downtime(down_type type, - const char* args, - io::stream& stream); - void _schedule_downtime(downtime const& dwn); - void _spawn_recurring_downtime(timestamp when, downtime const& dwn); - - // Downtime utility methods. - void _register_downtime(downtime const& d, io::stream* stream); - void _delete_downtime(downtime const& d, timestamp ts, io::stream* stream); - - // Cache and config loading. - void _check_downtime_timeperiod_consistency(); - void _load_config_file(); - void _load_cache(); - void _process_loaded_event(std::shared_ptr const& d); - void _apply_config_downtimes(); - void _save_cache(); -}; -} // namespace neb - -CCB_END() - -#endif // !CCB_NEB_NODE_EVENTS_STREAM_HH diff --git a/broker/neb/inc/com/centreon/broker/neb/node_id.hh b/broker/neb/inc/com/centreon/broker/neb/node_id.hh deleted file mode 100644 index 1e2494f5263..00000000000 --- a/broker/neb/inc/com/centreon/broker/neb/node_id.hh +++ /dev/null @@ -1,92 +0,0 @@ -/* -** Copyright 2011-2013 Centreon -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -** -** For more information : contact@centreon.com -*/ - -#ifndef CCB_NEB_NODE_ID_HH -#define CCB_NEB_NODE_ID_HH - -#include -#include "com/centreon/broker/namespace.hh" - -CCB_BEGIN() - -namespace neb { -/** - * @class node_id node_id.hh "com/centreon/broker/neb/node_id.hh" - * @brief Node id object. - * - * This object contains the id of a node: a host id and an associated - * service id. Both the host id or the service id can be zero for service - * associated with no hosts and inversely. - */ -class node_id { - public: - node_id(); - node_id(node_id const& obj); - node_id& operator=(node_id const& obj); - bool operator==(node_id const& other) const throw(); - explicit node_id(uint64_t host_id, uint64_t service_id = 0); - bool operator<(node_id const& obj) const throw(); - bool operator!=(node_id const& obj) const throw(); - - uint64_t get_host_id() const throw(); - uint64_t get_service_id() const throw(); - bool is_host() const throw(); - bool is_service() const throw(); - node_id to_host() const throw(); - bool empty() const throw(); - - private: - uint64_t _host_id; - uint64_t _service_id; -}; -} // namespace neb - -CCB_END() - -namespace std { -template <> -struct hash { - std::size_t operator()(const com::centreon::broker::neb::node_id& k) const { - uint32_t short_random1 = 842304669U; - uint32_t short_random2 = 619063811U; - uint32_t short_random3 = 937041849U; - uint32_t short_random4 = 3309708029U; - uint32_t value1a = static_cast(k.get_host_id() & 0xffffffff); - uint32_t value1b = - static_cast((k.get_host_id() >> 32) & 0xffffffff); - uint32_t value2a = static_cast(k.get_service_id() & 0xffffffff); - uint32_t value2b = - static_cast((k.get_service_id() >> 32) & 0xffffffff); - uint64_t product1 = static_cast(value1a) * short_random1; - uint64_t product2 = static_cast(value1b) * short_random2; - uint64_t product3 = static_cast(value2a) * short_random3; - uint64_t product4 = static_cast(value2b) * short_random4; - uint64_t hash64 = product1 + product2 + product3 + product4; - if (sizeof(size_t) >= sizeof(uint64_t)) - return static_cast(hash64); - uint64_t odd_random = 1578233944LL << 32 | 194370989LL; - uint32_t shift_random = 20591U << 16; - hash64 = hash64 * odd_random + shift_random; - size_t high_bits = static_cast( - hash64 >> (8 * (sizeof(uint64_t) - sizeof(size_t)))); - return high_bits; - } -}; -} // namespace std - -#endif // !CCB_NEB_NODE_ID_HH diff --git a/broker/neb/src/broker.cc b/broker/neb/src/broker.cc index e3dbbedd6d7..efa64c87ff2 100644 --- a/broker/neb/src/broker.cc +++ b/broker/neb/src/broker.cc @@ -146,6 +146,8 @@ void broker_module_init(void const* arg) { &neb::responsive_instance::operations, neb::responsive_instance::entries); + e.register_event(make_type(io::neb, neb::de_pb_downtime), "Downtime", + &neb::pb_downtime::operations, "downtimes"); e.register_event(make_type(io::neb, neb::de_pb_service), "Service", &neb::pb_service::operations, "services"); e.register_event(make_type(io::neb, neb::de_pb_adaptive_service), diff --git a/broker/neb/src/callbacks.cc b/broker/neb/src/callbacks.cc index 35c90b5de37..147c73f3f92 100644 --- a/broker/neb/src/callbacks.cc +++ b/broker/neb/src/callbacks.cc @@ -101,7 +101,7 @@ static struct { } const gl_pb_callbacks[] = { {NEBCALLBACK_ACKNOWLEDGEMENT_DATA, &neb::callback_acknowledgement}, {NEBCALLBACK_COMMENT_DATA, &neb::callback_pb_comment}, - {NEBCALLBACK_DOWNTIME_DATA, &neb::callback_downtime}, + {NEBCALLBACK_DOWNTIME_DATA, &neb::callback_pb_downtime}, {NEBCALLBACK_EVENT_HANDLER_DATA, &neb::callback_event_handler}, {NEBCALLBACK_EXTERNAL_COMMAND_DATA, &neb::callback_pb_external_command}, {NEBCALLBACK_FLAPPING_DATA, &neb::callback_flapping_status}, @@ -790,7 +790,7 @@ int neb::callback_downtime(int callback_type, void* data) { try { // In/Out variables. - std::shared_ptr downtime(std::make_shared()); + auto downtime{std::make_shared()}; // Fill output var. if (downtime_data->author_name) @@ -876,6 +876,119 @@ int neb::callback_downtime(int callback_type, void* data) { return 0; } +/** + * @brief Function that processes downtime data. + * + * This function is called by Nagios when some downtime data are available. + * + * @param[in] callback_type Type of the callback (NEBCALLBACK_DOWNTIME_DATA). + * @param[in] data A pointer to a nebstruct_downtime_data containing + * the downtime data. + * + * @return 0 on success. + */ +int neb::callback_pb_downtime(int callback_type, void* data) { + // Log message. + log_v2::neb()->info("callbacks: generating pb downtime event"); + (void)callback_type; + + const nebstruct_downtime_data* downtime_data = + static_cast(data); + if (downtime_data->type == NEBTYPE_DOWNTIME_LOAD) + return 0; + + // In/Out variables. + auto d{std::make_shared()}; + Downtime& downtime = d.get()->mut_obj(); + + // Fill output var. + if (downtime_data->author_name) + downtime.set_author( + misc::string::check_string_utf8(downtime_data->author_name)); + if (downtime_data->comment_data) + downtime.set_comment_data( + misc::string::check_string_utf8(downtime_data->comment_data)); + downtime.set_id(downtime_data->downtime_id); + downtime.set_type( + static_cast(downtime_data->downtime_type)); + downtime.set_duration(downtime_data->duration); + downtime.set_end_time(downtime_data->end_time); + downtime.set_entry_time(downtime_data->entry_time); + downtime.set_fixed(downtime_data->fixed); + if (!downtime_data->host_name) { + log_v2::neb()->error( + "callbacks: error occurred while generating downtime event: unnamed " + "host"); + return 0; + } + if (downtime_data->service_description) { + std::pair p; + p = engine::get_host_and_service_id(downtime_data->host_name, + downtime_data->service_description); + downtime.set_host_id(p.first); + downtime.set_service_id(p.second); + if (!downtime.host_id() || !downtime.service_id()) { + log_v2::neb()->error( + "callbacks: error occurred while generating downtime event: " + "could not find ID of service ('{}', '{}')", + downtime_data->host_name, downtime_data->service_description); + return 0; + } + } else { + downtime.set_host_id(engine::get_host_id(downtime_data->host_name)); + if (downtime.host_id() == 0) + log_v2::neb()->error( + "callbacks: error occurred while generating downtime event: " + "could not find ID of host '{}'", + downtime_data->host_name); + return 0; + } + downtime.set_instance_id(config::applier::state::instance().poller_id()); + downtime.set_start_time(downtime_data->start_time); + downtime.set_triggered_by(downtime_data->triggered_by); + private_downtime_params& params = downtimes[downtime.id()]; + switch (downtime_data->type) { + case NEBTYPE_DOWNTIME_ADD: + params.cancelled = false; + params.deletion_time = -1; + params.end_time = -1; + params.started = false; + params.start_time = -1; + break; + case NEBTYPE_DOWNTIME_START: + params.started = true; + params.start_time = downtime_data->timestamp.tv_sec; + break; + case NEBTYPE_DOWNTIME_STOP: + if (NEBATTR_DOWNTIME_STOP_CANCELLED == downtime_data->attr) + params.cancelled = true; + params.end_time = downtime_data->timestamp.tv_sec; + break; + case NEBTYPE_DOWNTIME_DELETE: + if (!params.started) + params.cancelled = true; + params.deletion_time = downtime_data->timestamp.tv_sec; + break; + default: + log_v2::neb()->error( + "callbacks: error occurred while generating downtime event: " + "Downtime with not managed type {}.", + downtime_data->host_name); + return 0; + } + downtime.set_actual_start_time(params.start_time); + downtime.set_actual_end_time(params.end_time); + downtime.set_deletion_time(params.deletion_time); + downtime.set_cancelled(params.cancelled); + downtime.set_started(params.started); + if (NEBTYPE_DOWNTIME_DELETE == downtime_data->type) + downtimes.erase(downtime.id()); + + // Send event. + gl_publisher.write(d); + return 0; +} + /** * @brief Function that process event handler data. * diff --git a/broker/neb/src/downtime_map.cc b/broker/neb/src/downtime_map.cc deleted file mode 100644 index bf12a0fb801..00000000000 --- a/broker/neb/src/downtime_map.cc +++ /dev/null @@ -1,247 +0,0 @@ -/* -** Copyright 2009-2013 Centreon -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -** -** For more information : contact@centreon.com -*/ - -#include "com/centreon/broker/neb/downtime_map.hh" - -using namespace com::centreon::broker; -using namespace com::centreon::broker::neb; - -/** - * Default constructor. - */ -downtime_map::downtime_map() : _actual_downtime_id{1} {} - -/** - * Copy constructor. - * - * @param[in] other The object to copy. - */ -downtime_map::downtime_map(downtime_map const& other) - : _actual_downtime_id(other._actual_downtime_id), - _downtimes(other._downtimes), - _downtime_id_by_nodes(other._downtime_id_by_nodes), - _recurring_downtimes(other._recurring_downtimes), - _recurring_downtime_id_by_nodes(other._recurring_downtime_id_by_nodes) {} - -/** - * Assignment operator. - * - * @param(in] other The object to copy. - * - * @return Reference to this object. - */ -downtime_map& downtime_map::operator=(downtime_map const& other) { - if (this != &other) { - _actual_downtime_id = other._actual_downtime_id; - _downtimes = other._downtimes; - _downtime_id_by_nodes = other._downtime_id_by_nodes; - _recurring_downtimes = other._recurring_downtimes; - _recurring_downtime_id_by_nodes = other._recurring_downtime_id_by_nodes; - } - return *this; -} - -/** - * Destructor. - */ -downtime_map::~downtime_map() {} - -/** - * Get a new downtime id. - * - * @return A new downtime id. - */ -uint32_t downtime_map::get_new_downtime_id() { - return _actual_downtime_id++; -} - -/** - * Get all the downtimes of a node. - * - * @param[in] id The id of the node. - * - * @return A list of downtimes of this node. - */ -std::list downtime_map::get_all_downtimes_of_node(node_id id) const { - std::list ret; - auto range(_downtime_id_by_nodes.equal_range(id)); - - for (std::unordered_multimap::const_iterator - it(range.first), - end(range.second); - it != end; ++it) - ret.push_back(_downtimes.at(it->second)); - return ret; -} - -/** - * Get all the recurring downtimes of a node. - * - * @param[in] id The id of the node. - * - * @return A list of downtimes of this node. - */ -std::list downtime_map::get_all_recurring_downtimes_of_node( - node_id id) const { - std::list ret; - auto range(_recurring_downtime_id_by_nodes.equal_range(id)); - - for (std::unordered_multimap::const_iterator - it{range.first}, - end{range.second}; - it != end; ++it) - ret.push_back(_recurring_downtimes.at(it->second)); - return ret; -} - -/** - * Delete a downtime. - * - * @param[in] internal_id The id of the downtime to remove. - */ -void downtime_map::delete_downtime(downtime const& dwn) { - _downtimes.erase(dwn.internal_id); - - node_id id{dwn.host_id, dwn.service_id}; - auto range(_downtime_id_by_nodes.equal_range(id)); - for (std::unordered_multimap::const_iterator - it(range.first), - end(range.second); - it != end; ++it) - if (it->second == dwn.internal_id) { - _downtime_id_by_nodes.erase(it); - break; - } - - _recurring_downtimes.erase(dwn.internal_id); - - range = _recurring_downtime_id_by_nodes.equal_range(id); - for (std::unordered_multimap::const_iterator - it{range.first}, - end{range.second}; - it != end; ++it) - if (it->second == dwn.internal_id) { - _recurring_downtime_id_by_nodes.erase(it); - break; - } -} - -/** - * Add a downtime. - * - * @param[in] dwn The downtime to add. - */ -void downtime_map::add_downtime(downtime const& dwn) { - if (!dwn.is_recurring) { - _downtimes.insert({dwn.internal_id, dwn}); - _downtime_id_by_nodes.insert( - {node_id(dwn.host_id, dwn.service_id), dwn.internal_id}); - } else { - _recurring_downtimes.insert({dwn.internal_id, dwn}); - _recurring_downtime_id_by_nodes.insert( - {node_id(dwn.host_id, dwn.service_id), dwn.internal_id}); - } - - if (_actual_downtime_id < dwn.internal_id) - _actual_downtime_id = dwn.internal_id + 1; -} - -/** - * Get a downtime from its internal id. - * - * @param[in] internal_id The internal id. - * - * @return Pointer to this downtime, or a null pointer. - */ -downtime* downtime_map::get_downtime(uint32_t internal_id) { - std::unordered_map::iterator found{ - _downtimes.find(internal_id)}; - if (found != _downtimes.end()) - return &found->second; - - found = _recurring_downtimes.find(internal_id); - if (found != _recurring_downtimes.end()) - return &found->second; - - return nullptr; -} - -/** - * Is this downtime recurring? - * - * @param[in] internal_id The id of the downtime. - * - * @return True or false. - */ -bool downtime_map::is_recurring(uint32_t internal_id) const { - std::unordered_map::const_iterator found{ - _recurring_downtimes.find(internal_id)}; - return found != _recurring_downtimes.end(); -} - -/** - * Get all the recurring downtimes. - * - * @return The recurring downtimes. - */ -std::list downtime_map::get_all_recurring_downtimes() const { - std::list retval; - for (std::unordered_map::const_iterator - it{_recurring_downtimes.begin()}, - end{_recurring_downtimes.end()}; - it != end; ++it) - retval.push_back(it->second); - return retval; -} - -/** - * Get all the downtimes. - * - * @return The downtimes. - */ -std::list downtime_map::get_all_downtimes() const { - std::list ret; - for (std::unordered_map::const_iterator - it{_recurring_downtimes.begin()}, - end{_recurring_downtimes.end()}; - it != end; ++it) - ret.push_back(it->second); - for (std::unordered_map::const_iterator - it{_downtimes.begin()}, - end{_downtimes.end()}; - it != end; ++it) - ret.push_back(it->second); - return ret; -} - -/** - * Return true if a spawned downtime exist. - * - * @param[in] parent_id The id of the parent downtime. - * - * @return True if a spawned downtime exist. - */ -bool downtime_map::spawned_downtime_exist(uint32_t parent_id) const { - for (std::unordered_map::const_iterator - it{_downtimes.begin()}, - end{_downtimes.end()}; - it != end; ++it) - if (it->second.triggered_by == parent_id) - return true; - return false; -} diff --git a/broker/neb/src/initial.cc b/broker/neb/src/initial.cc index 89692eb1013..0d8591acdf7 100644 --- a/broker/neb/src/initial.cc +++ b/broker/neb/src/initial.cc @@ -134,7 +134,7 @@ static void send_downtimes_list() { com::centreon::engine::downtimes::downtime_manager::instance() .get_scheduled_downtimes()}; // Iterate through all downtimes. - for (auto p : dts) { + for (const auto& p : dts) { // Fill callback struct. nebstruct_downtime_data nsdd; memset(&nsdd, 0, sizeof(nsdd)); diff --git a/broker/neb/src/node_id.cc b/broker/neb/src/node_id.cc deleted file mode 100644 index 75a8752b369..00000000000 --- a/broker/neb/src/node_id.cc +++ /dev/null @@ -1,144 +0,0 @@ -/* -** Copyright 2014 Centreon -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -** -** For more information : contact@centreon.com -*/ - -#include "com/centreon/broker/neb/node_id.hh" - -using namespace com::centreon::broker::neb; - -/** - * Default constructor. - */ -node_id::node_id() : _host_id(0), _service_id(0) {} - -/** - * Copy constructor. - * - * @param[in] obj The object to copy. - */ -node_id::node_id(node_id const& obj) { - node_id::operator=(obj); -} - -/** - * Assignment operator. - * - * @param[in] obj The object to copy. - * - * @return A reference to this object. - */ -node_id& node_id::operator=(node_id const& obj) { - if (this != &obj) { - _host_id = obj._host_id; - _service_id = obj._service_id; - } - return (*this); -} - -/** - * Operator == for node_id objects - * - * @param other - * - * @return a boolean - */ -bool node_id::operator==(node_id const& other) const throw() { - return _host_id == other._host_id && _service_id == other._service_id; -} - -/** - * Constructor given host and service id. - * - * @param[in] host_id The host id of this node. 0 if none. - * @param[in] service_id The service id of this node. 0 if none. - */ -node_id::node_id(uint64_t host_id, uint64_t service_id) - : _host_id{host_id}, _service_id{service_id} {} - -/** - * Comparison operator. - * - * @param obj The object to compare with. - * - * @return True if this object is lesser than the other. - */ -bool node_id::operator<(node_id const& obj) const throw() { - if (_host_id != obj._host_id) - return (_host_id < obj._host_id); - else - return (_service_id < obj._service_id); -} - -/** - * Inequality operator. - * - * @param[in] obj The object to compare with. - * - * @return True if the objects are inequal. - */ -bool node_id::operator!=(node_id const& obj) const throw() { - return (!node_id::operator==(obj)); -} - -/** - * Get the host id of this node. 0 if none. - * - * @return The host id of this node. 0 if none. - */ -uint64_t node_id::get_host_id() const throw() { - return _host_id; -} - -/** - * Get the service id of this node. 0 if none. - * - * @return The service id of this node. 0 if none. - */ -uint64_t node_id::get_service_id() const throw() { - return _service_id; -} - -/** - * Is this node a host? - * - * @return True if this node is a host. - */ -bool node_id::is_host() const throw() { - return (_service_id == 0); -} - -/** - * Is this node a service? - * - * @return True if this node is a service. - */ -bool node_id::is_service() const throw() { - return (_service_id != 0); -} - -/** - * Return the node_id of the host associated with this node. - * - * @return The node_id of the host associated with this node. - */ -node_id node_id::to_host() const throw() { - return (node_id(_host_id)); -} - -bool node_id::empty() const throw() { - return (_host_id == 0 && _service_id == 0); -} diff --git a/broker/test/db_cfg.cc b/broker/test/db_cfg.cc deleted file mode 100644 index 5bf85a9b2c8..00000000000 --- a/broker/test/db_cfg.cc +++ /dev/null @@ -1,322 +0,0 @@ -/* -** Copyright 2015 Centreon -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -** -** For more information : contact@centreon.com -*/ - -#include -#include -#include -#include -#include -#include -#include "com/centreon/broker/exceptions/msg.hh" -#include "test/broker_extcmd.hh" -#include "test/cbd.hh" -#include "test/config.hh" -#include "test/misc.hh" -#include "test/vars.hh" - -#define READ_DB_NAME "broker_db_cfg1" -#define WRITE_DB_NAME "broker_db_cfg2" - -using namespace com::centreon::broker; - -struct ba_entry { - uint32_t ba_id; - std::string name; - int warning; - int critical; -}; -struct kpi_entry { - uint32_t kpi_id; - int kpi_type; - uint32_t host_id; - uint32_t service_id; - uint32_t id_indicator_ba; - uint32_t id_ba; - uint32_t meta_id; - uint32_t boolean_id; - int drop_warning; - int drop_critical; - int drop_unknown; -}; - -/** - * Check BA entries in database. - * - * @param[in] db Database. - * @param[in] entries Expected entries. - */ -static void check_bas(test_db& db, ba_entry const* entries) { - QSqlQuery q(*db.centreon_db()); - if (!q.exec("SELECT ba_id, name, level_w, level_c, activate" - " FROM cfg_bam" - " ORDER BY ba_id ASC")) - throw(exceptions::msg() - << "could not retrieve BAs from DB: " << q.lastError().text()); - for (int i(0); entries[i].ba_id; ++i) { - if (!q.next()) - throw(exceptions::msg() << "not enough BA entries in DB"); - if ((q.value(0).toUInt() != entries[i].ba_id) || - (q.value(1).toString().toStdString() != entries[i].name) || - (q.value(2).toInt() != entries[i].warning) || - (q.value(3).toInt() != entries[i].critical) || !q.value(4).toBool()) - throw(exceptions::msg() - << "invalid BA entry: got (BA ID " << q.value(0).toUInt() - << ", name '" << q.value(1).toString() << "', warning " - << q.value(2).toInt() << ", critical " << q.value(3).toInt() - << "), expected (" << entries[i].ba_id << ", '" << entries[i].name - << "', " << entries[i].warning << ", " << entries[i].critical - << ")"); - } - if (q.next()) - throw(exceptions::msg() << "too much BA entries in DB"); - return; -} - -/** - * Check KPI entries in database. - * - * @param[in] db Database. - * @param[in] entries Expected entries. - */ -static void check_kpis(test_db& db, kpi_entry const* entries) { - QSqlQuery q(*db.centreon_db()); - if (!q.exec("SELECT kpi_id, kpi_type, host_id, service_id," - " id_indicator_ba, id_ba, meta_id, boolean_id," - " drop_warning, drop_critical, drop_unknown," - " activate" - " FROM cfg_bam_kpi" - " ORDER BY kpi_id ASC")) - throw(exceptions::msg() - << "could not retrieve KPIs from DB: " << q.lastError().text()); - for (int i(0); entries[i].kpi_id; ++i) { - if (!q.next()) - throw(exceptions::msg() << "not enough KPI entries in DB"); - if ((q.value(0).toUInt() != entries[i].kpi_id) || - (q.value(1).toInt() != entries[i].kpi_type) || - (q.value(2).toUInt() != entries[i].host_id) || - (q.value(3).toUInt() != entries[i].service_id) || - (q.value(4).toUInt() != entries[i].id_indicator_ba) || - (q.value(5).toUInt() != entries[i].id_ba) || - (q.value(6).toUInt() != entries[i].meta_id) || - (q.value(7).toUInt() != entries[i].boolean_id) || - (q.value(8).toInt() != entries[i].drop_warning) || - (q.value(9).toInt() != entries[i].drop_critical) || - (q.value(10).toInt() != entries[i].drop_unknown) || - !q.value(11).toBool()) - throw(exceptions::msg() - << "invalid KPI entry: got (KPI ID " << q.value(0).toUInt() - << ", type " << q.value(1).toInt() << ", host ID " - << q.value(2).toUInt() << ", service ID " << q.value(3).toUInt() - << ", ID indicator BA " << q.value(4).toUInt() << ", ID BA " - << q.value(5).toUInt() << ", meta ID " << q.value(6).toUInt() - << ", boolean ID " << q.value(7).toUInt() << ", drop warning " - << q.value(8).toInt() << ", drop critical " << q.value(9).toInt() - << ", drop unknown " << q.value(10).toInt() << "), expected (" - << entries[i].kpi_id << ", " << entries[i].kpi_type << ", " - << entries[i].host_id << ", " << entries[i].service_id << ", " - << entries[i].id_indicator_ba << ", " << entries[i].id_ba << ", " - << entries[i].meta_id << ", " << entries[i].boolean_id << ", " - << entries[i].drop_warning << ", " << entries[i].drop_critical - << ", " << entries[i].drop_unknown << ")"); - } - if (q.next()) - throw(exceptions::msg() << "too much KPI entries in DB"); - return; -} - -/** - * Check that DB configuration synchronisation work properly. - * - * @return EXIT_SUCCESS on success. - */ -int main() { - // Error flag. - bool error(true); - - // Variables that need cleaning. - cbd db_reader; - cbd db_writer; - test_db db_to_read; - test_db db_to_write; - broker_extcmd commander; - - try { - // Prepare databases. - db_to_read.open(READ_DB_NAME, NULL, true); - db_to_write.open(WRITE_DB_NAME, NULL, true); - - // Populate database. - { - char const* queries[] = { - "INSERT INTO cfg_organizations (organization_id, name," - " shortname)" - " VALUES (42, '42', '42')", - "INSERT INTO cfg_nodes (node_id, name, ip_address, enable," - " multiple_poller)" - " VALUES (1, 'MyPollerNode1', 'localhost', 1, 0)," - " (2, 'MyPollerNode2', 'remotehost', 1, 0)", - "INSERT INTO cfg_pollers (poller_id, node_id, organization_id," - " name, port, tmpl_name, enable)" - " VALUES (42, 1, 42, 'MyPoller1', 0, '', 1)," - " (43, 2, 42, 'MyPoller2', 0, '', 1)", - "INSERT INTO cfg_bam_ba_types (ba_type_id, name, slug," - " description)" - " VALUES (1, 'Default', 'default', 'Default type')", - "INSERT INTO cfg_bam (ba_id, name, level_w, level_c, activate," - " ba_type_id, organization_id)" - " VALUES (1, 'BA1', 90, 80, '1', 1, 42)," - " (2, 'BA2', 80, 70, '1', 1, 42)," - " (3, 'BA3', 70, 60, '1', 1, 42)," - " (4, 'BA4', 60, 50, '1', 1, 42)," - " (5, 'BA5', 50, 40, '1', 1, 42)," - " (6, 'BA6', 40, 30, '1', 1, 42)," - " (7, 'BA7', 30, 20, '1', 1, 42)," - " (8, 'BA8', 20, 10, '1', 1, 42)," - " (9, 'BA9', 10, 0, '1', 1, 42)," - " (1001, 'BA1001', 50, 50, '1', 1, 42)", - "INSERT INTO cfg_bam_poller_relations (ba_id, poller_id)" - " VALUES (1, 43), (2, 43), (3, 43), (4, 43), (5, 43)," - " (6, 43), (7, 43), (8, 43), (9, 43), (1001, 42)", - "INSERT INTO cfg_bam_kpi (kpi_id, kpi_type, host_id," - " service_id, id_indicator_ba, id_ba, config_type," - " drop_warning, drop_critical, drop_unknown," - " activate)" - " VALUES (1, '0', 3, 2, NULL, 1, '0', 10, 20, 30, '1')," - " (2, '0', 4, 3, NULL, 2, '0', 20, 30, 40, '1')," - " (3, '0', 5, 4, NULL, 3, '0', 30, 40, 50, '1')," - " (4, '0', 6, 5, NULL, 4, '0', 40, 50, 60, '1')," - " (5, '1', NULL, NULL, 6, 5, '0', 50, 60, 70, '1')", - NULL}; - QSqlQuery q(*db_to_read.centreon_db()); - for (int i(0); queries[i]; ++i) { - if (!q.exec(queries[i])) - throw(exceptions::msg() - << "could not run population query: " << q.lastError().text()); - } - } - - // Prepare config files. - commander.set_file(tmpnam(NULL)); - test_file db_reader_cfg; - db_reader_cfg.set_template(PROJECT_SOURCE_DIR "/test/cfg/db_cfg_1.xml.in"); - db_reader_cfg.set("DB_NAME", READ_DB_NAME); - db_reader_cfg.set("COMMAND_FILE", commander.get_file()); - test_file db_writer_cfg; - db_writer_cfg.set_template(PROJECT_SOURCE_DIR "/test/cfg/db_cfg_2.xml.in"); - db_writer_cfg.set("DB_NAME", WRITE_DB_NAME); - - // Run Brokers. - db_writer.set_config_file(db_writer_cfg.generate()); - db_writer.start(); - sleep_for(2); - db_reader.set_config_file(db_reader_cfg.generate()); - db_reader.start(); - sleep_for(2); - - // Full synchronization. - commander.execute("EXECUTE;84;dbcfg1-dbreader;SYNC_CFG_DB;43"); - sleep_for(3); - - // Check database. - { - ba_entry const bas[] = {{1, "BA1", 90, 80}, {2, "BA2", 80, 70}, - {3, "BA3", 70, 60}, {4, "BA4", 60, 50}, - {5, "BA5", 50, 40}, {6, "BA6", 40, 30}, - {7, "BA7", 30, 20}, {8, "BA8", 20, 10}, - {9, "BA9", 10, 0}, {0, "", 0, 0}}; - check_bas(db_to_write, bas); - } - { - kpi_entry const kpis[] = {{1, 0, 3, 2, 0, 1, 0, 0, 10, 20, 30}, - {2, 0, 4, 3, 0, 2, 0, 0, 20, 30, 40}, - {3, 0, 5, 4, 0, 3, 0, 0, 30, 40, 50}, - {4, 0, 6, 5, 0, 4, 0, 0, 40, 50, 60}, - {5, 1, 0, 0, 6, 5, 0, 0, 50, 60, 70}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; - check_kpis(db_to_write, kpis); - } - - // Change database entries. - { - char const* queries[] = { - "INSERT INTO cfg_bam (ba_id, name, level_w, level_c, activate," - " ba_type_id, organization_id)" - " VALUES (10, 'BA10', 75, 50, 1, 1, 42)", - "INSERT INTO cfg_bam_poller_relations (ba_id, poller_id)" - " VALUES (10, 43)", - "INSERT INTO cfg_bam_kpi (kpi_id, kpi_type, host_id," - " service_id, id_indicator_ba, id_ba, config_type," - " drop_warning, drop_critical, drop_unknown," - " activate)" - " VALUES (6, '0', 7, 6, NULL, 8, '0', 15, 25, 35, '1')," - " (7, '1', NULL, NULL, 10, 9, '0', 45, 55, 65, '1')", - "UPDATE cfg_bam SET name='SuperBA', level_w=42 WHERE ba_id=3", - "UPDATE cfg_bam_kpi SET kpi_type='1', host_id=NULL," - " service_id=NULL, id_indicator_ba=4" - " WHERE kpi_id=3", - "DELETE FROM cfg_bam WHERE ba_id=1 OR ba_id=7", - "DELETE FROM cfg_bam_kpi WHERE kpi_id=2", - NULL}; - QSqlQuery q(*db_to_read.centreon_db()); - for (int i(0); queries[i]; ++i) { - if (!q.exec(queries[i])) - throw(exceptions::msg() << "could not change database entries: " - << q.lastError().text()); - } - } - - // Diff synchronization. - commander.execute("EXECUTE;84;dbcfg1-dbreader;UPDATE_CFG_DB;43"); - sleep_for(3); - - // Check database. - { - ba_entry const bas[] = { - {2, "BA2", 80, 70}, {3, "SuperBA", 42, 60}, {4, "BA4", 60, 50}, - {5, "BA5", 50, 40}, {6, "BA6", 40, 30}, {8, "BA8", 20, 10}, - {9, "BA9", 10, 0}, {10, "BA10", 75, 50}, {0, "", 0, 0}}; - check_bas(db_to_write, bas); - } - { - kpi_entry const kpis[] = {{3, 1, 0, 0, 4, 3, 0, 0, 30, 40, 50}, - {4, 0, 6, 5, 0, 4, 0, 0, 40, 50, 60}, - {5, 1, 0, 0, 6, 5, 0, 0, 50, 60, 70}, - {6, 0, 7, 6, 0, 8, 0, 0, 15, 25, 35}, - {7, 1, 0, 0, 10, 9, 0, 0, 45, 55, 65}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; - check_kpis(db_to_write, kpis); - } - - // Success. - error = false; - } catch (std::exception const& e) { - db_to_read.set_remove_db_on_close(false); - db_to_write.set_remove_db_on_close(false); - std::cerr << e.what() << std::endl; - } catch (...) { - db_to_read.set_remove_db_on_close(false); - db_to_write.set_remove_db_on_close(false); - std::cerr << "unknown exception" << std::endl; - } - - // Cleanup. - db_reader.stop(); - db_writer.stop(); - - return (error ? EXIT_FAILURE : EXIT_SUCCESS); -} diff --git a/broker/test/notification.cc b/broker/test/notification.cc deleted file mode 100644 index 79b06b895f2..00000000000 --- a/broker/test/notification.cc +++ /dev/null @@ -1,710 +0,0 @@ -/* -** Copyright 2014-2015 Centreon -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -** -** For more information : contact@centreon.com -*/ - -#include "com/centreon/broker/exceptions/msg.hh" -#include "test/broker_extcmd.hh" -#include "test/config.hh" -#include "test/engine.hh" -#include "test/engine_extcmd.hh" -#include "test/generate.hh" -#include "test/misc.hh" -#include "test/vars.hh" - -using namespace com::centreon::broker; - -#define DB_NAME "broker_notification" -#define UTIL_FILE_WRITER PROJECT_SOURCE_DIR "/build/util_write_into_file" -#define TIME_MACROS "$LONGDATETIME$\n$SHORTDATETIME$\n$DATE$\n$TIME$\n$TIMET$\n" -#define HOST_MACROS \ - "$HOSTNAME$\n$HOSTALIAS$\n$HOSTADDRESS$\n$HOSTSTATE$\n" \ - "$HOSTSTATEID$\n$HOSTSTATETYPE$\n$HOSTATTEMPT$\n$MAXHOSTATTEMPTS$\n$" \ - "HOSTLATENCY$\n" \ - "$HOSTEXECUTIONTIME$\n$HOSTDURATION$\n$HOSTDURATIONSEC$\n$HOSTDOWNTIME$\n" \ - "$HOSTPERCENTCHANGE$\n$HOSTGROUPNAME$\n$HOSTGROUPNAMES$\n$LASTHOSTCHECK$\n" \ - "$LASTHOSTSTATECHANGE$\n$LASTHOSTUP$\n$LASTHOSTDOWN$\n" \ - "$LASTHOSTUNREACHABLE$\n$HOSTOUTPUT$\n$LONGHOSTOUTPUT$\n$HOSTPERFDATA$\n" \ - "$HOSTCHECKCOMMAND$\n$TOTALHOSTSERVICES$\n$TOTALHOSTSERVICESOK$\n" \ - "$TOTALHOSTSERVICESWARNING$\n$TOTALHOSTSERVICESUNKNOWN$\n" \ - "$TOTALHOSTSERVICESCRITICAL$\n" -#define SERVICE_MACROS \ - "$SERVICEDESC$\n$SERVICESTATE$\n$SERVICESTATEID$\n" \ - "$LASTSERVICESTATE$\n$LASTSERVICESTATEID$\n$SERVICESTATETYPE$\n" \ - "$SERVICEATTEMPT$\n$MAXSERVICEATTEMPTS$\n$SERVICEISVOLATILE$\n" \ - "$SERVICELATENCY$\n$SERVICEEXECUTIONTIME$\n$SERVICEDURATION$\n" \ - "$SERVICEDURATIONSEC$\n$SERVICEDOWNTIME$\n$SERVICEPERCENTCHANGE$\n" \ - "$SERVICEGROUPNAME$\n$SERVICEGROUPNAMES$\n$LASTSERVICECHECK$\n" \ - "$LASTSERVICESTATECHANGE$\n$LASTSERVICEOK$\n$LASTSERVICEWARNING$\n" \ - "$LASTSERVICEUNKNOWN$\n$LASTSERVICECRITICAL$\n$SERVICEOUTPUT$\n" \ - "$LONGSERVICEOUTPUT$\n$SERVICEPERFDATA$\n$SERVICECHECKCOMMAND$\n" - -#define COUNTING_MACROS \ - "$TOTALHOSTSUP$\n$TOTALHOSTSDOWN$\n$TOTALHOSTSUNREACHABLE$\n" \ - "$TOTALHOSTSDOWNUNHANDLED$\n$TOTALHOSTSUNREACHABLEUNHANDLED$\n" \ - "$TOTALHOSTPROBLEMS$\n$TOTALHOSTPROBLEMSUNHANDLED$\n$TOTALSERVICESOK$\n" \ - "$TOTALSERVICESWARNING$\n$TOTALSERVICESCRITICAL$\n$TOTALSERVICESUNKNOWN$\n" \ - "$TOTALSERVICESWARNINGUNHANDLED$\n$TOTALSERVICESCRITICALUNHANDLED$\n" \ - "$TOTALSERVICESUNKNOWNUNHANDLED$\n$TOTALSERVICEPROBLEMS$\n" \ - "$TOTALSERVICEPROBLEMSUNHANDLED$\n" - -#define GROUP_MACROS \ - "$HOSTGROUPALIAS$\n$HOSTGROUPMEMBERS$\n$SERVICEGROUPALIAS$\n$" \ - "SERVICEGROUPMEMBERS$\n" - -#define CONTACT_MACROS \ - "$CONTACTNAME$\n$CONTACTALIAS$\n$CONTACTEMAIL$\n$CONTACTPAGER$\n" \ - "$CONTACTADDRESS1$\n$CONTACTADDRESS2$\n$CONTACTADDRESS3$\n" \ - "$CONTACTADDRESS4$\n$CONTACTADDRESS5$\n$CONTACTADDRESS6$\n" \ - "$CONTACTGROUPALIAS$\n$CONTACTGROUPMEMBERS$\n" - -#define NOTIFICATION_MACROS \ - "$NOTIFICATIONTYPE$\n$NOTIFICATIONRECIPIENTS$\n$HOSTNOTIFICATIONNUMBER$\n" \ - "$SERVICENOTIFICATIONNUMBER$\n" - -#define MACRO_LIST \ - "\"" TIME_MACROS HOST_MACROS SERVICE_MACROS COUNTING_MACROS \ - NOTIFICATION_MACROS GROUP_MACROS CONTACT_MACROS "\"" - -#define RECOVERY_FILE_CONTENT "\"$NOTIFICATIONTYPE$\n\"" - -#define DOWNTIME_FILE_CONTENT "\"$NOTIFICATIONTYPE$\n\"" - -#define ACK_FILE_CONTENT "\"$NOTIFICATIONTYPE$\n\"" - -static const double epsilon = 0.000000001; -static time_t start; -static time_t now; - -struct macros_struct { - enum macro_type { null, string, integer, function, between }; - - macro_type type; - - // Not using an union because no designated initializer in the C++ standard. - const char* str; - int num; - bool (*f)(std::string const&); - double value1; - double value2; - - const char* macro_name; -}; - -/** - * Del a c string and dup another. - * - * @param[out] str The string to del. - * @param[in] format The format of the string to dup. - * @param[in] i Param for the format. - */ -void del_and_dup(char** str, std::string const& format, int i) { - delete[] * str; - char name[32]; - ::snprintf(name, 31, format.c_str(), i); - name[31] = '\0'; - *str = ::strdup(name); -} - -/** - * Validate a date. - * - * @param[in] str The string to validate. - * - * @return True if valid. - */ -bool validate_date(std::string const& str) { - int month, day, year; - if (sscanf(str.c_str(), "%d-%d-%d", &month, &day, &year) != 3) - return (false); - - struct tm t; - time_t now_time = ::time(NULL); - ::localtime_r(&now_time, &t); - - if (month != t.tm_mon + 1 || day != t.tm_mday || year != t.tm_year + 1900) - return (false); - - return (true); -} - -/** - * Validate a time. - * - * @param[in] str The string to validate. - * - * @return True if valid. - */ -bool validate_time(std::string const& str) { - int hour, min, sec; - - if (sscanf(str.c_str(), "%d:%d:%d", &hour, &min, &sec) != 3) - return (false); - - struct tm t; - time_t now_time = ::time(NULL); - ::localtime_r(&now_time, &t); - t.tm_hour = hour; - t.tm_min = min; - t.tm_sec = sec; - time_t res = ::mktime(&t); - - if (res < start || res > now) - return (false); - - return (true); -} - -/** - * Validate a long date time. - * - * @param[in] str The string to validate. - * - * @return True if valid. - */ -bool validate_long_date_time(std::string const& str) { - (void)str; - - return (true); -} - -/** - * Validate a short date time. - * - * @param[in] str The string to validate. - * - * @return True if valid. - */ -bool validate_short_date_time(std::string const& str) { - size_t sub = str.find_first_of(' '); - if (sub == std::string::npos) - return (false); - - std::string date = str.substr(0, sub); - std::string time = str.substr(sub + 1); - - return (validate_date(date) && validate_time(time)); -} - -/** - * Validate a duration string (xd x'h x''m x'''s) - * - * @param[in] str The string. - * - * @return True if valid. - */ -bool validate_durations(std::string const& str) { - int day, hour, min, sec; - if (sscanf(str.c_str(), "%id %ih %im %is", &day, &hour, &min, &sec) != 4) - return (false); - - if (day != 0 || hour != 0 || min != 0 || sec <= 0) - return (false); - - return (true); -} - -/** - * @brief Validate the macros. - * - * Throw on error. - * - * @param[in] macros_string The string containing all the macros. - * @param[in] macros The model macros. - * @param[in] num_macros The number of macros expected. - */ -void validate_macros(std::string const& macros_string, - macros_struct* macros, - uint32_t num_macros) { - // Validate that all macros were correctly processed. - if (macros_string.find_first_of('$') != std::string::npos) - throw(exceptions::msg() << "a macro wasn't replaced"); - - // Validate each macro manually. - uint32_t index = 0; - uint32_t i = 0; - try { - for (; i < num_macros; ++i) { - size_t next = macros_string.find_first_of('\n', index); - if (next == std::string::npos) - throw(exceptions::msg() - << "not enough macro: expected " << num_macros << " macros."); - std::string substr = macros_string.substr(index, next - index); - - if (macros[i].type == macros_struct::null) - ; // pass - else if (macros[i].type == macros_struct::string) { - if (substr != macros[i].str) - throw(exceptions::msg() - << "invalid macro: expected '" << macros[i].str << "' got '" - << substr << "'"); - } else if (macros[i].type == macros_struct::integer) { - std::stringstream ss; - int num; - ss << substr; - ss >> num; - if (!ss.eof()) - throw(exceptions::msg() - << "couldn't parse '" << substr << "' into an int"); - if (num != macros[i].num) - throw(exceptions::msg() << "invalid macro: expected '" - << macros[i].num << "'' got '" << num << "'"); - } else if (macros[i].type == macros_struct::function) { - if (!macros[i].f(substr)) - throw(exceptions::msg() << "could not validate '" << substr << "'"); - } else if (macros[i].type == macros_struct::between) { - std::stringstream ss; - double value; - ss << substr; - ss >> value; - if (!ss.eof()) - throw(exceptions::msg() - << "couldn't parse '" << substr << "' into a double"); - if (value < macros[i].value1 - epsilon || - value > macros[i].value2 + epsilon) - throw(exceptions::msg() - << "value outside of bound " << macros[i].value1 << " and " - << macros[i].value2 << " in '" << substr << "'"); - } - index = next + 1; - } - } catch (std::exception const& e) { - throw(exceptions::msg() << "error while trying to validate macro " - << macros[i].macro_name << ": " << e.what()); - } -} - -/** - * Get a file. - * - * @param[in] filename The filename. - * @param[out] error Error flag. - * @param[out] ss The resulting string stream. - */ -void get_file(std::string const& filename, - bool& error, - std::ostringstream& ss) { - ss.str(""); - std::ifstream filestream(filename.c_str()); - - if ((error = !filestream.is_open())) - throw(exceptions::msg() << "flag file '" << filename << "' doesn't exist"); - - filestream.exceptions(std::ifstream::failbit | std::ifstream::badbit); - ss << filestream.rdbuf(); - - std::cout << "content of " << filename << ": " << ss.str(); -} - -/** - * Check that notification is properly enabled. - * - * @return EXIT_SUCCESS on success. - */ -int main() { - // Error flag. - bool error(true); - - // Variables that need cleaning. - std::list hosts; - std::list services; - std::list commands; - std::string engine_config_path(tmpnam(NULL)); - std::string flag_file(tmpnam(NULL)); - std::string flag_file2(tmpnam(NULL)); - std::string flag_file3(tmpnam(NULL)); - std::string flag_file4(tmpnam(NULL)); - std::string node_cache_file(tmpnam(NULL)); - engine_extcmd commander; - broker_extcmd broker_commander; - engine monitoring; - test_file broker_cfg; - test_db db; - - try { - // Log some info. - std::cout << "flag file 1 (normal notification): " << flag_file << "\n"; - std::cout << "flag file 2 (up notification): " << flag_file2 << "\n"; - std::cout << "flag file 3 (downtime notification): " << flag_file3 << "\n"; - std::cout << "flag file 4 (ack notification): " << flag_file4 << "\n"; - std::cout << "node cache: " << node_cache_file << "\n"; - - // Prepare database. - db.open(DB_NAME, NULL, true); - - // Prepare monitoring engine configuration parameters. - generate_commands(commands, 1); - del_and_dup(&commands.begin()->name, "service_command_%i", 1); - generate_hosts(hosts, 1); - del_and_dup(&hosts.begin()->name, "Host%i", 1); - // XXX del_and_dup(&hosts.begin()->display_name, "%i", 1); - del_and_dup(&hosts.begin()->alias, "HostAlias%i", 1); - hosts.begin()->checks_enabled = 0; - generate_services(services, hosts, 2); - int i(1); - for (std::list::iterator it(services.begin()), end(services.end()); - it != end; ++it, ++i) { - it->checks_enabled = 0; - it->max_attempts = 1; - del_and_dup(&it->description, "Service%i", i); - // XXX del_and_dup(&it->display_name, "%i", i); - del_and_dup(&it->service_check_command, "service_command_%i", 1); - del_and_dup(&it->host_name, "Host%i", 1); - } - set_custom_variable(services.back(), "FLAGFILE", flag_file.c_str()); - set_custom_variable(services.back(), "FLAGFILE2", flag_file2.c_str()); - set_custom_variable(services.back(), "FLAGFILE3", flag_file3.c_str()); - set_custom_variable(services.back(), "FLAGFILE4", flag_file4.c_str()); - - // Populate database. - db.centreon_run( - "INSERT INTO cfg_organizations (organization_id, name, shortname)" - " VALUES (1, '42', '42')", - "could not create organization"); - - db.centreon_run( - "INSERT INTO cfg_hosts (host_id, host_name, host_alias, " - "organization_id)" - " VALUES (1, 'Host1', 'HostAlias1', 1)", - "could not create host"); - db.centreon_run( - "INSERT INTO cfg_services (service_id," - " service_description, organization_id)" - " VALUES (1, 'Service1', 1), (2, 'Service2', 1)", - "could not create services"); - db.centreon_run( - "INSERT INTO cfg_hosts_services_relations (host_host_id," - " service_service_id)" - " VALUES (1, 1), (1, 2)", - "could not link host and services"); - - // Create contact in DB. - db.centreon_run( - "INSERT INTO cfg_contacts (contact_id, description)" - " VALUES (1, 'Contact1')", - "could not create contact"); - db.centreon_run( - "INSERT INTO cfg_contacts_infos (contact_id, info_key, info_value)" - " VALUES (1, 'email', 'ContactEmail1'), (1, 'pager', 'ContactPager1')," - " (1, 'address1', 'ContactAddress1'), (1, 'address2', " - "'ContactAddress2')," - " (1, 'address3', 'ContactAddress3'), (1, 'address4', " - "'ContactAddress4')," - " (1, 'address5', 'ContactAddress5'), (1, 'address6', " - "'ContactAddress6')", - "could not create contact infos"); - - // Create notification command in DB. - db.centreon_run( - "INSERT INTO cfg_commands (command_id, command_name," - " command_line, organization_id)" - " VALUES (1, 'NotificationCommand1', '" UTIL_FILE_WRITER " " MACRO_LIST - " $_SERVICEFLAGFILE$', 1)," - " (2, 'NotificationCommand2', '" UTIL_FILE_WRITER - " " RECOVERY_FILE_CONTENT - " $_SERVICEFLAGFILE2$', 1)," - " (3, 'NotificationCommand3', '" UTIL_FILE_WRITER - " " DOWNTIME_FILE_CONTENT - " $_SERVICEFLAGFILE3$', 1)," - " (4, 'NotificationCommand4', '" UTIL_FILE_WRITER - " " ACK_FILE_CONTENT " $_SERVICEFLAGFILE4$', 1)", - "could not create notification command"); - - // Create notification rules in DB. - db.centreon_run( - "INSERT INTO cfg_notification_methods (method_id," - " name, command_id, `interval`, types, status)" - " VALUES (1, 'NotificationMethod', 1, 300, 'n', 'w,c,u')," - " (2, 'NotificationMethod2', 2, 300, 'r', 'o')," - " (3, 'NotificationMethod3', 3, 300, 'd', 'o')," - " (4, 'NotificationMethod4', 4, 300, 'a', 'o')", - "could not create notification method"); - db.centreon_run( - "INSERT INTO cfg_notification_rules (rule_id, method_id, " - " timeperiod_id, owner_id, contact_id, host_id," - " service_id, enabled)" - " VALUES (1, 1, NULL, 1, 1, 1, 2, 1)," - " (2, 2, NULL, 1, 1, 1, 2, 1)," - " (3, 3, NULL, 1, 1, 1, 2, 1)," - " (4, 4, NULL, 1, 1, 1, 2, 1)", - "could not create notification rule (cfg)"); - db.centreon_run( - "INSERT INTO rt_notification_rules (rule_id, method_id," - " timeperiod_id, contact_id, host_id," - " service_id)" - " VALUES (1, 1, NULL, 1, 1, 2)," - " (2, 2, NULL, 1, 1, 2)," - " (3, 3, NULL, 1, 1, 2)," - " (4, 4, NULL, 1, 1, 2)", - "could not create notification rule (rt)"); - - // Generate configuration. - broker_cfg.set_template(PROJECT_SOURCE_DIR "/test/cfg/notification.xml.in"); - broker_cfg.set("NODE_CACHE_FILE", node_cache_file); - commander.set_file(tmpnam(NULL)); - broker_commander.set_file(tmpnam(NULL)); - broker_cfg.set("BROKER_COMMAND_FILE", broker_commander.get_file()); - std::string additional_config; - { - std::ostringstream oss; - oss << commander.get_engine_config() << "broker_module=" << CBMOD_PATH - << " " << broker_cfg.generate() << "\n"; - additional_config = oss.str(); - } - config_write(engine_config_path.c_str(), additional_config.c_str(), &hosts, - &services, &commands); - - // Start monitoring. - start = ::time(NULL); - std::string engine_config_file(engine_config_path); - engine_config_file.append("/nagios.cfg"); - monitoring.set_config_file(engine_config_file); - monitoring.start(); - sleep_for(3); - commander.execute("PROCESS_HOST_CHECK_RESULT;Host1;0;Host Check Ok"); - commander.execute( - "PROCESS_SERVICE_CHECK_RESULT;Host1;Service1;0;Submitted by unit test"); - commander.execute( - "PROCESS_SERVICE_CHECK_RESULT;Host1;Service2;0;Submitted by unit test"); - sleep_for(5); - - // Make service 2 CRITICAL. - commander.execute( - "PROCESS_SERVICE_CHECK_RESULT;Host1;Service2;2;Critical submitted by " - "unit test"); - commander.execute("PROCESS_HOST_CHECK_RESULT;Host1;0;Host Check Ok"); - sleep_for(7); - - // Check file creation. - std::ostringstream ss; - get_file(flag_file, error, ss); - - now = ::time(NULL); - { - macros_struct macros[] = { - {macros_struct::function, NULL, 0, validate_long_date_time, 0, 0, - "LONGDATETIME"}, - {macros_struct::function, NULL, 0, validate_short_date_time, 0, 0, - "SHORTDATETIME"}, - {macros_struct::function, NULL, 0, validate_date, 0, 0, "DATE"}, - {macros_struct::function, NULL, 0, validate_time, 0, 0, "TIME"}, - {macros_struct::between, NULL, 0, NULL, start, now, "TIMET"}, - {macros_struct::string, "Host1", 0, NULL, 0, 0, "HOSTNAME"}, - {macros_struct::string, "HostAlias1", 0, NULL, 0, 0, "HOSTALIAS"}, - {macros_struct::string, "localhost", 0, NULL, 0, 0, "HOSTADDRESS"}, - {macros_struct::string, "UP", 0, NULL, 0, 0, "HOSTSTATE"}, - {macros_struct::integer, NULL, 0, NULL, 0, 0, "HOSTSTATEID"}, - {macros_struct::string, "HARD", 0, NULL, 0, 0, "HOSTSTATETYPE"}, - {macros_struct::integer, NULL, 1, NULL, 0, 0, "HOSTATTEMPT"}, - {macros_struct::integer, NULL, 3, NULL, 0, 0, "MAXHOSTATTEMPS"}, - {macros_struct::between, NULL, 0, NULL, 0.0000005, 1.20, - "HOSTLATENCY"}, - {macros_struct::between, NULL, 0, NULL, 0, 0, "HOSTEXECUTIONTIME"}, - {macros_struct::function, NULL, 0, validate_durations, 0, 0, - "HOSTDURATION"}, - {macros_struct::between, NULL, 0, NULL, 1, ::difftime(now, start), - "HOSTDURATIONSEC"}, - {macros_struct::integer, NULL, 0, NULL, 0, 0, "HOSTDOWNTIME"}, - {macros_struct::between, NULL, 0, NULL, 0, 0, "HOSTPERCENTCHANGE"}, - {macros_struct::string, "", 0, NULL, 0, 0, "HOSTGROUPNAME"}, - {macros_struct::string, "", 0, NULL, 0, 0, "HOSTGROUPNAMES"}, - {macros_struct::between, NULL, 0, NULL, start, now, "LASTHOSTCHECK"}, - {macros_struct::between, NULL, 0, NULL, start, now, - "LASTHOSTSTATECHANGE"}, - {macros_struct::between, NULL, 0, NULL, start, now, "LASTHOSTUP"}, - {macros_struct::integer, NULL, 0, NULL, 0, 0, "LASTHOSTDOWN"}, - {macros_struct::integer, NULL, 0, NULL, 0, 0, "LASTHOSTUNREACHABLE"}, - {macros_struct::string, "Host Check Ok", 0, NULL, 0, 0, "HOSTOUTPUT"}, - {macros_struct::string, "", 0, NULL, 0, 0, "LONGHOSTOUTPUT"}, - {macros_struct::string, "", 0, NULL, 0, 0, "HOSTPERFDATA"}, - {macros_struct::string, "default_command", 0, NULL, 0, 0, - "HOSTCHECKCOMMAND"}, - {macros_struct::integer, NULL, 2, NULL, 0, 0, "TOTALHOSTSERVICES"}, - {macros_struct::integer, NULL, 1, NULL, 0, 0, "TOTALHOSTSERVICESOK"}, - {macros_struct::integer, NULL, 0, NULL, 0, 0, - "TOTALHOSTSERVICESWARNING"}, - {macros_struct::integer, NULL, 0, NULL, 0, 0, - "TOTALHOSTSERVICESUNKNOWN"}, - {macros_struct::integer, NULL, 1, NULL, 0, 0, - "TOTALHOSTSERVICESCRITICAL"}, - {macros_struct::string, "Service2", 0, NULL, 0, 0, "SERVICEDESC"}, - {macros_struct::string, "CRITICAL", 0, NULL, 0, 0, "SERVICESTATE"}, - {macros_struct::integer, NULL, 2, NULL, 0, 0, "SERVICESTATEID"}, - {macros_struct::string, "OK", 0, NULL, 0, 0, "LASTSERVICESTATE"}, - {macros_struct::integer, NULL, 0, NULL, 0, 0, "LASTSERVICESTATEID"}, - {macros_struct::string, "HARD", 0, NULL, 0, 0, "SERVICESTATETYPE"}, - {macros_struct::integer, NULL, 1, NULL, 0, 0, "SERVICEATTEMPT"}, - {macros_struct::integer, NULL, 1, NULL, 0, 0, "MAXSERVICEATTEMPTS"}, - {macros_struct::integer, NULL, 0, NULL, 0, 0, "SERVICEISVOLATILE"}, - {macros_struct::between, NULL, 0, NULL, 0.0000005, 1.20, - "SERVICELATENCY"}, - {macros_struct::between, NULL, 0, NULL, 0, 0, "SERVICEEXECUTIONTIME"}, - {macros_struct::function, NULL, 0, validate_durations, 0, 0, - "SERVICEDURATION"}, - {macros_struct::between, NULL, 0, NULL, 1, ::difftime(now, start), - "SERVICEDURATIONSEC"}, - {macros_struct::integer, NULL, 0, NULL, 0, 0, "SERVICEDOWNTIME"}, - {macros_struct::between, NULL, 0, NULL, 6.25, 6.25, - "SERVICEPERCENTCHANGE"}, - {macros_struct::string, "", 0, NULL, 0, 0, "SERVICEGROUPNAME"}, - {macros_struct::string, "", 0, NULL, 0, 0, "SERVICEGROUPNAMES"}, - {macros_struct::between, NULL, 0, NULL, start, now, - "LASTSERVICECHECK"}, - {macros_struct::between, NULL, 0, NULL, start, now, - "LASTSERVICESTATECHANGE"}, - {macros_struct::between, NULL, 0, NULL, start, now, "LASTSERVICEOK"}, - {macros_struct::integer, NULL, 0, NULL, 0, 0, "LASTSERVICEWARNING"}, - {macros_struct::integer, NULL, 0, NULL, 0, 0, "LASTSERVICEUNKNOWN"}, - {macros_struct::between, NULL, 0, NULL, start, now, - "LASTSERVICECRITICAL"}, - {macros_struct::string, "Critical submitted by unit test", 0, NULL, 0, - 0, "SERVICEOUTPUT"}, - {macros_struct::string, "", 0, NULL, 0, 0, "LONGSERVICEOUTPUT"}, - {macros_struct::string, "", 0, NULL, 0, 0, "SERVICEPERFDATA"}, - {macros_struct::string, "service_command_1", 0, NULL, 0, 0, - "SERVICECHECKCOMMAND"}, - {macros_struct::integer, NULL, 1, NULL, 0, 0, "TOTALHOSTSUP"}, - {macros_struct::integer, NULL, 0, NULL, 0, 0, "TOTALHOSTSDOWN"}, - {macros_struct::integer, NULL, 0, NULL, 0, 0, - "TOTALHOSTSUNREACHABLE"}, - {macros_struct::integer, NULL, 0, NULL, 0, 0, - "TOTALHOSTSDOWNUNHANDLED"}, - {macros_struct::integer, NULL, 0, NULL, 0, 0, - "TOTALHOSTSUNREACHABLEUNHANDLED"}, - {macros_struct::integer, NULL, 0, NULL, 0, 0, "TOTALHOSTPROBLEMS"}, - {macros_struct::integer, NULL, 0, NULL, 0, 0, - "TOTALHOSTPROBLEMSUNHANDLED"}, - {macros_struct::integer, NULL, 1, NULL, 0, 0, "TOTALSERVICESOK"}, - {macros_struct::integer, NULL, 0, NULL, 0, 0, "TOTALSERVICESWARNING"}, - {macros_struct::integer, NULL, 1, NULL, 0, 0, - "TOTALSERVICESCRITICAL"}, - {macros_struct::integer, NULL, 0, NULL, 0, 0, "TOTALSERVICESUNKNOWN"}, - {macros_struct::integer, NULL, 0, NULL, 0, 0, - "TOTALSERVICESWARNINGUNHANDLED"}, - {macros_struct::integer, NULL, 1, NULL, 0, 0, - "TOTALSERVICESCRITICALUNHANDLED"}, - {macros_struct::integer, NULL, 0, NULL, 0, 0, - "TOTALSERVICESUNKNOWNUNHANDLED"}, - {macros_struct::integer, NULL, 1, NULL, 0, 0, "TOTALSERVICEPROBLEMS"}, - {macros_struct::integer, NULL, 1, NULL, 0, 0, - "TOTALSERVICEPROBLEMSUNHANDLED"}, - {macros_struct::string, "PROBLEM", 0, NULL, 0, 0, "NOTIFICATIONTYPE"}, - {macros_struct::string, "Contact1", 0, NULL, 0, 0, - "NOTIFICATIONRECIPIENT"}, - {macros_struct::integer, NULL, 1, NULL, 0, 0, - "HOSTNOTIFICATIONNUMBER"}, - {macros_struct::integer, NULL, 1, NULL, 0, 0, - "SERVICENOTIFICATIONNUMBER"}, - {macros_struct::string, "", 0, NULL, 0, 0, "HOSTGROUPALIAS"}, - {macros_struct::string, "", 0, NULL, 0, 0, "HOSTGROUPMEMBERS"}, - {macros_struct::string, "", 0, NULL, 0, 0, "SERVICEGROUPALIAS"}, - {macros_struct::string, "", 0, NULL, 0, 0, "SERVICEGROUPMEMBERS"}, - {macros_struct::string, "Contact1", 0, NULL, 0, 0, "CONTACTNAME"}, - {macros_struct::string, "Contact1", 0, NULL, 0, 0, "CONTACTALIAS"}, - {macros_struct::string, "ContactEmail1", 0, NULL, 0, 0, - "CONTACTEMAIL"}, - {macros_struct::string, "ContactPager1", 0, NULL, 0, 0, - "CONTACTPAGER"}, - {macros_struct::string, "ContactAddress1", 0, NULL, 0, 0, - "CONTACTADDRESS1"}, - {macros_struct::string, "ContactAddress2", 0, NULL, 0, 0, - "CONTACTADDRESS2"}, - {macros_struct::string, "ContactAddress3", 0, NULL, 0, 0, - "CONTACTADDRESS3"}, - {macros_struct::string, "ContactAddress4", 0, NULL, 0, 0, - "CONTACTADDRESS4"}, - {macros_struct::string, "ContactAddress5", 0, NULL, 0, 0, - "CONTACTADDRESS5"}, - {macros_struct::string, "ContactAddress6", 0, NULL, 0, 0, - "CONTACTADDRESS6"}, - {macros_struct::string, "", 0, NULL, 0, 0, "CONTACTGROUPALIAS"}, - {macros_struct::string, "", 0, NULL, 0, 0, "CONTACTGROUPMEMBERS"}}; - - validate_macros(ss.str(), macros, sizeof(macros) / sizeof(*macros)); - } - - // Make service 2 OK. - start = ::time(NULL); - commander.execute( - "PROCESS_SERVICE_CHECK_RESULT;Host1;Service2;0;Critical submitted by " - "unit test"); - sleep_for(10); - - // Check file creation. - get_file(flag_file2, error, ss); - { - macros_struct macros[] = {{macros_struct::string, "RECOVERY", 0, NULL, 0, - 0, "NOTIFICATIONTYPE"}}; - - validate_macros(ss.str(), macros, sizeof(macros) / sizeof(*macros)); - } - - // Check downtimes - time_t start = ::time(NULL); - time_t end = start + 5; - ss.str(""); - ss << "EXECUTE;84;notification-nodeevents;SCHEDULE_SVC_DOWNTIME;Host1;" - "Service2;" - << start << ";" << end << ";1;0;5;test author;some comments;test;0"; - broker_commander.execute(ss.str()); - - sleep_for(10); - - get_file(flag_file3, error, ss); - { - macros_struct macros[] = {{macros_struct::string, "DOWNTIME", 0, NULL, 0, - 0, "NOTIFICATIONTYPE"}}; - - validate_macros(ss.str(), macros, sizeof(macros) / sizeof(*macros)); - } - - // Check acks - broker_commander.execute( - "EXECUTE;84;notification-nodeevents;ACKNOWLEDGE_SVC_PROBLEM;Host1;" - "Service2;2;1;1;test author;some comments"); - - sleep_for(3); - get_file(flag_file4, error, ss); - { - macros_struct macros[] = {{macros_struct::string, "ACKNOWLEDGEMENT", 0, - NULL, 0, 0, "NOTIFICATIONTYPE"}}; - - validate_macros(ss.str(), macros, sizeof(macros) / sizeof(*macros)); - } - - } catch (std::exception const& e) { - std::cerr << e.what() << std::endl; - error = true; - } catch (...) { - std::cerr << "unknown exception" << std::endl; - error = true; - } - - // Cleanup. - monitoring.stop(); - sleep_for(3); - ::remove(flag_file.c_str()); - ::remove(flag_file2.c_str()); - ::remove(flag_file3.c_str()); - ::remove(flag_file4.c_str()); - ::remove(node_cache_file.c_str()); - config_remove(engine_config_path.c_str()); - free_hosts(hosts); - free_services(services); - free_commands(commands); - - return (error ? EXIT_FAILURE : EXIT_SUCCESS); -} diff --git a/broker/test/notification_correlated.cc b/broker/test/notification_correlated.cc deleted file mode 100644 index 6c0a19c4f9d..00000000000 --- a/broker/test/notification_correlated.cc +++ /dev/null @@ -1,182 +0,0 @@ -/* -** Copyright 2014-2015 Centreon -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -** -** For more information : contact@centreon.com -*/ - -#include -#include -#include -#include -#include -#include "com/centreon/broker/exceptions/msg.hh" -#include "test/config.hh" -#include "test/engine.hh" -#include "test/engine_extcmd.hh" -#include "test/generate.hh" -#include "test/misc.hh" -#include "test/vars.hh" - -using namespace com::centreon::broker; - -#define DB_NAME "broker_notification_correlated" - -/** - * Check that notification is properly enabled when non-correlation - * option is set on services. - * - * @return EXIT_SUCCESS on success. - */ -int main() { - // Error flag. - bool error(true); - - // Variables that need cleaning. - std::list hosts; - std::list services; - std::string engine_config_path(tmpnam(NULL)); - std::string flag_file(tmpnam(NULL)); - std::string node_cache_file(tmpnam(NULL)); - engine_extcmd commander; - engine monitoring; - test_file broker_cfg; - test_db db; - - try { - // Log some info. - std::cout << "flag file: " << flag_file << "\n"; - std::cout << "node cache: " << node_cache_file << "\n"; - - // Prepare database. - db.open(DB_NAME, NULL, true); - - // Prepare monitoring engine configuration parameters. - generate_hosts(hosts, 1); - hosts.begin()->checks_enabled = 0; - generate_services(services, hosts, 2); - for (std::list::iterator it(services.begin()), end(services.end()); - it != end; ++it) { - it->checks_enabled = 0; - it->max_attempts = 1; - } - set_custom_variable(services.back(), "FLAGFILE", flag_file.c_str()); - - // Populate database. - db.centreon_run( - "INSERT INTO cfg_organizations (organization_id, name, shortname)" - " VALUES (1, '42', '42')", - "could not create organization"); - - db.centreon_run( - "INSERT INTO cfg_hosts (host_id, host_name, organization_id)" - " VALUES (1, 'Host1', 1)", - "could not create host"); - db.centreon_run( - "INSERT INTO cfg_services (service_id," - " service_description," - " service_notification_options, organization_id)" - " VALUES (1, 'Service1', 'ywcu', 1), (2, 'Service2', 'ywcu', 1)", - "could not create services"); - db.centreon_run( - "INSERT INTO cfg_hosts_services_relations (host_host_id," - " service_service_id)" - " VALUES (1, 1), (1, 2)", - "could not link host and services"); - - // Create contact in DB. - db.centreon_run( - "INSERT INTO cfg_contacts (contact_id, description)" - " VALUES (1, 'Contact1')", - "could not create contact"); - - // Create notification command in DB. - db.centreon_run( - "INSERT INTO cfg_commands (command_id, command_name," - " command_line, organization_id)" - " VALUES (1, 'NotificationCommand1', 'cmake -E touch " - "$_SERVICEFLAGFILE$', 1)", - "could not create notification command"); - - // Create notification rules in DB. - db.centreon_run( - "INSERT INTO cfg_notification_methods (method_id," - " name, command_id, `interval`, status, types)" - " VALUES (1, 'NotificationMethod', 1, 300, 'w,c,u', 'n')", - "could not create notification method"); - db.centreon_run( - "INSERT INTO cfg_notification_rules (rule_id, method_id, " - " timeperiod_id, owner_id, contact_id, host_id," - " service_id, enabled)" - " VALUES (1, 1, NULL, 1, 1, 1, 2, 1)", - "could not create notification rule (cfg)"); - - // Generate configuration. - broker_cfg.set_template(PROJECT_SOURCE_DIR - "/test/cfg/notification_correlated.xml.in"); - broker_cfg.set("NODE_CACHE_FILE", node_cache_file); - commander.set_file(tmpnam(NULL)); - std::string additional_config; - { - std::ostringstream oss; - oss << commander.get_engine_config() << "broker_module=" << CBMOD_PATH - << " " << broker_cfg.generate() << "\n"; - additional_config = oss.str(); - } - config_write(engine_config_path.c_str(), additional_config.c_str(), &hosts, - &services); - - // Start monitoring. - std::string engine_config_file(engine_config_path); - engine_config_file.append("/nagios.cfg"); - monitoring.set_config_file(engine_config_file); - monitoring.start(); - sleep_for(3); - commander.execute("PROCESS_HOST_CHECK_RESULT;1;0;Host Check Ok"); - commander.execute( - "PROCESS_SERVICE_CHECK_RESULT;1;1;0;Submitted by unit test"); - commander.execute( - "PROCESS_SERVICE_CHECK_RESULT;1;2;0;Submitted by unit test"); - sleep_for(5); - - // Make services CRITICAL. - commander.execute( - "PROCESS_SERVICE_CHECK_RESULT;1;1;2;Submitted by unit test"); - commander.execute( - "PROCESS_SERVICE_CHECK_RESULT;1;2;2;Submitted by unit test"); - sleep_for(7); - - // Check file creation. No file should be created. - error = QFile::exists(flag_file.c_str()); - - if (error) - std::cout << "error: file " << flag_file << " has been created" - << std::endl; - } catch (std::exception const& e) { - std::cerr << e.what() << std::endl; - } catch (...) { - std::cerr << "unknown exception" << std::endl; - } - - // Cleanup. - monitoring.stop(); - sleep_for(3); - ::remove(flag_file.c_str()); - ::remove(node_cache_file.c_str()); - config_remove(engine_config_path.c_str()); - free_hosts(hosts); - free_services(services); - - return (error ? EXIT_FAILURE : EXIT_SUCCESS); -} diff --git a/broker/test/notification_non_correlated.cc b/broker/test/notification_non_correlated.cc deleted file mode 100644 index fce0754ba62..00000000000 --- a/broker/test/notification_non_correlated.cc +++ /dev/null @@ -1,182 +0,0 @@ -/* -** Copyright 2014-2015 Centreon -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -** -** For more information : contact@centreon.com -*/ - -#include -#include -#include -#include -#include -#include "com/centreon/broker/exceptions/msg.hh" -#include "test/config.hh" -#include "test/engine.hh" -#include "test/engine_extcmd.hh" -#include "test/generate.hh" -#include "test/misc.hh" -#include "test/vars.hh" - -using namespace com::centreon::broker; - -#define DB_NAME "broker_notification_non_correlated" - -/** - * Check that notification is properly enabled when non-correlation - * option is set on services. - * - * @return EXIT_SUCCESS on success. - */ -int main() { - // Error flag. - bool error(true); - - // Variables that need cleaning. - std::list hosts; - std::list services; - std::string engine_config_path(tmpnam(NULL)); - std::string flag_file(tmpnam(NULL)); - std::string node_cache_file(tmpnam(NULL)); - engine_extcmd commander; - engine monitoring; - test_file broker_cfg; - test_db db; - - try { - // Log some info. - std::cout << "flag file: " << flag_file << "\n"; - std::cout << "node cache: " << node_cache_file << "\n"; - - // Prepare database. - db.open(DB_NAME, NULL, true); - - // Prepare monitoring engine configuration parameters. - generate_hosts(hosts, 1); - generate_services(services, hosts, 2); - for (std::list::iterator it(services.begin()), end(services.end()); - it != end; ++it) { - it->checks_enabled = 0; - it->max_attempts = 1; - } - set_custom_variable(services.back(), "FLAGFILE", flag_file.c_str()); - - // Populate database. - db.centreon_run( - "INSERT INTO cfg_organizations (organization_id, name, shortname)" - " VALUES (1, '42', '42')", - "could not create organization"); - - db.centreon_run( - "INSERT INTO cfg_hosts (host_id, host_name, organization_id)" - " VALUES (1, 'Host1', 1)", - "could not create host"); - db.centreon_run( - "INSERT INTO cfg_services (service_id," - " service_description," - " service_notification_options, organization_id)" - " VALUES (1, 'Service1', 'ywcu', 1), (2, 'Service2', 'ywcu', 1)", - "could not create services"); - db.centreon_run( - "INSERT INTO cfg_hosts_services_relations (host_host_id," - " service_service_id)" - " VALUES (1, 1), (1, 2)", - "could not link host and services"); - - // Create contact in DB. - db.centreon_run( - "INSERT INTO cfg_contacts (contact_id, description)" - " VALUES (1, 'Contact1')", - "could not create contact"); - - // Create notification command in DB. - db.centreon_run( - "INSERT INTO cfg_commands (command_id, command_name," - " command_line, organization_id)" - " VALUES (1, 'NotificationCommand1', 'cmake -E touch " - "$_SERVICEFLAGFILE$', 1)", - "could not create notification command"); - - // Create notification rules in DB. - db.centreon_run( - "INSERT INTO cfg_notification_methods (method_id," - " name, command_id, `interval`, status, types)" - " VALUES (1, 'NotificationMethod', 1, 300, 'w,c,u', 'n')", - "could not create notification method"); - db.centreon_run( - "INSERT INTO cfg_notification_rules (rule_id, method_id, " - " timeperiod_id, owner_id, contact_id, host_id," - " service_id, enabled)" - " VALUES (1, 1, NULL, 1, 1, 1, 2, 1)", - "could not create notification rule (cfg)"); - db.centreon_run( - "INSERT INTO rt_notification_rules (rule_id, method_id," - " timeperiod_id, contact_id, host_id," - " service_id)" - " VALUES (1, 1, NULL, 1, 1, 2)", - "could not create notification rule (rt)"); - - // Generate configuration. - broker_cfg.set_template(PROJECT_SOURCE_DIR - "/test/cfg/notification_non_correlated.xml.in"); - broker_cfg.set("NODE_CACHE_FILE", node_cache_file); - commander.set_file(tmpnam(NULL)); - std::string additional_config; - { - std::ostringstream oss; - oss << commander.get_engine_config() << "broker_module=" << CBMOD_PATH - << " " << broker_cfg.generate() << "\n"; - additional_config = oss.str(); - } - config_write(engine_config_path.c_str(), additional_config.c_str(), &hosts, - &services); - - // Start monitoring. - std::string engine_config_file(engine_config_path); - engine_config_file.append("/nagios.cfg"); - monitoring.set_config_file(engine_config_file); - monitoring.start(); - sleep_for(3); - commander.execute( - "PROCESS_SERVICE_CHECK_RESULT;1;1;0;Submitted by unit test"); - commander.execute( - "PROCESS_SERVICE_CHECK_RESULT;1;2;0;Submitted by unit test"); - sleep_for(5); - - // Make services CRITICAL. - commander.execute( - "PROCESS_SERVICE_CHECK_RESULT;1;1;2;Submitted by unit test"); - commander.execute( - "PROCESS_SERVICE_CHECK_RESULT;1;2;2;Submitted by unit test"); - sleep_for(15); - - // Check file creation. - error = !QFile::exists(flag_file.c_str()); - } catch (std::exception const& e) { - std::cerr << e.what() << std::endl; - } catch (...) { - std::cerr << "unknown exception" << std::endl; - } - - // Cleanup. - monitoring.stop(); - sleep_for(3); - ::remove(flag_file.c_str()); - ::remove(node_cache_file.c_str()); - config_remove(engine_config_path.c_str()); - free_hosts(hosts); - free_services(services); - - return (error ? EXIT_FAILURE : EXIT_SUCCESS); -} diff --git a/broker/unified_sql/inc/com/centreon/broker/unified_sql/stream.hh b/broker/unified_sql/inc/com/centreon/broker/unified_sql/stream.hh index 2f4d7eccdfe..b21b1657c64 100644 --- a/broker/unified_sql/inc/com/centreon/broker/unified_sql/stream.hh +++ b/broker/unified_sql/inc/com/centreon/broker/unified_sql/stream.hh @@ -326,6 +326,7 @@ class stream : public io::stream { void _process_pb_custom_variable(const std::shared_ptr& d); void _process_pb_custom_variable_status(const std::shared_ptr& d); void _process_downtime(const std::shared_ptr& d); + void _process_pb_downtime(const std::shared_ptr& d); void _process_event_handler(const std::shared_ptr& d); void _process_flapping_status(const std::shared_ptr& d); void _process_host_check(const std::shared_ptr& d); diff --git a/broker/unified_sql/src/stream.cc b/broker/unified_sql/src/stream.cc index 0c746b751ef..48d93232993 100644 --- a/broker/unified_sql/src/stream.cc +++ b/broker/unified_sql/src/stream.cc @@ -85,7 +85,7 @@ void (stream::*const stream::_neb_processing_table[])( &stream::_process_severity, &stream::_process_tag, &stream::_process_pb_comment, - nullptr, + &stream::_process_pb_downtime, &stream::_process_pb_custom_variable, &stream::_process_pb_custom_variable_status, diff --git a/broker/unified_sql/src/stream_sql.cc b/broker/unified_sql/src/stream_sql.cc index 1feb41dc726..9c435a90de1 100644 --- a/broker/unified_sql/src/stream_sql.cc +++ b/broker/unified_sql/src/stream_sql.cc @@ -36,6 +36,10 @@ static inline bool is_not_zero(const int64_t& value) { return value != 0; } +static bool time_is_undefined(uint64_t t) { + return t == 0 || t == static_cast(-1); +} + /** * @brief Clean tables with data associated to the instance. * @@ -713,7 +717,7 @@ void stream::_process_pb_custom_variable_status( */ void stream::_process_downtime(const std::shared_ptr& d) { // Cast object. - neb::downtime const& dd = *static_cast(d.get()); + const neb::downtime& dd = *static_cast(d.get()); // Log message. SPDLOG_LOGGER_INFO(log_v2::sql(), @@ -753,6 +757,68 @@ void stream::_process_downtime(const std::shared_ptr& d) { } } +/** + * Process a downtime (protobuf) event. + * + * @param[in] e Uncasted downtime. + * + * @return The number of events that can be acknowledged. + */ +void stream::_process_pb_downtime(const std::shared_ptr& d) { + // Cast object. + const neb::pb_downtime& dd = *static_cast(d.get()); + auto& dt_obj = dd.obj(); + + // Log message. + log_v2::sql()->info( + "SQL: processing pb downtime event (poller: {}" + ", host: {}, service: {}, start time: {}, end_time: {}" + ", actual start time: {}" + ", actual end time: {}" + ", duration: {}, entry time: {}" + ", deletion time: {})", + dt_obj.instance_id(), dt_obj.host_id(), dt_obj.service_id(), + dt_obj.start_time(), dt_obj.end_time(), dt_obj.actual_start_time(), + dt_obj.actual_end_time(), dt_obj.duration(), dt_obj.entry_time(), + dt_obj.deletion_time()); + + // Check if poller is valid. + if (_is_valid_poller(dt_obj.instance_id())) { + _downtimes_queue.emplace_back(fmt::format( + "({},{},'{}',{},{},{},{},{},{},{},{},{},{},{},{},{},{},'{}')", + time_is_undefined(dt_obj.actual_end_time()) + ? "NULL" + : fmt::format("{}", dt_obj.actual_end_time()), + time_is_undefined(dt_obj.actual_start_time()) + ? "NULL" + : fmt::format("{}", dt_obj.actual_start_time()), + misc::string::escape(dt_obj.author(), + get_downtimes_col_size(downtimes_author)), + dt_obj.type(), + time_is_undefined(dt_obj.deletion_time()) + ? "NULL" + : fmt::format("{}", dt_obj.deletion_time()), + dt_obj.duration(), + time_is_undefined(dt_obj.end_time()) + ? "NULL" + : fmt::format("{}", dt_obj.end_time()), + time_is_undefined(dt_obj.entry_time()) + ? "NULL" + : fmt::format("{}", dt_obj.entry_time()), + dt_obj.fixed(), dt_obj.host_id(), dt_obj.instance_id(), dt_obj.id(), + dt_obj.service_id(), + time_is_undefined(dt_obj.start_time()) + ? "NULL" + : fmt::format("{}", dt_obj.start_time()), + time_is_undefined(dt_obj.triggered_by()) + ? "NULL" + : fmt::format("{}", dt_obj.triggered_by()), + dt_obj.cancelled(), dt_obj.started(), + misc::string::escape(dt_obj.comment_data(), + get_downtimes_col_size(downtimes_comment_data)))); + } +} + bool stream::_host_instance_known(uint64_t host_id) const { bool retval = _cache_host_instance.find(static_cast(host_id)) != _cache_host_instance.end(); diff --git a/cmake.sh b/cmake.sh index 4f16c740f7e..d318889532c 100755 --- a/cmake.sh +++ b/cmake.sh @@ -63,8 +63,12 @@ done # Am I root? my_id=$(id -u) -if [ -r /etc/centos-release ] ; then - maj="centos$(cat /etc/centos-release | awk '{print $4}' | cut -f1 -d'.')" +if [ -r /etc/centos-release -o -r /etc/almalinux-release ] ; then + if [ -r /etc/centos-release ] ; then + maj="centos$(cat /etc/centos-release | awk '{print $4}' | cut -f1 -d'.')" + else + maj="centos$(cat /etc/almalinux-release | awk '{print $3}' | cut -f1 -d'.')" + fi v=$(cmake --version) if [[ "$v" =~ "version 3" ]] ; then cmake='cmake' @@ -88,6 +92,7 @@ if [ -r /etc/centos-release ] ; then echo "python38 already installed" fi else + yum -y install gcc-c++ if [[ ! -x /usr/bin/python3 ]] ; then yum -y install python3 else @@ -126,8 +131,10 @@ if [ -r /etc/centos-release ] ; then if ! rpm -q $i ; then if [[ "$maj" == 'centos7' ]] ; then yum install -y $i - else + elif [[ "$maj" == 'centos8' ]] ; then dnf -y --enablerepo=PowerTools install $i + else + dnf -y install $i fi fi done diff --git a/conanfile.txt b/conanfile.txt index 5c4dcc9ae91..f063e542bc8 100755 --- a/conanfile.txt +++ b/conanfile.txt @@ -4,7 +4,7 @@ asio/1.24.0 fmt/8.1.1 spdlog/1.10.0 nlohmann_json/3.10.5 -openssl/1.1.1o +openssl/1.1.1q grpc/1.46.3 mariadb-connector-c/3.1.12 zlib/1.2.12 diff --git a/tests/README.md b/tests/README.md index 9b81dee4157..d4a8db08da0 100644 --- a/tests/README.md +++ b/tests/README.md @@ -329,9 +329,9 @@ Here is the list of the currently implemented tests: - [x] **EBNSGU1**: New service group with several pollers and connections to DB with broker configured with unified_sql - [x] **EBNSGU2**: New service group with several pollers and connections to DB with broker configured with unified_sql - [x] **EBNSVC1**: New services with several pollers -- [x] **EBSAU2**: New hosts with action_url with more than 2000 characters -- [x] **EBSN3**: New hosts with notes with more than 500 characters -- [x] **EBSNU1**: New hosts with notes_url with more than 2000 characters +- [x] **EBSAU2**: New services with action_url with more than 2000 characters +- [x] **EBSN3**: New services with notes with more than 500 characters +- [x] **EBSNU1**: New services with notes_url with more than 2000 characters - [x] **ENRSCHE1**: check next check of reschedule is last_check+interval_check - [x] **LOGV2BE2**: log-v2 enabled old log enabled check broker sink is equal - [x] **LOGV2DB1**: log-v2 disabled old log enabled check broker sink diff --git a/tests/bam/inherited_downtime.robot b/tests/bam/inherited_downtime.robot index f4db481a8fd..24586224e5a 100644 --- a/tests/bam/inherited_downtime.robot +++ b/tests/bam/inherited_downtime.robot @@ -63,6 +63,10 @@ BEBAMIDT1 Delete Service Downtime host_16 service_314 ${result}= Check Service Downtime With Timeout host_16 service_314 0 60 Should Be True ${result} msg=The service (host_16, service_314) is in downtime and should not. + + ${result}= Check Downtimes With Timeout 0 60 + Should Be True ${result} msg=We should have no more running downtimes + ${result}= Check Service Downtime With Timeout _Module_BAM_1 ba_1 0 60 Should Be True ${result} msg=The BA ba_1 is in downtime as it should not @@ -110,6 +114,10 @@ BEBAMIDT2 Schedule Service Downtime host_16 service_314 3600 ${result}= Check Service Downtime With Timeout host_16 service_314 1 60 Should Be True ${result} msg=The service (host_16, service_314) is not in downtime as it should be + + ${result}= Check Downtimes With Timeout 2 60 + Should Be True ${result} msg=We should have one running downtime + ${result}= Check Service Downtime With Timeout _Module_BAM_1 ba_1 1 60 Should Be True ${result} msg=The BA ba_1 is not in downtime as it should @@ -131,20 +139,19 @@ BEBAMIDT2 END # There are still two downtimes: the one on the ba and the one on the kpi. - ${result}= Number Of Downtimes is 2 60 - Should Be True ${result} msg=We should only have only two downtimes + ${result}= Check Downtimes With Timeout 2 60 + Should Be True ${result} msg=We should have two downtimes # The downtime is deleted Delete Service Downtime host_16 service_314 ${result}= Check Service Downtime With Timeout host_16 service_314 0 60 Should Be True ${result} msg=The service (host_16, service_314) is in downtime and should not. + ${result}= Check Downtimes With Timeout 0 60 + Should Be True ${result} msg=We should have no more downtime + ${result}= Check Service Downtime With Timeout _Module_BAM_1 ba_1 0 60 Should Be True ${result} msg=The BA ba_1 is in downtime as it should not - # We should have no more downtime - ${result}= Number Of Downtimes Is 0 60 - Should Be True ${result} msg=We should have no more downtime - log to console Broker is stopped (end of BEBAMIDT2) Stop Engine Kindly Stop Broker @@ -232,6 +239,9 @@ BEBAMIGNDT1 Should Be True ${result} msg=The service (host_16, service_314) does not contain 1 downtime as it should Log to console Still one downtime applied to service_314. + ${result}= Check Downtimes With Timeout 1 60 + Should Be True ${result} msg=We should have one downtime + ${result}= Check Ba Status With Timeout test 0 60 Should Be True ${result} msg=The BA is not OK whereas the service_314 is still in downtime. Log to console The BA is still OK @@ -243,6 +253,9 @@ BEBAMIGNDT1 Should Be True ${result} msg=The service (host_16, service_314) does not contain 0 downtime as it should Log to console No more downtime applied to service_314. + ${result}= Check Downtimes With Timeout 0 60 + Should Be True ${result} msg=We should have no more running downtimes + ${result}= Check Ba Status With Timeout test 2 60 Should Be True ${result} msg=The critical service is no more in downtime, the BA should be critical. Log to console The BA is now critical (no more downtime) @@ -328,95 +341,8 @@ BEBAMIGNDT2 Should Be True ${result} msg=The BA is not OK whereas the service_314 is still in downtime. Log to console The BA is still OK - # The second downtime finishes - ${result}= Check Ba Status With Timeout test 2 60 - Should Be True ${result} msg=The critical service is no more in downtime, the BA should be critical. - Log to console The BA is now critical (no more downtime) - - Stop Engine - Kindly Stop Broker - -BEBAMIGNDTU1 - [Documentation] A BA of type 'worst' with two services is configured. The downtime policy on this ba is "Ignore the indicator in the calculation". The BA is in critical state, because of the second critical service. Then we apply two downtimes on this last one. The BA state is ok because of the policy on indicators. The first downtime reaches its end, the BA is still OK, but when the second downtime reaches its end, the BA should be CRITICAL. - [Tags] broker downtime engine bam bbdo - Clear Commands Status - Config Broker module - Config Broker central - Config Broker rrd - Broker Config Log central core error - Broker Config Log central bam trace - Config Broker Sql Output central unified_sql - Broker Config Add Item module0 bbdo_version 3.0.1 - Broker Config Add Item rrd bbdo_version 3.0.1 - Broker Config Add Item central bbdo_version 3.0.1 - Config Engine ${1} - - Clone Engine Config To DB - Add Bam Config To Engine - - @{svc}= Set Variable ${{ [("host_16", "service_313"), ("host_16", "service_314")] }} - Create BA With Services test worst ${svc} ignore - Add Bam Config To Broker central - # Command of service_314 is set to critical - ${cmd_1}= Get Command Id 313 - Log To Console service_314 has command id ${cmd_1} - Set Command Status ${cmd_1} 0 - ${cmd_2}= Get Command Id 314 - Log To Console service_314 has command id ${cmd_2} - Set Command Status ${cmd_2} 2 - Start Broker - ${start}= Get Current Date - Start Engine - # Let's wait for the initial service states. - ${content}= Create List INITIAL SERVICE STATE: host_50;service_1000; - ${result}= Find In Log with Timeout ${engineLog0} ${start} ${content} 60 - Should Be True ${result} msg=An Initial service state on service (50, 1000) should be raised before we can start external commands. - - # KPI set to ok - Repeat Keyword 3 times Process Service Check Result host_16 service_313 0 output critical for 313 - ${result}= Check Service Status With Timeout host_16 service_313 0 60 - Should Be True ${result} msg=The service (host_16,service_313) is not OK as expected - - # KPI set to critical - Repeat Keyword 3 times Process Service Check Result host_16 service_314 2 output critical for 314 - ${result}= Check Service Status With Timeout host_16 service_314 2 60 - Should Be True ${result} msg=The service (host_16,service_314) is not CRITICAL as expected - - # The BA should become critical - ${result}= Check Ba Status With Timeout test 2 60 - Should Be True ${result} msg=The BA ba_1 is not CRITICAL as expected - Log To console The BA is critical. - - # Two downtimes are applied on service_314 - Schedule Service Downtime host_16 service_314 60 - ${result}= Check Service Downtime With Timeout host_16 service_314 1 60 - Should Be True ${result} msg=The service (host_16, service_314) is not in downtime as it should be - Log to console One downtime applied to service_314. - - Schedule Service Downtime host_16 service_314 30 - ${result}= Check Service Downtime With Timeout host_16 service_314 2 60 - Should Be True ${result} msg=The service (host_16, service_314) is not in downtime as it should be - Log to console Two downtimes applied to service_314. - - ${result}= Check Service Downtime With Timeout _Module_BAM_1 ba_1 0 60 - Should Be True ${result} msg=The BA ba_1 is in downtime but should not - Log to console The BA is configured to ignore kpis in downtime - - ${result}= Check Ba Status With Timeout test 0 60 - Should Be True ${result} msg=The service in downtime should be ignored while computing the state of this BA. - Log to console The BA is OK, since the critical service is in downtime. - - # The first downtime should reach its end - - Log to console After 30s, the first downtime should be finished. - ${result}= Check Service Downtime With Timeout host_16 service_314 1 60 - Should Be True ${result} msg=The service (host_16, service_314) does not contain 1 downtime as it should - Log to console Still one downtime applied to service_314. - - Log to console After 30s, the second downtime should be finished. - ${result}= Check Ba Status With Timeout test 0 60 - Should Be True ${result} msg=The BA is not OK whereas the service_314 is still in downtime. - Log to console The BA is still OK + ${result}= Check Downtimes With Timeout 0 60 + Should Be True ${result} msg=We should have no more running downtimes # The second downtime finishes ${result}= Check Ba Status With Timeout test 2 60 @@ -425,9 +351,6 @@ BEBAMIGNDTU1 Stop Engine Kindly Stop Broker - ${lst}= Create List 1 0 3 - ${result}= Check Types in resources ${lst} - Should Be True ${result} msg=The table 'resources' should contain rows of types SERVICE, HOST and BA. *** Keywords *** BAM Setup @@ -435,4 +358,4 @@ BAM Setup Connect To Database pymysql ${DBName} ${DBUser} ${DBPass} ${DBHost} ${DBPort} ${date}= Get Current Date result_format=epoch log to console date=${date} - Query UPDATE downtimes SET deletion_time=${date}, actual_end_time=${date} WHERE actual_end_time is null + Execute SQL String UPDATE downtimes SET deletion_time=${date}, actual_end_time=${date} WHERE actual_end_time is null diff --git a/tests/bam/pb_inherited_downtime.robot b/tests/bam/pb_inherited_downtime.robot new file mode 100644 index 00000000000..abaa9f89c18 --- /dev/null +++ b/tests/bam/pb_inherited_downtime.robot @@ -0,0 +1,370 @@ +*** Settings *** +Resource ../resources/resources.robot +Suite Setup Clean Before Suite +Suite Teardown Clean After Suite +Test Setup BAM Setup +Test Teardown Save logs If Failed + +Documentation Centreon Broker and BAM with bbdo version 3.0.1 +Library Process +Library DatabaseLibrary +Library DateTime +Library OperatingSystem +Library ../resources/Broker.py +Library ../resources/Engine.py + + +*** Test Cases *** +BEBAMIDTU1 + [Documentation] With bbdo version 3.0.1, a BA of type 'worst' with one service is configured. The BA is in critical state, because of its service. Then we set a downtime on this last one. An inherited downtime is set to the BA. The downtime is removed from the service, the inherited downtime is then deleted. + [Tags] Broker downtime engine bam + Clear Commands Status + Config Broker module + Config Broker central + Config Broker rrd + Broker Config Log central bam trace + Config Broker Sql Output central unified_sql + Broker Config Add Item module0 bbdo_version 3.0.1 + Broker Config Add Item rrd bbdo_version 3.0.1 + Broker Config Add Item central bbdo_version 3.0.1 + Config Engine ${1} + + Clone Engine Config To DB + Add Bam Config To Engine + + @{svc}= Set Variable ${{ [("host_16", "service_314")] }} + Create BA With Services test worst ${svc} + Add Bam Config To Broker central + # Command of service_314 is set to critical + ${cmd_1}= Get Command Id 314 + Log To Console service_314 has command id ${cmd_1} + Set Command Status ${cmd_1} 2 + Start Broker + ${start}= Get Current Date + Start Engine + # Let's wait for the initial service states. + ${content}= Create List INITIAL SERVICE STATE: host_50;service_1000; + ${result}= Find In Log with Timeout ${engineLog0} ${start} ${content} 60 + Should Be True ${result} msg=An Initial service state on service (50, 1000) should be raised before we can start external commands. + + # KPI set to critical + Repeat Keyword 3 times Process Service Check Result host_16 service_314 2 output critical for 314 + ${result}= Check Service Status With Timeout host_16 service_314 2 60 HARD + Should Be True ${result} msg=The service (host_16,service_314) is not CRITICAL as expected + + # The BA should become critical + ${result}= Check Ba Status With Timeout test 2 60 + Should Be True ${result} msg=The BA ba_1 is not CRITICAL as expected + + # A downtime is put on service_314 + Schedule Service Downtime host_16 service_314 3600 + ${result}= Check Service Downtime With Timeout host_16 service_314 1 60 + Should Be True ${result} msg=The service (host_16, service_314) is not in downtime as it should be + ${result}= Check Service Downtime With Timeout _Module_BAM_1 ba_1 1 60 + Should Be True ${result} msg=The BA ba_1 is not in downtime as it should + + # The downtime is deleted + Delete Service Downtime host_16 service_314 + ${result}= Check Service Downtime With Timeout host_16 service_314 0 60 + Should Be True ${result} msg=The service (host_16, service_314) is in downtime and should not. + + ${result}= Check Downtimes With Timeout 0 60 + Should Be True ${result} msg=No downtime should still be running. + ${result}= Check Service Downtime With Timeout _Module_BAM_1 ba_1 0 60 + Should Be True ${result} msg=The BA ba_1 is in downtime as it should not + + Stop Engine + Kindly Stop Broker + +BEBAMIDTU2 + [Documentation] With bbdo version 3.0.1, a BA of type 'worst' with one service is configured. The BA is in critical state, because of its service. Then we set a downtime on this last one. An inherited downtime is set to the BA. Engine is restarted. Broker is restarted. The two downtimes are still there with no duplicates. The downtime is removed from the service, the inherited downtime is then deleted. + [Tags] Broker downtime engine bam start stop + Clear Commands Status + Config Broker module + Config Broker central + Config Broker rrd + Broker Config Log central bam trace + Config Broker Sql Output central unified_sql + Broker Config Add Item module0 bbdo_version 3.0.1 + Broker Config Add Item rrd bbdo_version 3.0.1 + Broker Config Add Item central bbdo_version 3.0.1 + Config Engine ${1} + + Clone Engine Config To DB + Add Bam Config To Engine + + @{svc}= Set Variable ${{ [("host_16", "service_314")] }} + Create BA With Services test worst ${svc} + Add Bam Config To Broker central + # Command of service_314 is set to critical + ${cmd_1}= Get Command Id 314 + Log To Console service_314 has command id ${cmd_1} + Set Command Status ${cmd_1} 2 + Start Broker + ${start}= Get Current Date + Start Engine + # Let's wait for the initial service states. + ${content}= Create List INITIAL SERVICE STATE: host_50;service_1000; + ${result}= Find In Log with Timeout ${engineLog0} ${start} ${content} 60 + Should Be True ${result} msg=An Initial service state on service (50, 1000) should be raised before we can start external commands. + + # KPI set to critical + Repeat Keyword 3 times Process Service Check Result host_16 service_314 2 output critical for 314 + ${result}= Check Service Status With Timeout host_16 service_314 2 60 + Should Be True ${result} msg=The service (host_16,service_314) is not CRITICAL as expected + + # The BA should become critical + ${result}= Check Ba Status With Timeout test 2 60 + Should Be True ${result} msg=The BA ba_1 is not CRITICAL as expected + + # A downtime is put on service_314 + Schedule Service Downtime host_16 service_314 3600 + ${result}= Check Service Downtime With Timeout host_16 service_314 1 60 + Should Be True ${result} msg=The service (host_16, service_314) is not in downtime as it should be + ${result}= Check Service Downtime With Timeout _Module_BAM_1 ba_1 1 60 + Should Be True ${result} msg=The BA ba_1 is not in downtime as it should + + FOR ${i} IN RANGE 2 + # Engine is restarted + Stop Engine + ${start}= Get Current Date + Start Engine + # Let's wait for the initial service states. + ${content}= Create List INITIAL SERVICE STATE: host_50;service_1000; + ${result}= Find In Log with Timeout ${engineLog0} ${start} ${content} 60 + Should Be True ${result} msg=An Initial service state on service (50, 1000) should be raised before we can start external commands. + + # Broker is restarted + log to console Broker is stopped (step ${i}) + Kindly Stop Broker + log to console Broker is started + Start Broker + END + + # There are still two downtimes: the one on the ba and the one on the kpi. + ${result}= Number Of Downtimes is 2 60 + Should Be True ${result} msg=We should only have only two downtimes + + # The downtime is deleted + Delete Service Downtime host_16 service_314 + ${result}= Check Service Downtime With Timeout host_16 service_314 0 60 + Should Be True ${result} msg=The service (host_16, service_314) is in downtime and should not. + ${result}= Check Service Downtime With Timeout _Module_BAM_1 ba_1 0 60 + Should Be True ${result} msg=The BA ba_1 is in downtime as it should not + + # We should have no more downtime + ${result}= Number Of Downtimes Is 0 60 + Should Be True ${result} msg=We should have no more downtime + + log to console Broker is stopped (end of BEBAMIDT2) + Stop Engine + Kindly Stop Broker + +BEBAMIGNDTU1 + [Documentation] With bbdo version 3.0.1, a BA of type 'worst' with two services is configured. The downtime policy on this ba is "Ignore the indicator in the calculation". The BA is in critical state, because of the second critical service. Then we apply two downtimes on this last one. The BA state is ok because of the policy on indicators. A first downtime is cancelled, the BA is still OK, but when the second downtime is cancelled, the BA should be CRITICAL. + [Tags] broker downtime engine bam + Clear Commands Status + Config Broker module + Config Broker central + Broker Config Log central bam trace + Broker Config Log central sql trace + Broker Config Flush Log module0 0 + Broker Config Log module0 neb trace + Config Broker rrd + Config Broker Sql Output central unified_sql + Broker Config Add Item module0 bbdo_version 3.0.1 + Broker Config Add Item rrd bbdo_version 3.0.1 + Broker Config Add Item central bbdo_version 3.0.1 + Config Engine ${1} + Engine Config Set Value ${0} log_legacy_enabled ${0} + Engine Config Set Value ${0} log_v2_enabled ${1} + Engine Config Set Value ${0} log_level_functions trace + Engine Config Set Value ${0} log_flush_period 0 True + + Clone Engine Config To DB + Add Bam Config To Engine + + @{svc}= Set Variable ${{ [("host_16", "service_313"), ("host_16", "service_314")] }} + Create BA With Services test worst ${svc} ignore + Add Bam Config To Broker central + + # Command of service_313 is set to ok + ${cmd_1}= Get Command Id 313 + Log To Console service_313 has command id ${cmd_1} + Set Command Status ${cmd_1} 0 + + # Command of service_314 is set to critical + ${cmd_2}= Get Command Id 314 + Log To Console service_314 has command id ${cmd_2} + Set Command Status ${cmd_2} 2 + + Start Broker + ${start}= Get Current Date + Start Engine + # Let's wait for the initial service states. + ${content}= Create List INITIAL SERVICE STATE: host_50;service_1000; + ${result}= Find In Log with Timeout ${engineLog0} ${start} ${content} 60 + Should Be True ${result} msg=An Initial service state on service (50, 1000) should be raised before we can start external commands. + + # KPI set to ok + Repeat Keyword 3 times Process Service Check Result host_16 service_313 0 output critical for 313 + ${result}= Check Service Status With Timeout host_16 service_313 0 60 + Should Be True ${result} msg=The service (host_16,service_313) is not OK as expected + + # KPI set to critical + Repeat Keyword 3 times Process Service Check Result host_16 service_314 2 output critical for 314 + ${result}= Check Service Status With Timeout host_16 service_314 2 60 + Should Be True ${result} msg=The service (host_16,service_314) is not CRITICAL as expected + + # The BA should become critical + ${result}= Check Ba Status With Timeout test 2 60 + Should Be True ${result} msg=The BA ba_1 is not CRITICAL as expected + Log To console The BA is critical. + + # Two downtimes are applied on service_314 + Schedule Service Downtime host_16 service_314 3600 + ${result}= Check Service Downtime With Timeout host_16 service_314 1 60 + Should Be True ${result} msg=The service (host_16, service_314) is not in downtime as it should be + Log to console One downtime applied to service_314. + + Schedule Service Downtime host_16 service_314 1800 + ${result}= Check Service Downtime With Timeout host_16 service_314 2 60 + Should Be True ${result} msg=The service (host_16, service_314) is not in downtime as it should be + Log to console Two downtimes applied to service_314. + + ${result}= Check Service Downtime With Timeout _Module_BAM_1 ba_1 0 60 + Should Be True ${result} msg=The BA ba_1 is in downtime but should not + Log to console The BA is configured to ignore kpis in downtime + + ${result}= Check Ba Status With Timeout test 0 60 + Should Be True ${result} msg=The service in downtime should be ignored while computing the state of this BA. + Log to console The BA is OK, since the critical service is in downtime. + + # The first downtime is deleted + Delete Service Downtime host_16 service_314 + + ${result}= Check Service Downtime With Timeout host_16 service_314 1 60 + Should Be True ${result} msg=The service (host_16, service_314) does not contain 1 downtime as it should + Log to console Still one downtime applied to service_314. + + ${result}= Check Ba Status With Timeout test 0 60 + Should Be True ${result} msg=The BA is not OK whereas the service_314 is still in downtime. + Log to console The BA is still OK + + ${result}= Check Downtimes With Timeout 1 60 + Should Be True ${result} msg=We should have one running downtime + + # The second downtime is deleted + Delete Service Downtime host_16 service_314 + + ${result}= Check Service Downtime With Timeout host_16 service_314 0 60 + Should Be True ${result} msg=The service (host_16, service_314) does not contain 0 downtime as it should + Log to console No more downtime applied to service_314. + + ${result}= Check Downtimes With Timeout 0 60 + Should Be True ${result} msg=We should have no more running downtimes + + ${result}= Check Ba Status With Timeout test 2 60 + Should Be True ${result} msg=The critical service is no more in downtime, the BA should be critical. + Log to console The BA is now critical (no more downtime) + + Stop Engine + Kindly Stop Broker + +BEBAMIGNDTU2 + [Documentation] With bbdo version 3.0.1, a BA of type 'worst' with two services is configured. The downtime policy on this ba is "Ignore the indicator in the calculation". The BA is in critical state, because of the second critical service. Then we apply two downtimes on this last one. The BA state is ok because of the policy on indicators. The first downtime reaches its end, the BA is still OK, but when the second downtime reaches its end, the BA should be CRITICAL. + [Tags] broker downtime engine bam + Clear Commands Status + Config Broker module + Config Broker central + Broker Config Log central core error + Broker Config Log central bam trace + Config Broker rrd + Config Broker Sql Output central unified_sql + Broker Config Add Item module0 bbdo_version 3.0.1 + Broker Config Add Item rrd bbdo_version 3.0.1 + Broker Config Add Item central bbdo_version 3.0.1 + Config Engine ${1} + + Clone Engine Config To DB + Add Bam Config To Engine + + @{svc}= Set Variable ${{ [("host_16", "service_313"), ("host_16", "service_314")] }} + Create BA With Services test worst ${svc} ignore + Add Bam Config To Broker central + # Command of service_314 is set to critical + ${cmd_1}= Get Command Id 313 + Log To Console service_314 has command id ${cmd_1} + Set Command Status ${cmd_1} 0 + ${cmd_2}= Get Command Id 314 + Log To Console service_314 has command id ${cmd_2} + Set Command Status ${cmd_2} 2 + Start Broker + ${start}= Get Current Date + Start Engine + # Let's wait for the initial service states. + ${content}= Create List INITIAL SERVICE STATE: host_50;service_1000; + ${result}= Find In Log with Timeout ${engineLog0} ${start} ${content} 60 + Should Be True ${result} msg=An Initial service state on service (50, 1000) should be raised before we can start external commands. + + # KPI set to ok + Repeat Keyword 3 times Process Service Check Result host_16 service_313 0 output critical for 313 + ${result}= Check Service Status With Timeout host_16 service_313 0 60 + Should Be True ${result} msg=The service (host_16,service_313) is not OK as expected + + # KPI set to critical + Repeat Keyword 3 times Process Service Check Result host_16 service_314 2 output critical for 314 + ${result}= Check Service Status With Timeout host_16 service_314 2 60 + Should Be True ${result} msg=The service (host_16,service_314) is not CRITICAL as expected + + # The BA should become critical + ${result}= Check Ba Status With Timeout test 2 60 + Should Be True ${result} msg=The BA ba_1 is not CRITICAL as expected + Log To console The BA is critical. + + # Two downtimes are applied on service_314 + Schedule Service Downtime host_16 service_314 60 + ${result}= Check Service Downtime With Timeout host_16 service_314 1 60 + Should Be True ${result} msg=The service (host_16, service_314) is not in downtime as it should be + Log to console One downtime applied to service_314. + + Schedule Service Downtime host_16 service_314 30 + ${result}= Check Service Downtime With Timeout host_16 service_314 2 60 + Should Be True ${result} msg=The service (host_16, service_314) is not in downtime as it should be + Log to console Two downtimes applied to service_314. + + ${result}= Check Service Downtime With Timeout _Module_BAM_1 ba_1 0 60 + Should Be True ${result} msg=The BA ba_1 is in downtime but should not + Log to console The BA is configured to ignore kpis in downtime + + ${result}= Check Ba Status With Timeout test 0 60 + Should Be True ${result} msg=The service in downtime should be ignored while computing the state of this BA. + Log to console The BA is OK, since the critical service is in downtime. + + # The first downtime should reach its end + + Log to console After 30s, the first downtime should be finished. + ${result}= Check Service Downtime With Timeout host_16 service_314 1 60 + Should Be True ${result} msg=The service (host_16, service_314) does not contain 1 downtime as it should + Log to console Still one downtime applied to service_314. + + Log to console After 30s, the second downtime should be finished. + ${result}= Check Ba Status With Timeout test 0 60 + Should Be True ${result} msg=The BA is not OK whereas the service_314 is still in downtime. + Log to console The BA is still OK + + # The second downtime finishes + ${result}= Check Ba Status With Timeout test 2 60 + Should Be True ${result} msg=The critical service is no more in downtime, the BA should be critical. + Log to console The BA is now critical (no more downtime) + + Stop Engine + Kindly Stop Broker + +*** Keywords *** +BAM Setup + Stop Processes + Connect To Database pymysql ${DBName} ${DBUser} ${DBPass} ${DBHost} ${DBPort} + ${date}= Get Current Date result_format=epoch + log to console Cleaning downtimes at date=${date} + Execute SQL String UPDATE downtimes SET deletion_time=${date}, actual_end_time=${date} WHERE actual_end_time is null diff --git a/tests/broker-engine/reverse-connection.robot b/tests/broker-engine/reverse-connection.robot index 424d1e0d88b..b34c0a5e687 100644 --- a/tests/broker-engine/reverse-connection.robot +++ b/tests/broker-engine/reverse-connection.robot @@ -74,7 +74,7 @@ BRCTS1 BRCS1 [Documentation] Broker reverse connection stopped - [Tags] Broker map reverse connection stopped + [Tags] Broker map reversed Config Engine ${1} Config Broker rrd Config Broker central_map diff --git a/tests/resources/Broker.py b/tests/resources/Broker.py index b317fb2073d..6b369ec6f37 100755 --- a/tests/resources/Broker.py +++ b/tests/resources/Broker.py @@ -436,23 +436,22 @@ def config_broker(name, poller_inst: int = 1): broker_name = "central-module-master" filename = "central-module0.json" else: - if not exists(VAR_ROOT + "/lib/centreon/metrics/"): - makedirs(VAR_ROOT + "/lib/centreon/metrics/") - if not exists(VAR_ROOT + "/lib/centreon/status/"): - makedirs(VAR_ROOT + "/lib/centreon/status/") - if not exists(VAR_ROOT + "/lib/centreon/metrics/tmpl_15552000_300_0.rrd"): + if not exists(f"{VAR_ROOT}/lib/centreon/metrics/"): + makedirs(f"{VAR_ROOT}/lib/centreon/metrics/") + if not exists(f"{VAR_ROOT}/lib/centreon/status/"): + makedirs(f"{VAR_ROOT}/lib/centreon/status/") + if not exists(f"{VAR_ROOT}/lib/centreon/metrics/tmpl_15552000_300_0.rrd"): getoutput( - "rrdcreate " + VAR_ROOT + "/lib/centreon/metrics/tmpl_15552000_300_0.rrd DS:value:ABSOLUTE:3000:U:U RRA:AVERAGE:0.5:1:864000") + f"rrdcreate {VAR_ROOT}/lib/centreon/metrics/tmpl_15552000_300_0.rrd DS:value:ABSOLUTE:3000:U:U RRA:AVERAGE:0.5:1:864000") broker_id = 2 broker_name = "central-rrd-master" filename = "central-rrd.json" if name == 'module': for i in range(poller_inst): - broker_name = ETC_ROOT + "/centreon-broker/central-module{}.json".format( - i) + broker_name = f"{ETC_ROOT}/centreon-broker/central-module{i}.json" buf = config[name].format( - broker_id, "central-module-master{}".format(i), "", "", "", "", "", VAR_ROOT) + broker_id, f"central-module-master{i}", "", "", "", "", "", VAR_ROOT) conf = json.loads(buf) conf["centreonBroker"]["poller_name"] = f"Poller{i}" conf["centreonBroker"]["poller_id"] = i + 1 @@ -461,7 +460,7 @@ def config_broker(name, poller_inst: int = 1): f.write(json.dumps(conf, indent=2)) f.close() else: - f = open(ETC_ROOT + "/centreon-broker/{}".format(filename), "w") + f = open(f"{ETC_ROOT}/centreon-broker/{filename}", "w") f.write(config[name].format(broker_id, broker_name, DB_HOST, DB_PORT, DB_USER, DB_PASS, DB_NAME_STORAGE, VAR_ROOT)) f.close() @@ -1253,18 +1252,12 @@ def get_indexes_to_rebuild(count: int): "building data for metric {}".format(r['metric_id'])) start = int(time.time()) - 24 * 60 * 60 * 30 # We go back to 30 days with steps of 5 mn - value1 = int(r['metric_id']) - value2 = 0 - value = value1 + value = int(r['metric_id']) // 2 cursor.execute("DELETE FROM data_bin WHERE id_metric={} AND ctime >= {}".format( r['metric_id'], start)) - for i in range(0, 24 * 60 * 60 * 30, 60 * 5): + for i in range(0, 24 * 60 * 60 * 31, 60 * 5): cursor.execute("INSERT INTO data_bin (id_metric, ctime, value, status) VALUES ({},{},{},'0')".format( r['metric_id'], start + i, value)) - if value == value1: - value = value2 - else: - value = value1 connection.commit() retval.append(int(r['index_id'])) @@ -1427,7 +1420,7 @@ def compare_rrd_average_value(metric, value: float): return err < 0.05 else: logger.console( - "It was impossible to get the average value from the file " + VAR_ROOT + "/lib/centreon/metrics/{}.rrd from the last 30 days".format(metric)) + f"It was impossible to get the average value from the file {VAR_ROOT}/lib/centreon/metrics/{metric}.rrd from the last 30 days") return True @@ -1494,7 +1487,7 @@ def add_bam_config_to_broker(name): else: filename = "central-rrd.json" - f = open(ETC_ROOT + "/centreon-broker/{}".format(filename), "r") + f = open(f"{ETC_ROOT}/centreon-broker/{filename}", "r") buf = f.read() f.close() conf = json.loads(buf) diff --git a/tests/resources/Common.py b/tests/resources/Common.py index ae0114b9e34..7e9a4135aff 100644 --- a/tests/resources/Common.py +++ b/tests/resources/Common.py @@ -474,6 +474,28 @@ def check_ba_status_with_timeout(ba_name: str, status: int, timeout: int): return False +def check_downtimes_with_timeout(nb: int, timeout: int): + limit = time.time() + timeout + while time.time() < limit: + connection = pymysql.connect(host=DB_HOST, + user=DB_USER, + password=DB_PASS, + database=DB_NAME_STORAGE, + charset='utf8mb4', + cursorclass=pymysql.cursors.DictCursor) + + with connection: + with connection.cursor() as cursor: + cursor.execute("SELECT count(*) FROM downtimes WHERE deletion_time IS NULL") + result = cursor.fetchall() + if len(result) > 0 and not result[0]['count(*)'] is None: + logger.console(result[0]['count(*)']) + if result[0]['count(*)'] == int(nb): + return True + else: + logger.console(f"We should have {nb} downtimes but we have {result[0]['count(*)']}") + time.sleep(2) + return False def check_service_downtime_with_timeout(hostname: str, service_desc: str, enabled, timeout: int): limit = time.time() + timeout while time.time() < limit: @@ -495,8 +517,7 @@ def check_service_downtime_with_timeout(hostname: str, service_desc: str, enable return False -def delete_service_downtime(hst: str, svc: str): - now = int(time.time()) +def show_downtimes(): connection = pymysql.connect(host=DB_HOST, user=DB_USER, password=DB_PASS, @@ -507,11 +528,33 @@ def delete_service_downtime(hst: str, svc: str): with connection: with connection.cursor() as cursor: cursor.execute( - f"select d.internal_id from downtimes d inner join hosts h on d.host_id=h.host_id inner join services s on d.service_id=s.service_id where d.deletion_time is null and s.scheduled_downtime_depth<>'0' and s.description='{svc}' and h.name='{hst}' LIMIT 1") + f"select * FROM downtimes WHERE deletion_time is null") result = cursor.fetchall() - did = int(result[0]['internal_id']) - cmd = f"[{now}] DEL_SVC_DOWNTIME;{did}" + for r in result: + logger.console(f" >> {r}") + +def delete_service_downtime(hst: str, svc: str): + now = int(time.time()) + while time.time() < now + TIMEOUT: + connection = pymysql.connect(host=DB_HOST, + user=DB_USER, + password=DB_PASS, + database=DB_NAME_STORAGE, + charset='utf8mb4', + cursorclass=pymysql.cursors.DictCursor) + + with connection: + with connection.cursor() as cursor: + cursor.execute( + f"select d.internal_id from downtimes d inner join hosts h on d.host_id=h.host_id inner join services s on d.service_id=s.service_id where d.deletion_time is null and s.scheduled_downtime_depth<>'0' and s.description='{svc}' and h.name='{hst}' LIMIT 1") + result = cursor.fetchall() + if len(result) > 0: + did = int(result[0]['internal_id']) + break + time.sleep(1) + + cmd = f"[{now}] DEL_SVC_DOWNTIME;{did}\n" f = open(VAR_ROOT + "/lib/centreon-engine/config0/rw/centengine.cmd", "w") f.write(cmd) f.close() @@ -715,7 +758,7 @@ def check_number_of_downtimes(expected: int, start, timeout: int): with connection: with connection.cursor() as cursor: cursor.execute( - "SELECT count(*) FROM downtimes WHERE enabled='1' AND start_time >= {} AND deletion_time IS NULL".format(d)) + "SELECT count(*) FROM downtimes WHERE start_time >= {} AND deletion_time IS NULL".format(d)) result = cursor.fetchall() if len(result) > 0: logger.console( diff --git a/tests/resources/resources.robot b/tests/resources/resources.robot index f0cc928182b..bba735b0c1f 100644 --- a/tests/resources/resources.robot +++ b/tests/resources/resources.robot @@ -132,10 +132,12 @@ Check Connections FOR ${idx} IN RANGE 0 ${count} ${alias}= Catenate SEPARATOR= e ${idx} ${pid2}= Get Process Id ${alias} + Log to console Check Connection 5669 ${pid1} ${pid2} ${retval}= Check Connection 5669 ${pid1} ${pid2} Return from Keyword If ${retval} == ${False} ${False} END ${pid2}= Get Process Id b2 + Log to console Check Connection 5670 ${pid1} ${pid2} ${retval}= Check Connection 5670 ${pid1} ${pid2} [Return] ${retval} @@ -157,6 +159,7 @@ Save Logs ${failDir}= Catenate SEPARATOR= failed/ ${Test Name} Create Directory ${failDir} Copy files ${centralLog} ${failDir} + Copy files ${rrdLog} ${failDir} Copy files ${moduleLog0} ${failDir} Copy files ${engineLog0} ${failDir} Copy files ${ENGINE_LOG}/config0/gcore_* ${failDir}