2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-30 21:45:37 +00:00

[#3278] Added configurable PerfMonMgr singleton

load() now creates PerfMonMgr singleton and invokes it's configure() function.

src/hooks/dhcp/perfmon/monitored_duration.*
    DurationKey::getMessageTypeLabel(uint16_t family, uint16_t msg_type)  - new function
    Translates DHCP_NOTYPE/DHCPV6_NOTYPE to "*"

src/hooks/dhcp/perfmon/perfmon_callouts.cc
    Added PerfMonMgr singleton
    int load(LibraryHandle& handle)  - creates singleton and parses configuration

src/hooks/dhcp/perfmon/perfmon_config.cc
 DurationKeyParser::getMessageNameType4(const std::string& name)
 DurationKeyParser::getMessageNameType6(const std::string& name) - map "*" to NOTYPE
     static std::map<std::string, uint16_t> name_type_map = {

src/hooks/dhcp/perfmon/tests/duration_key_parser_unittests.cc
    TEST_F(DurationKeyParserTest, validScenarios4) - verify "*" message type parses

src/hooks/dhcp/perfmon/libloadtests/load_unload_unittests.cc
    Updated to pass in a valid configuration on load test.
This commit is contained in:
Thomas Markwalder
2024-03-20 10:47:42 -04:00
parent dae3cb04ec
commit e7c5bbb5e2
8 changed files with 143 additions and 28 deletions

View File

@@ -42,16 +42,42 @@ public:
virtual ~PerfMonLibLoadTest() {
unloadLibraries();
}
/// @brief Creates a valid set configuration parameters valid for the library.
virtual isc::data::ElementPtr validConfigParams() {
std::string valid_config =
R"({
"enable-monitoring" : true,
"interval-width-secs" : 5,
"stats-mgr-reporting" : true,
"alarm-report-secs" : 600,
"alarms": [{
"duration-key": {
"query-type" : "*",
"response-type" : "*",
"start-event" : "socket-received",
"stop-event" : "buffer-read",
"subnet-id" : 70
},
"enable-alarm" : true,
"high-water-ms" : 500,
"low-water-ms" : 25
}]
})";
// Convert JSON texts to Element map.
return (Element::fromJSON(valid_config));
}
};
// Simple V4 test that checks the library can be loaded and unloaded several times.
TEST_F(PerfMonLibLoadTest, validLoad4) {
validDaemonTest("kea-dhcp4");
validDaemonTest("kea-dhcp4", AF_INET, valid_params_);
}
// Simple V6 test that checks the library can be loaded and unloaded several times.
TEST_F(PerfMonLibLoadTest, validLoad6) {
validDaemonTest("kea-dhcp6", AF_INET6);
validDaemonTest("kea-dhcp6", AF_INET6, valid_params_);
}
// Simple test that checks the library cannot by loaded by invalid daemons.

View File

