Files
qt5-legatus-legacy/Lts/Proxies/ComponentMonitor/checkmk_handler_schedule_check.cpp
T
2026-08-13 18:33:10 +02:00

264 lines
8.2 KiB
C++
Executable File

/**
* @RDE_HEADER@
* Handler for CheckmkHandlerScheduleCheck
* $Id$
* $HeadURL$
* $Author$
* Created by Norbert Thoden, 2022-11-30
*/
#include "checkmk_handler_schedule_check.h"
#include <QTimer>
#include <QHostAddress>
#include <QDateTime>
namespace ComponentMonitor
{
CheckmkHandlerScheduleCheck::CheckmkHandlerScheduleCheck(const std::shared_ptr<DdsHandler> &ddsHandler)
: QObject()
, TriggerUpdateRequestHandler(ddsHandler->fts())
, m_socket(new QTcpSocket(this))
, m_ddsHandler(ddsHandler)
, m_logger(getLogger("CheckmkHandlerScheduleCheck"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
CheckmkHandlerScheduleCheck::~CheckmkHandlerScheduleCheck()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (m_timer)
m_timer->stop();
delete m_socket;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool CheckmkHandlerScheduleCheck::initialize(const QString &checkMkServerHostname, int checkMkServerPort)
{
NOTICE_LOG(m_logger) << LOGFUNCTION << " START"
<< " , hostname=" << checkMkServerHostname
<< " , port=" << checkMkServerPort;
DEBUG_LOG(m_logger) << LOGFUNCTION << " ddsHandler referenced";
m_checkMkHost = checkMkServerHostname;
m_checkMkPort = checkMkServerPort;
if (!m_timer)
{
m_timer = new QTimer(this);
m_timer->setSingleShot(true);
connect(m_timer, &QTimer::timeout, this, &CheckmkHandlerScheduleCheck::onTimeout);
}
connect(m_socket, &QTcpSocket::stateChanged, this, &CheckmkHandlerScheduleCheck::onStateChanged);
connect(m_socket, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error),
this, &CheckmkHandlerScheduleCheck::onSocketError);
connect(m_socket, &QTcpSocket::connected,
this, &CheckmkHandlerScheduleCheck::onConnected);
INFO_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
void CheckmkHandlerScheduleCheck::run(int timoutMsec)
{
INFO_LOG(m_logger) << LOGFUNCTION << " START, timoutMsec=" << timoutMsec;
m_timer->start(timoutMsec);
INFO_LOG(m_logger) << LOGFUNCTION << " END";
}
void CheckmkHandlerScheduleCheck::stop()
{
INFO_LOG(m_logger) << LOGFUNCTION << " START";
m_timer->stop();
INFO_LOG(m_logger) << LOGFUNCTION << " END";
}
void CheckmkHandlerScheduleCheck::onTimeout()
{
if (m_socket->state() == QAbstractSocket::SocketState::ConnectedState)
{
writeScheduleUpdateRequest();
} else {
doConnect();
}
}
bool CheckmkHandlerScheduleCheck::doConnect()
{
INFO_LOG(m_logger) << LOGFUNCTION << " START, (int)m_socket->state()=" << (int)m_socket->state();
// (for 'COMMAND [%1] SCHEDULE_FORCED_HOST_CHECK...' the socket connection should not be closed)
// But maybe the CheckMk-Server ist restarted:
m_socket->connectToHost(m_checkMkHost, m_checkMkPort);
if (!m_socket->waitForConnected(5000))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " Could not (re)open tcp destination " << m_checkMkHost << ":" << m_checkMkPort << ", error: " << m_socket->errorString();
return false;
}
INFO_LOG(m_logger) << LOGFUNCTION << " (Re)openend tcp destination " << m_checkMkHost << ":" << m_checkMkPort;
INFO_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
void CheckmkHandlerScheduleCheck::addScheduleCheckHostnames(const QStringList &hostnames)
{
INFO_LOG(m_logger) << LOGFUNCTION << " hostnames: " << hostnames.join(QStringLiteral(";"));
m_scheduleCheckHostnames += hostnames;
}
bool CheckmkHandlerScheduleCheck::writeScheduleUpdateRequest()
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " state " << (int)m_socket->state()
<< ", isOpen " << m_socket->isOpen();
if (!m_socket->isOpen() || (m_socket->state() != QAbstractSocket::SocketState::ConnectedState))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " socket not open or connected "
<< " host/port: " << m_checkMkHost << ":" << m_checkMkPort;
return false;
}
if (m_scheduleCheckHostnames.isEmpty())
return false;
// avoid duplicates:
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
const QSet<QString> hosts = QSet<QString>::fromList(m_scheduleCheckHostnames);
#else
const QSet<QString> hosts(m_scheduleCheckHostnames.begin(), m_scheduleCheckHostnames.end());
#endif // QT_VERSION
int bWrittenAll = 0;
for (const QString &hostname : qAsConst(hosts))
{
qint64 now = QDateTime::currentSecsSinceEpoch();
// CheckMK is is configured with <HOSTNAME> -> toUpper()
const QString cmd = QString(QStringLiteral("COMMAND [%1] SCHEDULE_FORCED_HOST_CHECK;%2;%3")).arg(now).arg(hostname.toUpper()).arg(now);
DEBUG_LOG(m_logger) << LOGFUNCTION << " cmd= '" << cmd << "'";
int bWritten = m_socket->write(cmd.toUtf8()) + m_socket->write("\n\n");
DEBUG_LOG(m_logger) << LOGFUNCTION << " bWritten= " << bWritten;
bWrittenAll += bWritten;
} // for
INFO_LOG(m_logger) << LOGFUNCTION << " bWrittenAll= " << bWrittenAll;
// avoid scheduling more than once -> clear
m_scheduleCheckHostnames.clear();
//
// avoid hanging application, since slot (CheckmkHandler::onImmediateGetStateRequested
// most likely has to reconnect...
QTimer::singleShot(100, this, [this](){
emit newCheckScheduled();
});
return true;
}
void CheckmkHandlerScheduleCheck::onConnected()
{
writeScheduleUpdateRequest();
}
void CheckmkHandlerScheduleCheck::onStateChanged(const QAbstractSocket::SocketState &newState)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " SocketState changed to: " << newState;
qInfo() << " CheckmkHandlerScheduleCheck: SocketState changed to: " << newState;
}
void CheckmkHandlerScheduleCheck::onSocketError(const QAbstractSocket::SocketError &socketError)
{
qCritical() << "CheckmkHandlerScheduleCheck: Error occured: " << socketError;
}
void CheckmkHandlerScheduleCheck::onTriggerUpdateRequest(const rti::core::SampleIdentity &cookie, const TriggerUpdate &request)
{
INFO_LOG(m_logger) << LOGFUNCTION << " request=" << request;
DEBUG_LOG(m_logger) << LOGFUNCTION << " m_socket->state=" << (int)m_socket->state();
// if ((m_socket->state() != QAbstractSocket::SocketState::ConnectedState))
// {
// ERROR_LOG(m_logger) << LOGFUNCTION << " not connected";
// Core::FunctionReplyObject ret(0); // no request.id()
// ret.setId(-1);
// ret.setStr(tr_lts("dds", "No Connection to CheckMK"));
// if (m_ddsHandler && m_ddsHandler->fts())
// m_ddsHandler->fts()->triggerUpdateReply(cookie, ret);
// return;
// }
const std::vector< std::string >& hostnames = request.hostnames();
QStringList sl;
sl.reserve(hostnames.size());
QString temp;
for (const std::string &str : qAsConst(hostnames))
{
temp = QString::fromStdString(str);
if (!sl.contains(temp))
sl.push_back(temp);
} // for
// add to list
addScheduleCheckHostnames(sl);
// updateLastCheckTimeDirect :
// BEFORE writeScheduleUpdateRequest to avoid race condition!
const qint64 now = QDateTime::currentSecsSinceEpoch();
emit updateLastCheckTimeDirect(sl, now);
// : updateLastCheckTimeDirect
Core::FunctionReplyObject ret(0); // no request.id()
const bool connected = m_socket->state() == QAbstractSocket::SocketState::ConnectedState;
if (connected)
{
bool writeOk = writeScheduleUpdateRequest();
if (!writeOk)
{
ret.setId(-1);
ret.setStr(tr_lts("dds", "WriteError on CheckMk"));
}
} else {
// GUEZE-1653 MsgBox 'cmd queued due to lost connection to CheckMk' vermeiden
WARNING_LOG(m_logger) << LOGFUNCTION << " socket not connected"
<< ", (int)m_socket->state()=" << (int)m_socket->state()
<< ", destination " << m_checkMkHost << ":" << m_checkMkPort
<< ", -> queued cmd/request: " << request;
// ret.setId(-1);
// ret.setStr(tr_lts("dds", "cmd queued due to lost connection to CheckMk"));
}
INFO_LOG(m_logger) << LOGFUNCTION << " m_ddsHandler = " << m_ddsHandler;
INFO_LOG(m_logger) << LOGFUNCTION << " m_ddsHandler->fts() = " << m_ddsHandler->fts();
if (m_ddsHandler && m_ddsHandler->fts())
m_ddsHandler->fts()->triggerUpdateReply(cookie, ret);
else
ERROR_LOG(m_logger) << LOGFUNCTION << " no m_ddsHandler or m_ddsHandler->fts()";
if (!connected)
doConnect();
return;
}
} // namespace ComponentMonitor