diff --git a/include/com/centreon/engine/broker.hh b/include/com/centreon/engine/broker.hh index 2f627f716b8..e5d49f14ea8 100644 --- a/include/com/centreon/engine/broker.hh +++ b/include/com/centreon/engine/broker.hh @@ -316,8 +316,8 @@ void broker_acknowledgement_data(int type, int attr, int acknowledgement_type, void* data, - char* ack_author, - char* ack_data, + const char* ack_author, + const char* ack_data, int subtype, int notify_contacts, int persistent_comment, diff --git a/include/com/centreon/engine/engine_impl.hh b/include/com/centreon/engine/engine_impl.hh index 134e6abb54c..264481a0ce7 100644 --- a/include/com/centreon/engine/engine_impl.hh +++ b/include/com/centreon/engine/engine_impl.hh @@ -94,6 +94,12 @@ class engine_impl final : public Engine::Service { grpc::Status RemoveServiceAcknowledgement(grpc::ServerContext* context, const ServiceIdentifier* request, CommandSuccess* response) override; + grpc::Status AcknowledgementHostProblem(grpc::ServerContext* context, + const EngineAcknowledgement* request, + CommandSuccess* response) override; + grpc::Status AcknowledgementServiceProblem(grpc::ServerContext* context, + const EngineAcknowledgement* request, + CommandSuccess* response) override; grpc::Status ScheduleHostDowntime(grpc::ServerContext* context, const ScheduleDowntimeIdentifier* request, CommandSuccess* response) override; diff --git a/include/com/centreon/engine/nebstructs.hh b/include/com/centreon/engine/nebstructs.hh index 3c09190ece4..e81dc9fb9f7 100644 --- a/include/com/centreon/engine/nebstructs.hh +++ b/include/com/centreon/engine/nebstructs.hh @@ -35,8 +35,8 @@ typedef struct nebstruct_acknowledgement_struct { uint64_t host_id; uint64_t service_id; int state; - char* author_name; - char* comment_data; + const char* author_name; + const char* comment_data; int is_sticky; int persistent_comment; int notify_contacts; diff --git a/src/cce_core/broker.cc b/src/cce_core/broker.cc index 53f910d70d5..8fc24dcc415 100644 --- a/src/cce_core/broker.cc +++ b/src/cce_core/broker.cc @@ -53,8 +53,8 @@ void broker_acknowledgement_data(int type, int attr, int acknowledgement_type, void* data, - char* ack_author, - char* ack_data, + const char* ack_author, + const char* ack_data, int subtype, int notify_contacts, int persistent_comment, diff --git a/src/cce_rpc/engine.proto b/src/cce_rpc/engine.proto index b6a298b3a29..f661292ba2c 100644 --- a/src/cce_rpc/engine.proto +++ b/src/cce_rpc/engine.proto @@ -53,6 +53,10 @@ service Engine { rpc RemoveHostAcknowledgement(HostIdentifier) returns (CommandSuccess) {} rpc RemoveServiceAcknowledgement(ServiceIdentifier) returns (CommandSuccess) {} + rpc AcknowledgementHostProblem(EngineAcknowledgement) + returns (CommandSuccess) {} + rpc AcknowledgementServiceProblem(EngineAcknowledgement) + returns (CommandSuccess) {} rpc DeleteHostDowntime(GenericValue) returns (CommandSuccess) {} rpc DeleteServiceDowntime(GenericValue) returns (CommandSuccess) {} rpc DeleteHostDowntimeFull(DowntimeCriterias) returns (CommandSuccess) {} @@ -437,3 +441,17 @@ message EngineSignalProcess { Process process = 1; uint32 scheduled_time = 2; } + +message EngineAcknowledgement { + string host_name = 1; + string service_desc = 2; + string ack_author = 3; + string ack_data = 4; + enum Type { + NORMAL = 0; + STICKY = 1; + } + Type type = 5; + bool notify = 6; + bool persistent = 7; +} diff --git a/src/centengine/engine_impl.cc b/src/centengine/engine_impl.cc index 3a02534b098..e763fe380a5 100644 --- a/src/centengine/engine_impl.cc +++ b/src/centengine/engine_impl.cc @@ -16,7 +16,6 @@ * For more information : contact@centreon.com * */ - #include "com/centreon/engine/engine_impl.hh" #include @@ -27,6 +26,7 @@ #include #include "com/centreon/engine/anomalydetection.hh" +#include "com/centreon/engine/broker.hh" #include "com/centreon/engine/command_manager.hh" #include "com/centreon/engine/comment.hh" #include "com/centreon/engine/common.hh" @@ -133,7 +133,7 @@ grpc::Status engine_impl::GetHost(grpc::ServerContext* context host->set_address(selectedhost->get_address()); host->set_check_period(selectedhost->get_check_period()); host->set_current_state( - static_cast(selectedhost->get_current_state())); + static_cast(selectedhost->get_current_state())); host->set_id(selectedhost->get_host_id()); return 0; }); @@ -792,6 +792,119 @@ grpc::Status engine_impl::RemoveServiceAcknowledgement( return grpc::Status::OK; } +grpc::Status engine_impl::AcknowledgementHostProblem( + grpc::ServerContext* context __attribute__((unused)), + const EngineAcknowledgement* request, + CommandSuccess* response) { + auto fn = std::packaged_task([request]() -> int32_t { + std::shared_ptr temp_host; + /* get the host */ + auto it = host::hosts.find(request->host_name()); + if (it != host::hosts.end()) + temp_host = it->second; + if (temp_host == nullptr) + return 1; + /* cannot acknowledge a non-existent problem */ + if (temp_host->get_current_state() == host::state_up) + return 1; + /* set the acknowledgement flag */ + temp_host->set_problem_has_been_acknowledged(true); + /* set the acknowledgement type */ + if (EngineAcknowledgement::Type_Name(request->type()) == "STICKY") + temp_host->set_acknowledgement_type(ACKNOWLEDGEMENT_STICKY); + else + temp_host->set_acknowledgement_type(ACKNOWLEDGEMENT_NORMAL); + /* schedule acknowledgement expiration */ + time_t current_time(time(nullptr)); + temp_host->set_last_acknowledgement(current_time); + temp_host->schedule_acknowledgement_expiration(); + /* send data to event broker */ + broker_acknowledgement_data( + NEBTYPE_ACKNOWLEDGEMENT_ADD, NEBFLAG_NONE, NEBATTR_NONE, + HOST_ACKNOWLEDGEMENT, static_cast(temp_host.get()), + request->ack_author().c_str(), request->ack_data().c_str(), + request->type(), request->notify(), request->persistent(), nullptr); + /* send out an acknowledgement notification */ + if (request->notify()) + temp_host->notify(notifier::reason_acknowledgement, request->ack_author(), + request->ack_data(), + notifier::notification_option_none); + /* update the status log with the host info */ + temp_host->update_status(false); + /* add a comment for the acknowledgement */ + auto com = std::make_shared( + comment::host, comment::acknowledgment, temp_host->get_host_id(), 0, + current_time, request->ack_author(), request->ack_data(), + request->persistent(), comment::internal, false, (time_t)0); + comment::comments.insert({com->get_comment_id(), com}); + + return 0; + }); + + std::future result = fn.get_future(); + command_manager::instance().enqueue(std::move(fn)); + + response->set_value(!result.get()); + return grpc::Status::OK; +} + +grpc::Status engine_impl::AcknowledgementServiceProblem( + grpc::ServerContext* context __attribute__((unused)), + const EngineAcknowledgement* request, + CommandSuccess* response) { + auto fn = std::packaged_task([request]() -> int32_t { + std::shared_ptr temp_service; + auto it = + service::services.find({request->host_name(), request->service_desc()}); + if (it != service::services.end()) + temp_service = it->second; + if (temp_service == nullptr) + return 1; + /* cannot acknowledge a non-existent problem */ + if (temp_service->get_current_state() == service::state_ok) + return 1; + /* set the acknowledgement flag */ + temp_service->set_problem_has_been_acknowledged(true); + /* set the acknowledgement type */ + if (EngineAcknowledgement::Type_Name(request->type()) == "STICKY") + temp_service->set_acknowledgement_type(ACKNOWLEDGEMENT_STICKY); + else + temp_service->set_acknowledgement_type(ACKNOWLEDGEMENT_NORMAL); + /* schedule acknowledgement expiration */ + time_t current_time(time(nullptr)); + temp_service->set_last_acknowledgement(current_time); + temp_service->schedule_acknowledgement_expiration(); + /* send data to event broker */ + broker_acknowledgement_data( + NEBTYPE_ACKNOWLEDGEMENT_ADD, NEBFLAG_NONE, NEBATTR_NONE, + SERVICE_ACKNOWLEDGEMENT, static_cast(temp_service.get()), + request->ack_author().c_str(), request->ack_data().c_str(), + request->type(), request->notify(), request->persistent(), nullptr); + /* send out an acknowledgement notification */ + if (request->notify()) + temp_service->notify(notifier::reason_acknowledgement, + request->ack_author(), request->ack_data(), + notifier::notification_option_none); + /* update the status log with the service info */ + temp_service->update_status(false); + + /* add a comment for the acknowledgement */ + auto com = std::make_shared( + comment::service, comment::acknowledgment, temp_service->get_host_id(), + temp_service->get_service_id(), current_time, request->ack_author(), + request->ack_data(), request->persistent(), comment::internal, false, + (time_t)0); + comment::comments.insert({com->get_comment_id(), com}); + return 0; + }); + + std::future result = fn.get_future(); + command_manager::instance().enqueue(std::move(fn)); + + response->set_value(!result.get()); + return grpc::Status::OK; +} + /** * @brief Schedules downtime for a specific host. * diff --git a/tests/engine/enginerpc/client.cc b/tests/engine/enginerpc/client.cc index 694bca5efac..a0fda10ec2c 100644 --- a/tests/engine/enginerpc/client.cc +++ b/tests/engine/enginerpc/client.cc @@ -445,6 +445,60 @@ class EngineRPCClient { return true; } + bool AcknowledgementHostProblem(std::string const& hostname, + std::string const& ackauthor, + std::string const& ackdata, + int type, + bool notify, + bool persistent, + CommandSuccess* response) { + EngineAcknowledgement request; + grpc::ClientContext context; + request.set_host_name(hostname); + request.set_ack_author(ackauthor); + request.set_ack_data(ackdata); + request.set_type(static_cast(type)); + request.set_notify(notify); + request.set_persistent(persistent); + + grpc::Status status = + _stub->AcknowledgementHostProblem(&context, request, response); + if (!status.ok()) { + std::cout << "AcknowledgementHostProblem rpc engine failed" + << std::endl; + return false; + } + return true; + } + + bool AcknowledgementServiceProblem(std::string const& hostname, + std::string const& servicedesc, + std::string const& ackauthor, + std::string const& ackdata, + int type, + bool notify, + bool persistent, + CommandSuccess* response) { + EngineAcknowledgement request; + grpc::ClientContext context; + request.set_host_name(hostname); + request.set_service_desc(servicedesc); + request.set_ack_author(ackauthor); + request.set_ack_data(ackdata); + request.set_type(static_cast(type)); + request.set_notify(notify); + request.set_persistent(persistent); + + grpc::Status status = + _stub->AcknowledgementServiceProblem(&context, request, response); + if (!status.ok()) { + std::cout << "AcknowledgementServiceProblem rpc engine failed" + << std::endl; + return false; + } + return true; + } + bool ScheduleHostDowntime(std::string const& hostname, std::string const& hostgroupname, std::string const& servicegroupname, @@ -1733,9 +1787,36 @@ int main(int argc, char** argv) { status = client.SignalProcess(process, scheduledtime, &response); std::cout << "SignalProcess" << std::endl; + } else if (strcmp(argv[1], "AcknowledgementHostProblem") == 0) { + CommandSuccess response; + std::string hostname(argv[2]); + std::string ackauthor(argv[3]); + std::string ackdata(argv[4]); + int type = atoi(argv[5]); + bool notify = atoi(argv[6]); + bool persistent = atoi(argv[7]); + + status = client.AcknowledgementHostProblem(hostname, ackauthor, + ackdata, type, notify, persistent, &response); + std::cout << "AcknowledgementHostProblem" << std::endl; + } else if (strcmp(argv[1], "AcknowledgementServiceProblem") == 0) { + CommandSuccess response; + std::string hostname(argv[2]); + std::string servicedesc(argv[3]); + std::string ackauthor(argv[4]); + std::string ackdata(argv[5]); + int type = atoi(argv[6]); + bool notify = atoi(argv[7]); + bool persistent = atoi(argv[8]); + + status = client.AcknowledgementServiceProblem(hostname, servicedesc, ackauthor, + ackdata, type, notify, persistent, &response); + std::cout << "AcknowledgementServiceProblem" << std::endl; } - else + else { std::cout << "unknown command" << std::endl; + status = EXIT_FAILURE; + } exit(status); } diff --git a/tests/engine/enginerpc/enginerpc.cc b/tests/engine/enginerpc/enginerpc.cc index fa9b3693710..bbfa399c195 100644 --- a/tests/engine/enginerpc/enginerpc.cc +++ b/tests/engine/enginerpc/enginerpc.cc @@ -131,7 +131,7 @@ class EngineRpc : public TestEngine { host_map const& hm{engine::host::hosts}; _host = hm.begin()->second; - _host->set_current_state(engine::host::state_up); + _host->set_current_state(engine::host::state_down); _host->set_state_type(checkable::hard); _host->set_problem_has_been_acknowledged(false); _host->set_notify_on(static_cast(-1)); @@ -144,6 +144,10 @@ class EngineRpc : public TestEngine { else _svc = svc; } + _svc->set_current_state(engine::service::state_critical); + _svc->set_state_type(checkable::hard); + _svc->set_problem_has_been_acknowledged(false); + _svc->set_notify_on(static_cast(-1)); contact_map const& cm{engine::contact::contacts}; _contact = cm.begin()->second; @@ -770,6 +774,52 @@ TEST_F(EngineRpc, RemoveServiceAcknowledgement) { erpc.shutdown(); } +TEST_F(EngineRpc, AcknowledgementHostProblem) { + enginerpc erpc("0.0.0.0", 40001); + std::unique_ptr th; + std::condition_variable condvar; + std::mutex mutex; + bool continuerunning = false; + + ASSERT_EQ(_host->get_problem_has_been_acknowledged(), false); + call_command_manager(th, &condvar, &mutex, &continuerunning); + + auto output = execute("AcknowledgementHostProblem test_host admin test 1 0 0"); + { + std::lock_guard lock(mutex); + continuerunning = true; + } + condvar.notify_one(); + th->join(); + + ASSERT_EQ(_host->get_problem_has_been_acknowledged(), true); + erpc.shutdown(); +} + +TEST_F(EngineRpc, AcknowledgementServiceProblem) { + enginerpc erpc("0.0.0.0", 40001); + std::unique_ptr th; + std::condition_variable condvar; + std::mutex mutex; + bool continuerunning = false; + + ASSERT_EQ(_svc->get_problem_has_been_acknowledged(), false); + call_command_manager(th, &condvar, &mutex, &continuerunning); + + auto output = execute("AcknowledgementServiceProblem test_host test_svc admin test 1 0 0"); +; + { + std::lock_guard lock(mutex); + continuerunning = true; + } + condvar.notify_one(); + th->join(); + + ASSERT_EQ(_svc->get_problem_has_been_acknowledged(), true); + erpc.shutdown(); +} + + TEST_F(EngineRpc, ScheduleHostDowntime) { enginerpc erpc("0.0.0.0", 40001); std::unique_ptr th;