From b9ac220ff8533005cb03d9fac014a1b6dbc6cf6d Mon Sep 17 00:00:00 2001 From: Sechkem Date: Wed, 27 Nov 2024 11:16:25 +0100 Subject: [PATCH] fix(engine): coredump when disabling a host with children relation (#1863) * fix(engine/broker): make parents_host shared ptr & remove relation db when child is deleted * feat(test): add tests EBPN about relation parent child REFS: MON-152645 --- broker/neb/src/callbacks.cc | 14 +- broker/neb/src/initial.cc | 6 +- engine/enginerpc/engine.proto | 3 + engine/enginerpc/engine_impl.cc | 12 +- engine/inc/com/centreon/engine/host.hh | 5 +- engine/src/configuration/applier/host.cc | 17 +- engine/src/host.cc | 97 +++---- engine/src/macros/grab_host.cc | 12 +- .../broker-engine/parent_child_relation.robot | 262 ++++++++++++++++++ tests/resources/Engine.py | 100 +++++++ 10 files changed, 446 insertions(+), 82 deletions(-) create mode 100644 tests/broker-engine/parent_child_relation.robot diff --git a/broker/neb/src/callbacks.cc b/broker/neb/src/callbacks.cc index 783db2a2609..f6a8ec4b3ab 100644 --- a/broker/neb/src/callbacks.cc +++ b/broker/neb/src/callbacks.cc @@ -2908,12 +2908,8 @@ int neb::callback_relation(int callback_type, void* data) { if (relation->hst && relation->dep_hst && !relation->svc && !relation->dep_svc) { // Find host IDs. - int host_id; - int parent_id; - { - host_id = engine::get_host_id(relation->dep_hst->name()); - parent_id = engine::get_host_id(relation->hst->name()); - } + int host_id = relation->dep_hst->host_id(); + int parent_id = relation->hst->host_id(); if (host_id && parent_id) { // Generate parent event. auto new_host_parent{std::make_shared()}; @@ -2964,10 +2960,8 @@ int neb::callback_pb_relation(int callback_type [[maybe_unused]], void* data) { if (relation->hst && relation->dep_hst && !relation->svc && !relation->dep_svc) { // Find host IDs. - int host_id; - int parent_id; - host_id = engine::get_host_id(relation->dep_hst->name()); - parent_id = engine::get_host_id(relation->hst->name()); + int host_id = relation->dep_hst->host_id(); + int parent_id = relation->hst->host_id(); if (host_id && parent_id) { // Generate parent event. auto new_host_parent{std::make_shared()}; diff --git a/broker/neb/src/initial.cc b/broker/neb/src/initial.cc index a8fad65920e..2d2c2cd8a42 100644 --- a/broker/neb/src/initial.cc +++ b/broker/neb/src/initial.cc @@ -336,14 +336,12 @@ static void send_host_parents_list(neb_sender sender = neb::callback_relation) { end{com::centreon::engine::host::hosts.end()}; it != end; ++it) { // Loop through all parents. - for (host_map_unsafe::iterator pit{it->second->parent_hosts.begin()}, - pend{it->second->parent_hosts.end()}; - pit != pend; ++pit) { + for (auto [_, sptr_host] : it->second->parent_hosts) { // Fill callback struct. nebstruct_relation_data nsrd; memset(&nsrd, 0, sizeof(nsrd)); nsrd.type = NEBTYPE_PARENT_ADD; - nsrd.hst = pit->second; + nsrd.hst = sptr_host.get(); nsrd.dep_hst = it->second.get(); // Callback. diff --git a/engine/enginerpc/engine.proto b/engine/enginerpc/engine.proto index f11b867dda0..2280e53f9d1 100644 --- a/engine/enginerpc/engine.proto +++ b/engine/enginerpc/engine.proto @@ -356,6 +356,9 @@ message EngineHost { UNREACHABLE = 2; } State current_state = 6; + string display_name = 7; + repeated string parent_hosts = 8; + repeated string child_hosts = 9; } message ContactIdentifier { diff --git a/engine/enginerpc/engine_impl.cc b/engine/enginerpc/engine_impl.cc index 0476f9dc9d0..f32a0aefc5e 100644 --- a/engine/enginerpc/engine_impl.cc +++ b/engine/enginerpc/engine_impl.cc @@ -245,9 +245,19 @@ grpc::Status engine_impl::GetHost(grpc::ServerContext* context [[maybe_unused]], host->set_alias(selectedhost->get_alias()); host->set_address(selectedhost->get_address()); host->set_check_period(selectedhost->check_period()); + host->set_id(selectedhost->host_id()); host->set_current_state( static_cast(selectedhost->get_current_state())); - host->set_id(selectedhost->host_id()); + host->set_display_name(selectedhost->get_display_name()); + + if (!selectedhost->parent_hosts.empty()) + for (const auto& [key, _] : selectedhost->parent_hosts) + host->add_parent_hosts(key); + + if (!selectedhost->child_hosts.empty()) + for (const auto& [key, _] : selectedhost->child_hosts) + host->add_child_hosts(key); + return 0; }); diff --git a/engine/inc/com/centreon/engine/host.hh b/engine/inc/com/centreon/engine/host.hh index c91f28a5e6a..0c97d18c5eb 100644 --- a/engine/inc/com/centreon/engine/host.hh +++ b/engine/inc/com/centreon/engine/host.hh @@ -250,7 +250,7 @@ class host : public notifier { void set_check_command_ptr( const std::shared_ptr& cmd) override; - host_map_unsafe parent_hosts; + host_map parent_hosts; host_map_unsafe child_hosts; static host_map hosts; static host_id_map hosts_by_id; @@ -307,6 +307,7 @@ int number_of_total_parent_hosts(com::centreon::engine::host* hst); std::ostream& operator<<(std::ostream& os, com::centreon::engine::host const& obj); std::ostream& operator<<(std::ostream& os, host_map_unsafe const& obj); +std::ostream& operator<<(std::ostream& os, host_map const& obj); namespace com::centreon::engine { @@ -318,6 +319,4 @@ std::string get_host_name(const uint64_t host_id); } // namespace com::centreon::engine -std::ostream& operator<<(std::ostream& os, host_map_unsafe const& obj); - #endif // !CCE_HOST_HH diff --git a/engine/src/configuration/applier/host.cc b/engine/src/configuration/applier/host.cc index 8459866d7ac..1e45408b6b0 100644 --- a/engine/src/configuration/applier/host.cc +++ b/engine/src/configuration/applier/host.cc @@ -374,10 +374,8 @@ void applier::host::modify_object(configuration::host const& obj) { if (obj.parents() != obj_old.parents()) { // Delete old parents. { - for (host_map_unsafe::iterator it(it_obj->second->parent_hosts.begin()), - end(it_obj->second->parent_hosts.end()); - it != end; it++) - broker_relation_data(NEBTYPE_PARENT_DELETE, it->second, nullptr, + for (const auto& [_, sptr_host] : it_obj->second->parent_hosts) + broker_relation_data(NEBTYPE_PARENT_DELETE, sptr_host.get(), nullptr, it_obj->second.get(), nullptr); } it_obj->second->parent_hosts.clear(); @@ -436,6 +434,11 @@ void applier::host::remove_object(configuration::host const& obj) { for (auto& it_h : it->second->get_parent_groups()) it_h->members.erase(it->second->name()); + // remove any relations + for (const auto& [_, sptr_host] : it->second->parent_hosts) + broker_relation_data(NEBTYPE_PARENT_DELETE, sptr_host.get(), nullptr, + it->second.get(), nullptr); + // Notify event broker. for (auto it_s = it->second->services.begin(); it_s != it->second->services.end(); ++it_s) @@ -470,10 +473,8 @@ void applier::host::resolve_object(configuration::host const& obj) { // It is necessary to do it only once to prevent the removal // of valid child backlinks. if (obj == *config->hosts().begin()) { - for (host_map::iterator it(engine::host::hosts.begin()), - end(engine::host::hosts.end()); - it != end; ++it) - it->second->child_hosts.clear(); + for (const auto& [_, sptr_host] : engine::host::hosts) + sptr_host->child_hosts.clear(); } // Find host. diff --git a/engine/src/host.cc b/engine/src/host.cc index ca62b79de61..f6f2b63e693 100644 --- a/engine/src/host.cc +++ b/engine/src/host.cc @@ -593,6 +593,19 @@ std::ostream& operator<<(std::ostream& os, host_map_unsafe const& obj) { return os; } +std::ostream& operator<<(std::ostream& os, host_map const& obj) { + bool first = true; + for (const auto& [key, _] : obj) { + if (first) { + first = false; + } else { + os << ", "; + } + os << key; + } + return os; +} + /** * Dump host content into the stream. * @@ -1036,8 +1049,7 @@ int is_host_immediate_child_of_host(com::centreon::engine::host* parent_host, } // Mid-level/bottom hosts. else { - host_map_unsafe::const_iterator it{ - child_host->parent_hosts.find(parent_host->name())}; + auto it{child_host->parent_hosts.find(parent_host->name())}; return it != child_host->parent_hosts.end(); } @@ -1856,8 +1868,8 @@ int host::run_async_check(int check_options, try { // Run command. get_check_command_ptr()->run(processed_cmd, *macros, - config->host_check_timeout(), - check_result_info); + config->host_check_timeout(), + check_result_info); } catch (com::centreon::exceptions::interruption const& e) { retry = true; } catch (std::exception const& e) { @@ -3157,17 +3169,15 @@ int host::process_check_result_3x(enum host::host_state new_state, SPDLOG_LOGGER_DEBUG(checks_logger, "Propagating checks to parent host(s)..."); - for (host_map_unsafe::iterator it{parent_hosts.begin()}, - end{parent_hosts.end()}; - it != end; it++) { - if (!it->second) + for (const auto& [key, sptr_host] : parent_hosts) { + if (!sptr_host) continue; - if (it->second->get_current_state() != host::state_up) { + if (sptr_host->get_current_state() != host::state_up) { engine_logger(dbg_checks, more) - << "Check of parent host '" << it->first << "' queued."; + << "Check of parent host '" << key << "' queued."; SPDLOG_LOGGER_DEBUG(checks_logger, - "Check of parent host '{}' queued.", it->first); - check_hostlist.push_back(it->second); + "Check of parent host '{}' queued.", key); + check_hostlist.push_back(sptr_host.get()); } } @@ -3280,24 +3290,21 @@ int host::process_check_result_3x(enum host::host_state new_state, "** WARNING: Max attempts = 1, so we have to run serial " "checks of all parent hosts!"); - for (host_map_unsafe::iterator it{parent_hosts.begin()}, - end{parent_hosts.end()}; - it != end; it++) { - if (!it->second) + for (const auto& [key, sptr_host] : parent_hosts) { + if (!sptr_host) continue; has_parent = true; engine_logger(dbg_checks, more) - << "Running serial check parent host '" << it->first << "'..."; - SPDLOG_LOGGER_DEBUG(checks_logger, - "Running serial check parent host '{}'...", - it->first); + << "Running serial check parent host '" << key << "'..."; + SPDLOG_LOGGER_DEBUG( + checks_logger, "Running serial check parent host '{}'...", key); /* run an immediate check of the parent host */ - it->second->run_sync_check_3x(&parent_state, check_options, - use_cached_result, - check_timestamp_horizon); + sptr_host->run_sync_check_3x(&parent_state, check_options, + use_cached_result, + check_timestamp_horizon); /* bail out as soon as we find one parent host that is UP */ if (parent_state == host::state_up) { @@ -3392,17 +3399,15 @@ int host::process_check_result_3x(enum host::host_state new_state, "Propagating checks to immediate parent hosts that " "are UP..."); - for (host_map_unsafe::iterator it{parent_hosts.begin()}, - end{parent_hosts.end()}; - it != end; it++) { - if (it->second == nullptr) + for (const auto& [key, sptr_host] : parent_hosts) { + if (sptr_host == nullptr) continue; - if (it->second->get_current_state() == host::state_up) { - check_hostlist.push_back(it->second); + if (sptr_host->get_current_state() == host::state_up) { + check_hostlist.push_back(sptr_host.get()); engine_logger(dbg_checks, more) - << "Check of host '" << it->first << "' queued."; + << "Check of host '" << key << "' queued."; SPDLOG_LOGGER_DEBUG(checks_logger, "Check of host '{}' queued.", - it->first); + key); } } @@ -3644,22 +3649,20 @@ enum host::host_state host::determine_host_reachability( /* check all parent hosts to see if we're DOWN or UNREACHABLE */ else { - for (host_map_unsafe::iterator it{parent_hosts.begin()}, - end{parent_hosts.end()}; - it != end; it++) { - if (!it->second) + for (const auto& [key, sptr_host] : parent_hosts) { + if (!sptr_host) continue; /* bail out as soon as we find one parent host that is UP */ - if (it->second->get_current_state() == host::state_up) { + if (sptr_host->get_current_state() == host::state_up) { is_host_present = true; /* set the current state */ state = host::state_down; - engine_logger(dbg_checks, most) << "At least one parent (" << it->first - << ") is up, so host is DOWN."; + engine_logger(dbg_checks, most) + << "At least one parent (" << key << ") is up, so host is DOWN."; SPDLOG_LOGGER_DEBUG(checks_logger, "At least one parent ({}) is up, so host is DOWN.", - it->first); + key); break; } } @@ -3984,22 +3987,20 @@ void host::resolve(int& w, int& e) { } /* check all parent parent host */ - for (host_map_unsafe::iterator it(parent_hosts.begin()), - end(parent_hosts.end()); - it != end; it++) { - host_map::const_iterator it_host{host::hosts.find(it->first)}; + for (auto& [key, sptr_host] : parent_hosts) { + host_map::const_iterator it_host{host::hosts.find(key)}; if (it_host == host::hosts.end() || !it_host->second) { - engine_logger(log_verification_error, basic) << "Error: '" << it->first + engine_logger(log_verification_error, basic) << "Error: '" << key << "' is not a " "valid parent for host '" << name() << "'!"; config_logger->error("Error: '{}' is not a valid parent for host '{}'!", - it->first, name()); + key, name()); errors++; } else { - it->second = it_host->second.get(); - it_host->second->add_child_host( - this); // add a reverse (child) link to make searches faster later on + sptr_host = it_host->second; + it_host->second->add_child_host(this); // add a reverse (child) link to + // make searches faster later on } } diff --git a/engine/src/macros/grab_host.cc b/engine/src/macros/grab_host.cc index c611278d665..22cf6899213 100644 --- a/engine/src/macros/grab_host.cc +++ b/engine/src/macros/grab_host.cc @@ -184,12 +184,10 @@ std::string get_host_total_services(host& hst, nagios_macros* mac) { static std::string get_host_parents(host& hst, nagios_macros* mac) { (void)mac; std::string retval; - for (host_map_unsafe::const_iterator it(hst.parent_hosts.begin()), - end(hst.parent_hosts.end()); - it != end; it++) { + for (const auto& [key, _] : hst.parent_hosts) { if (!retval.empty()) retval.append(","); - retval.append(it->first); + retval.append(key); } return retval; } @@ -205,12 +203,10 @@ static std::string get_host_parents(host& hst, nagios_macros* mac) { static std::string get_host_children(host& hst, nagios_macros* mac) { (void)mac; std::string retval; - for (host_map_unsafe::const_iterator it(hst.child_hosts.begin()), - end(hst.child_hosts.end()); - it != end; it++) { + for (const auto& [key, _] : hst.child_hosts) { if (!retval.empty()) retval.append(","); - retval.append(it->first); + retval.append(key); } return retval; } diff --git a/tests/broker-engine/parent_child_relation.robot b/tests/broker-engine/parent_child_relation.robot new file mode 100644 index 00000000000..2a123df2f5e --- /dev/null +++ b/tests/broker-engine/parent_child_relation.robot @@ -0,0 +1,262 @@ +*** Settings *** +Documentation Centreon Engine/Broker verify relation parent child host. + +Resource ../resources/import.resource + +Suite Setup Ctn Clean Before Suite +Suite Teardown Ctn Clean After Suite +Test Setup Ctn Stop Processes +Test Teardown Ctn Save Logs If Failed + + +*** Test Cases *** + +EBPN0 + [Documentation] Verify if child is in queue when parent is down. + [Tags] broker engine MON-151686 + + Ctn Config Engine ${1} ${5} ${1} + Ctn Config Broker rrd + Ctn Config Broker central + Ctn Config Broker module + Ctn Config BBDO3 1 + + Ctn Broker Config Log rrd rrd trace + Ctn Broker Config Log central sql debug + Ctn Broker Config Log rrd core error + Ctn Engine Config Set Value 0 log_level_checks debug + Ctn Config Broker Sql Output central unified_sql 10 + Ctn Broker Config Flush Log central 0 + Ctn Broker Config Flush Log rrd 0 + + Ctn Clear Retention + Ctn Clear Db resources + + # force the check result to 2 + Ctn Config Host Command Status ${0} checkh1 2 + + # host_1 is parent of host_2 + Ctn Add Parent To Host 0 host_2 host_1 + + ${start} Get Current Date + Ctn Start Broker + Ctn Start Engine + Ctn Wait For Engine To Be Ready ${start} ${1} + + # check if host_2 is child of host_1 + Connect To Database pymysql ${DBName} ${DBUser} ${DBPass} ${DBHost} ${DBPort} + + FOR ${index} IN RANGE 30 + ${output} Query + ... SELECT child_id, parent_id FROM hosts_hosts_parents + Log To Console ${output} + Sleep 1s + IF "${output}" == "((2, 1),)" BREAK + END + Should Be Equal As Strings ${output} ((2, 1),) host parent not inserted + + # check if host_1 is pending + ${result} Ctn Check Host Status host_1 4 1 True + Should Be True ${result} host_1 should be pending + + ${result} Ctn Check Host Status host_2 4 1 True + Should Be True ${result} host_2 should be pending + + ${content} Create List INITIAL HOST STATE: host_1; + ${result} Ctn Find In Log With Timeout ${engineLog0} ${start} ${content} 60 + Should Be True + ... ${result} + ... An Initial host state on host_1 should be raised before we can start our external commands. + + Ctn Process Host Check Result host_1 0 host_1 UP + + FOR ${i} IN RANGE ${4} + Ctn Schedule Forced Host Check host_1 ${VarRoot}/lib/centreon-engine/config0/rw/centengine.cmd + Sleep 1s + END + + ${content} Create List + ... EXTERNAL COMMAND: SCHEDULE_FORCED_HOST_CHECK;host_1; + ... HOST ALERT: host_1;DOWN;HARD; + + ${result} Ctn Find In Log With Timeout ${engineLog0} ${start} ${content} 60 + Should Be True ${result} Message about SCHEDULE HOST should be down in log. + + ${result} Ctn Check Host Status host_1 1 1 True + Should Be True ${result} host_1 should be down/hard + + ${content} Create List + ... Check of child host 'host_2' queued. + ${result} Ctn Find In Log With Timeout ${engineLog0} ${start} ${content} 60 + Should Be True ${result} Check of child host 'host_2' should be queued. + + Disconnect From Database + Ctn Stop Engine + Ctn Kindly Stop Broker + +EBPN1 + [Documentation] verify relation parent child when delete parent. + [Tags] broker engine MON-151686 + + Ctn Config Engine ${1} ${5} ${1} + Ctn Config Broker rrd + Ctn Config Broker central + Ctn Config Broker module + Ctn Config BBDO3 1 + + Ctn Broker Config Log rrd rrd error + Ctn Broker Config Log rrd core error + Ctn Broker Config Log module0 core error + + Ctn Broker Config Log central sql debug + Ctn Engine Config Set Value 0 log_level_checks error + Ctn Config Broker Sql Output central unified_sql 10 + Ctn Broker Config Flush Log central 0 + Ctn Broker Config Flush Log rrd 0 + + Ctn Clear Retention + + + # host_1 is parent of host_2 + Ctn Add Parent To Host 0 host_2 host_1 + + ${start} Get Current Date + Ctn Start Broker + Ctn Start Engine + Ctn Wait For Engine To Be Ready ${start} ${1} + + ${output} Ctn Get Host Info Grpc ${2} + Log To Console parents:${output}[parentHosts] + Should Contain ${output}[parentHosts] host_1 parentHosts + + ${output} Ctn Get Host Info Grpc ${1} + Log To Console childs:${output}[childHosts] + Should Contain ${output}[childHosts] host_2 childHosts + + Connect To Database pymysql ${DBName} ${DBUser} ${DBPass} ${DBHost} ${DBPort} + + FOR ${index} IN RANGE 30 + ${output} Query + ... SELECT child_id, parent_id FROM hosts_hosts_parents + Log To Console ${output} + Sleep 1s + IF "${output}" == "((2, 1),)" BREAK + END + Should Be Equal As Strings ${output} ((2, 1),) the parent link not inserted + + Ctn Engine Config Del Block In Cfg ${0} host host_1 hosts.cfg + Ctn Engine Config Del Block In Cfg ${0} service host_1 services.cfg + Ctn Engine Config Delete Value In Hosts ${0} host_2 parents + + ${start} Get Current Date + Ctn Reload Engine + Ctn Wait For Engine To Be Ready ${start} ${1} + ${content} Create List Reload configuration finished + ${result} Ctn Find In Log With Timeout + ... ${ENGINE_LOG}/config0/centengine.log + ... ${start} + ... ${content} + ... 60 + ... verbose=False + Should Be True ${result} Engine is Not Ready after 60s!! + + + ${output} Ctn Get Host Info Grpc ${2} + Log To Console parents:${output}[parentHosts] + Should Be Empty ${output}[parentHosts] + + FOR ${index} IN RANGE 30 + ${output} Query + ... SELECT child_id, parent_id FROM hosts_hosts_parents + Log To Console ${output} + Sleep 1s + IF "${output}" == "()" BREAK + END + Should Be Equal As Strings ${output} () the parent link should be deleted + + Disconnect From Database + Ctn Stop Engine + Ctn Kindly Stop Broker + +EBPN2 + [Documentation] verify relation parent child when delete child. + [Tags] broker engine MON-151686 + + Ctn Config Engine ${1} ${5} ${1} + Ctn Config Broker rrd + Ctn Config Broker central + Ctn Config Broker module + Ctn Config BBDO3 1 + + Ctn Broker Config Log rrd rrd error + Ctn Broker Config Log rrd core error + Ctn Broker Config Log module0 core error + + Ctn Broker Config Log central sql debug + Ctn Engine Config Set Value 0 log_level_checks error + Ctn Config Broker Sql Output central unified_sql 10 + Ctn Broker Config Flush Log central 0 + Ctn Broker Config Flush Log rrd 0 + + Ctn Clear Retention + + # host_1 is parent of host_2 + Ctn Add Parent To Host 0 host_2 host_1 + + ${start} Get Current Date + + Ctn Start Broker + Ctn Start Engine + Ctn Wait For Engine To Be Ready ${start} ${1} + + ${output} Ctn Get Host Info Grpc ${2} + Log To Console parents:${output}[parentHosts] + Should Contain ${output}[parentHosts] host_1 parentHosts + + ${output} Ctn Get Host Info Grpc ${1} + Log To Console childs:${output}[childHosts] + Should Contain ${output}[childHosts] host_2 childHosts + + Connect To Database pymysql ${DBName} ${DBUser} ${DBPass} ${DBHost} ${DBPort} + + FOR ${index} IN RANGE 30 + ${output} Query + ... SELECT child_id, parent_id FROM hosts_hosts_parents + Log To Console ${output} + Sleep 1s + IF "${output}" == "((2, 1),)" BREAK + END + Should Be Equal As Strings ${output} ((2, 1),) the parent link not inserted + + Ctn Engine Config Del Block In Cfg ${0} host host_2 hosts.cfg + Ctn Engine Config Del Block In Cfg ${0} service host_2 services.cfg + Ctn Engine Config Delete Value In Hosts ${0} host_2 parents + + ${start} Get Current Date + Ctn Reload Engine + Ctn Wait For Engine To Be Ready ${start} ${1} + ${content} Create List Reload configuration finished + ${result} Ctn Find In Log With Timeout + ... ${ENGINE_LOG}/config0/centengine.log + ... ${start} + ... ${content} + ... 60 + ... verbose=False + Should Be True ${result} Engine is Not Ready after 60s!! + + ${output} Ctn Get Host Info Grpc ${1} + Log To Console childs:${output}[childHosts] + Should Be Empty ${output}[childHosts] + + FOR ${index} IN RANGE 30 + ${output} Query + ... SELECT child_id, parent_id FROM hosts_hosts_parents + Log To Console ${output} + Sleep 1s + IF "${output}" == "()" BREAK + END + Should Be Equal As Strings ${output} () the parent link should be deleted + + Disconnect From Database + Ctn Stop Engine + Ctn Kindly Stop Broker \ No newline at end of file diff --git a/tests/resources/Engine.py b/tests/resources/Engine.py index 3df8fddf7db..2def5e7ec3c 100755 --- a/tests/resources/Engine.py +++ b/tests/resources/Engine.py @@ -32,6 +32,7 @@ from array import array from dateutil import parser import datetime +from google.protobuf.json_format import MessageToDict from os import makedirs, chmod from os.path import exists, dirname from robot.api import logger @@ -3648,3 +3649,102 @@ def ctn_send_otl_to_engine(port: int, resource_metrics: list): logger.console("gRPC server not ready") +def ctn_engine_config_del_block_in_cfg(idx: int, type: str, key: str, file): + """ + Delete a element in the file given for the Engine configuration idx. + + Args: + idx (int): Index of the Engine configuration (from 0) + type (str): The type (host/service/...). + key (str): The parameter that will be deleted. + file (str): The file to delete the key from. + """ + filename = f"{ETC_ROOT}/centreon-engine/config{idx}/{file}" + + with open(filename, "r") as f: + content = f.read() + + if type == "host": + pattern = rf"define host \{{\s*host_name\s+{re.escape(key)}\b.*?\}}" + elif type == "service": + pattern = rf"define service \{{\s*host_name\s+{re.escape(key)}\b.*?\}}" + + # Use re.sub to remove the matched block + new_content = re.sub(pattern, '', content, flags=re.DOTALL) + new_content = re.sub(r'\n\s*\n', '\n', new_content) + + if content != new_content: + with open(filename, "w") as f: + f.write(new_content) + else: + logger.console(f'\n\033[91mFailed : Cannot delete the block with the type : {type} and the key : {key} in {file}\033[0m') + +def ctn_get_host_info_grpc(id:int): + """ + Retrieve host information via a gRPC call. + + Args: + id: The identifier of the host to retrieve. + + Returns: + A dictionary containing the host informations, if successfully retrieved. + """ + if id is not None: + limit = time.time() + 30 + while time.time() < limit: + time.sleep(1) + with grpc.insecure_channel("127.0.0.1:50001") as channel: + stub = engine_pb2_grpc.EngineStub(channel) + request = engine_pb2.HostIdentifier(id=id) + try: + host = stub.GetHost(request) + host_dict = MessageToDict(host, always_print_fields_with_no_presence=True) + return host_dict + except Exception as e: + logger.console(f"gRPC server not ready {e}") + return {} + +def ctn_engine_config_delete_value_in_hosts(idx: int, desc: str, key: str, file: str = 'hosts.cfg'): + """ + Delete a parameter in the hosts.cfg for the Engine configuration idx. + + Args: + idx (int): Index of the Engine configuration (from 0) + desc (str): host name of the host to modify. + key (str): the parameter that will be deleted. + file (str): The file to modify, default value 'hosts.cfg' + """ + + + filename = f"{ETC_ROOT}/centreon-engine/config{idx}/{file}" + with open(filename, "r") as f: + lines = f.readlines() + + r = re.compile(r"^\s*host_name\s+" + desc + "\s*$") + rbis = re.compile(r"^\s*name\s+" + desc + "\s*$") + found = False + for i in range(len(lines)): + if r.match(lines[i]): + print("here" + lines[i]) + for j in range(i + 1, len(lines)): + if '}' in lines[j]: + break + if key in lines[j]: + del lines[j] + found = True + break + break + + if not found: + for i in range(len(lines)): + if rbis.match(lines[i]): + for j in range(i + 1, len(lines)): + if '}' in lines[j]: + break + if key in lines[j]: + del lines[j] + found = True + break + break + with open(filename, "w") as f: + f.writelines(lines) \ No newline at end of file