@@ -157,17 +157,21 @@ DurationKey::validateMessagePair(uint16_t family, uint8_t query_type, uint8_t re
}
std::string
DurationKey::getLabel() const {
std::ostringstream oss;
if (family_ == AF_INET) {
oss << (query_type_ == DHCP_NOTYPE ? "NONE" : Pkt4::getName(query_type_)) << "-"
<< (response_type_ == DHCP_NOTYPE ? "NONE" : Pkt4::getName(response_type_));
} else {
oss << (query_type_ == DHCPV6_NOTYPE ? "NONE" : Pkt6::getName(query_type_)) << "-"
<< (response_type_ == DHCPV6_NOTYPE ? "NONE" : Pkt6::getName(response_type_));
DurationKey::getMessageTypeLabel(uint16_t family, uint16_t msg_type) {
if (family == AF_INET) {
return (msg_type == DHCP_NOTYPE ? "*" : Pkt4::getName(msg_type));
}
oss << "." << start_event_label_ << "-" << stop_event_label_
return (msg_type == DHCPV6_NOTYPE ? "*" : Pkt6::getName(msg_type));
}
std::string
DurationKey::getLabel() const {
std::ostringstream oss;
oss << getMessageTypeLabel(family_, query_type_)
<< "-"
<< getMessageTypeLabel(family_, response_type_)
<< "." << start_event_label_ << "-" << stop_event_label_
<< "." << subnet_id_;
return (oss.str());

View File

@@ -188,6 +188,15 @@ public:
return (subnet_id_);
}
/// @brief Get a label for a family-specific message type (e.g.
/// "DHCPDISCOVER", "SOLICIT")
///
/// @param family Protocol family of the key (AF_INET or AF_INET6)
/// @param msg_type numeric message type to translate
///
/// @return Text label, for values of DHCP_NOTYPE or DHCPV6_NOTYPE: "*"
static std::string getMessageTypeLabel(uint16_t family, uint16_t msg_type);
/// @brief Get a composite label of the member values with text message types.
///
/// The format of the string:
@@ -201,7 +210,7 @@ public:
///
/// or
///
/// "DHCPV6_SOLICIT-DHCPV6_ADVERTISE.socket_received.buffer_read.12"
/// "SOLICIT-ADVERTISE.socket_received.buffer_read.12"
///
/// @endcode
///

View File

@@ -11,11 +11,22 @@
#include <config.h>
#include <perfmon_log.h>
#include <perfmon_mgr.h>
#include <cc/command_interpreter.h>
#include <dhcpsrv/cfgmgr.h>
#include <hooks/hooks.h>
#include <process/daemon.h>
namespace isc {
namespace perfmon {
/// @brief PerfMonMgr singleton
PerfMonMgrPtr mgr;
} // end of namespace perfmon
}
using namespace isc::data;
using namespace isc::dhcp;
using namespace isc::hooks;
using namespace isc::log;
@@ -88,24 +99,34 @@ int pkt6_send(CalloutHandle& handle) {
///
/// @param handle library handle
/// @return 0 when initialization is successful, 1 otherwise
int load(LibraryHandle& /* handle */) {
// Make the hook library not loadable by d2 or ca.
uint16_t family = CfgMgr::instance().getFamily();
const std::string& proc_name = Daemon::getProcName();
if (family == AF_INET) {
if (proc_name != "kea-dhcp4") {
isc_throw(isc::Unexpected, "Bad process name: " << proc_name
<< ", expected kea-dhcp4");
}
} else {
if (proc_name != "kea-dhcp6") {
int load(LibraryHandle& handle) {
try {
// Make the hook library only loadable for kea-dhcpX.
uint16_t family = CfgMgr::instance().getFamily();
const std::string& proc_name = Daemon::getProcName();
if (family == AF_INET) {
if (proc_name != "kea-dhcp4") {
isc_throw(isc::Unexpected, "Bad process name: " << proc_name
<< ", expected kea-dhcp4");
}
} else if (proc_name != "kea-dhcp6") {
isc_throw(isc::Unexpected, "Bad process name: " << proc_name
<< ", expected kea-dhcp6");
}
}
/// @todo register commands
/// handle.registerCommandCallout("command-here", handler_here);
// Instantiate the manager singleton.
mgr.reset(new PerfMonMgr(family));
// Configure the manager using the hook library's parameters.
ConstElementPtr json = handle.getParameters();
mgr->configure(json);
/// @todo register commands
/// handle.registerCommandCallout("command-here", handler_here);
} catch (const std::exception& ex) {
LOG_ERROR(perfmon_logger, PERFMON_INIT_FAILED).arg(ex.what());
return (1);
}
LOG_INFO(perfmon_logger, PERFMON_INIT_OK);
return (0);

View File

@@ -33,6 +33,7 @@ uint16_t
DurationKeyParser::getMessageNameType4(const std::string& name) {
static std::map<std::string, uint16_t> name_type_map = {
{"", DHCP_NOTYPE},
{"*", DHCP_NOTYPE},
{"DHCPDISCOVER", DHCPDISCOVER},
{"DHCPOFFER", DHCPOFFER},
{"DHCPREQUEST", DHCPREQUEST},
@@ -63,6 +64,7 @@ uint16_t
DurationKeyParser::getMessageNameType6(const std::string& name) {
static std::map<std::string, uint16_t> name_type_map = {
{"", DHCPV6_NOTYPE},
{"*", DHCPV6_NOTYPE},
{"SOLICIT", DHCPV6_SOLICIT},
{"ADVERTISE", DHCPV6_ADVERTISE},
{"REQUEST", DHCPV6_REQUEST},

View File

@@ -37,7 +37,7 @@ namespace perfmon {
/// },
/// "enable-alarm" : true,
/// "high-water-ms" : 500,
/// "low-water-ms" : 25,
/// "low-water-ms" : 25
/// },
/// ..
/// }]

View File

@@ -165,6 +165,32 @@ TEST_F(DurationKeyParserTest, validScenarios4) {
})",
DHCPDISCOVER, DHCPOFFER, "start_here", "stop_there", SUBNET_ID_GLOBAL
},
{
// Empty message types should map to DHCP_NOTYPE
__LINE__,
R"(
{
"query-type": "",
"response-type": "",
"start-event": "start_here",
"stop-event": "stop_there",
"subnet-id": 701
})",
DHCP_NOTYPE, DHCP_NOTYPE, "start_here", "stop_there", 701
},
{
// "*" message types should map to DHCP_NOTYPE
__LINE__,
R"(
{
"query-type": "*",
"response-type": "*",
"start-event": "start_here",
"stop-event": "stop_there",
"subnet-id": 701
})",
DHCP_NOTYPE, DHCP_NOTYPE, "start_here", "stop_there", 701
},
};
testValidScenarios(scenarios, AF_INET);
@@ -386,6 +412,32 @@ TEST_F(DurationKeyParserTest, parseValidScenarios6) {
})",
DHCPV6_SOLICIT, DHCPV6_ADVERTISE, "start_here", "stop_there", SUBNET_ID_GLOBAL
},
{
// Empty message types should map to DHCPV6_NOTYPE
__LINE__,
R"(
{
"query-type": "",
"response-type": "",
"start-event": "start_here",
"stop-event": "stop_there",
"subnet-id": 701
})",
DHCPV6_NOTYPE, DHCPV6_NOTYPE, "start_here", "stop_there", 701
},
{
// "*" message types should map to DHCPV6_NOTYPE
__LINE__,
R"(
{
"query-type": "*",
"response-type": "*",
"start-event": "start_here",
"stop-event": "stop_there",
"subnet-id": 701
})",
DHCPV6_NOTYPE, DHCPV6_NOTYPE, "start_here", "stop_there", 701
},
};
testValidScenarios(scenarios, AF_INET6);

View File

@@ -117,7 +117,8 @@ public:
EXPECT_EQ(mgr->getAlarmStore()->getFamily(), family_);
AlarmCollectionPtr alarms = mgr->getAlarmStore()->getAll();
ASSERT_EQ(alarms->size(), 1);
DurationKeyPtr key(new DurationKey(family_, 0, 0, "process-started", "process-completed", 70));
DurationKeyPtr key(new DurationKey(family_, 0, 0, "process-started",
"process-completed", 70));
AlarmPtr alarm = (*alarms)[0];
ASSERT_TRUE(alarm);
EXPECT_EQ(*alarm, *key) << "alarm:" << alarm->getLabel();