mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-09-03 23:45:27 +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:
@@ -42,16 +42,42 @@ public:
|
|||||||
virtual ~PerfMonLibLoadTest() {
|
virtual ~PerfMonLibLoadTest() {
|
||||||
unloadLibraries();
|
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.
|
// Simple V4 test that checks the library can be loaded and unloaded several times.
|
||||||
TEST_F(PerfMonLibLoadTest, validLoad4) {
|
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.
|
// Simple V6 test that checks the library can be loaded and unloaded several times.
|
||||||
TEST_F(PerfMonLibLoadTest, validLoad6) {
|
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.
|
// Simple test that checks the library cannot by loaded by invalid daemons.
|
||||||
|
|||||||
@@ -157,17 +157,21 @@ DurationKey::validateMessagePair(uint16_t family, uint8_t query_type, uint8_t re
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
DurationKey::getLabel() const {
|
DurationKey::getMessageTypeLabel(uint16_t family, uint16_t msg_type) {
|
||||||
std::ostringstream oss;
|
if (family == AF_INET) {
|
||||||
if (family_ == AF_INET) {
|
return (msg_type == DHCP_NOTYPE ? "*" : Pkt4::getName(msg_type));
|
||||||
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_));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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_;
|
<< "." << subnet_id_;
|
||||||
|
|
||||||
return (oss.str());
|
return (oss.str());
|
||||||
|
|||||||
@@ -188,6 +188,15 @@ public:
|
|||||||
return (subnet_id_);
|
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.
|
/// @brief Get a composite label of the member values with text message types.
|
||||||
///
|
///
|
||||||
/// The format of the string:
|
/// The format of the string:
|
||||||
@@ -201,7 +210,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// or
|
/// or
|
||||||
///
|
///
|
||||||
/// "DHCPV6_SOLICIT-DHCPV6_ADVERTISE.socket_received.buffer_read.12"
|
/// "SOLICIT-ADVERTISE.socket_received.buffer_read.12"
|
||||||
///
|
///
|
||||||
/// @endcode
|
/// @endcode
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -11,11 +11,22 @@
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
#include <perfmon_log.h>
|
#include <perfmon_log.h>
|
||||||
|
#include <perfmon_mgr.h>
|
||||||
#include <cc/command_interpreter.h>
|
#include <cc/command_interpreter.h>
|
||||||
#include <dhcpsrv/cfgmgr.h>
|
#include <dhcpsrv/cfgmgr.h>
|
||||||
#include <hooks/hooks.h>
|
#include <hooks/hooks.h>
|
||||||
#include <process/daemon.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::dhcp;
|
||||||
using namespace isc::hooks;
|
using namespace isc::hooks;
|
||||||
using namespace isc::log;
|
using namespace isc::log;
|
||||||
@@ -88,24 +99,34 @@ int pkt6_send(CalloutHandle& handle) {
|
|||||||
///
|
///
|
||||||
/// @param handle library handle
|
/// @param handle library handle
|
||||||
/// @return 0 when initialization is successful, 1 otherwise
|
/// @return 0 when initialization is successful, 1 otherwise
|
||||||
int load(LibraryHandle& /* handle */) {
|
int load(LibraryHandle& handle) {
|
||||||
// Make the hook library not loadable by d2 or ca.
|
try {
|
||||||
uint16_t family = CfgMgr::instance().getFamily();
|
// Make the hook library only loadable for kea-dhcpX.
|
||||||
const std::string& proc_name = Daemon::getProcName();
|
uint16_t family = CfgMgr::instance().getFamily();
|
||||||
if (family == AF_INET) {
|
const std::string& proc_name = Daemon::getProcName();
|
||||||
if (proc_name != "kea-dhcp4") {
|
if (family == AF_INET) {
|
||||||
isc_throw(isc::Unexpected, "Bad process name: " << proc_name
|
if (proc_name != "kea-dhcp4") {
|
||||||
<< ", expected kea-dhcp4");
|
isc_throw(isc::Unexpected, "Bad process name: " << proc_name
|
||||||
}
|
<< ", expected kea-dhcp4");
|
||||||
} else {
|
}
|
||||||
if (proc_name != "kea-dhcp6") {
|
} else if (proc_name != "kea-dhcp6") {
|
||||||
isc_throw(isc::Unexpected, "Bad process name: " << proc_name
|
isc_throw(isc::Unexpected, "Bad process name: " << proc_name
|
||||||
<< ", expected kea-dhcp6");
|
<< ", expected kea-dhcp6");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// @todo register commands
|
// Instantiate the manager singleton.
|
||||||
/// handle.registerCommandCallout("command-here", handler_here);
|
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);
|
LOG_INFO(perfmon_logger, PERFMON_INIT_OK);
|
||||||
return (0);
|
return (0);
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ uint16_t
|
|||||||
DurationKeyParser::getMessageNameType4(const std::string& name) {
|
DurationKeyParser::getMessageNameType4(const std::string& name) {
|
||||||
static std::map<std::string, uint16_t> name_type_map = {
|
static std::map<std::string, uint16_t> name_type_map = {
|
||||||
{"", DHCP_NOTYPE},
|
{"", DHCP_NOTYPE},
|
||||||
|
{"*", DHCP_NOTYPE},
|
||||||
{"DHCPDISCOVER", DHCPDISCOVER},
|
{"DHCPDISCOVER", DHCPDISCOVER},
|
||||||
{"DHCPOFFER", DHCPOFFER},
|
{"DHCPOFFER", DHCPOFFER},
|
||||||
{"DHCPREQUEST", DHCPREQUEST},
|
{"DHCPREQUEST", DHCPREQUEST},
|
||||||
@@ -63,6 +64,7 @@ uint16_t
|
|||||||
DurationKeyParser::getMessageNameType6(const std::string& name) {
|
DurationKeyParser::getMessageNameType6(const std::string& name) {
|
||||||
static std::map<std::string, uint16_t> name_type_map = {
|
static std::map<std::string, uint16_t> name_type_map = {
|
||||||
{"", DHCPV6_NOTYPE},
|
{"", DHCPV6_NOTYPE},
|
||||||
|
{"*", DHCPV6_NOTYPE},
|
||||||
{"SOLICIT", DHCPV6_SOLICIT},
|
{"SOLICIT", DHCPV6_SOLICIT},
|
||||||
{"ADVERTISE", DHCPV6_ADVERTISE},
|
{"ADVERTISE", DHCPV6_ADVERTISE},
|
||||||
{"REQUEST", DHCPV6_REQUEST},
|
{"REQUEST", DHCPV6_REQUEST},
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace perfmon {
|
|||||||
/// },
|
/// },
|
||||||
/// "enable-alarm" : true,
|
/// "enable-alarm" : true,
|
||||||
/// "high-water-ms" : 500,
|
/// "high-water-ms" : 500,
|
||||||
/// "low-water-ms" : 25,
|
/// "low-water-ms" : 25
|
||||||
/// },
|
/// },
|
||||||
/// ..
|
/// ..
|
||||||
/// }]
|
/// }]
|
||||||
|
|||||||
@@ -165,6 +165,32 @@ TEST_F(DurationKeyParserTest, validScenarios4) {
|
|||||||
})",
|
})",
|
||||||
DHCPDISCOVER, DHCPOFFER, "start_here", "stop_there", SUBNET_ID_GLOBAL
|
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);
|
testValidScenarios(scenarios, AF_INET);
|
||||||
@@ -386,6 +412,32 @@ TEST_F(DurationKeyParserTest, parseValidScenarios6) {
|
|||||||
})",
|
})",
|
||||||
DHCPV6_SOLICIT, DHCPV6_ADVERTISE, "start_here", "stop_there", SUBNET_ID_GLOBAL
|
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);
|
testValidScenarios(scenarios, AF_INET6);
|
||||||
|
|||||||
@@ -117,7 +117,8 @@ public:
|
|||||||
EXPECT_EQ(mgr->getAlarmStore()->getFamily(), family_);
|
EXPECT_EQ(mgr->getAlarmStore()->getFamily(), family_);
|
||||||
AlarmCollectionPtr alarms = mgr->getAlarmStore()->getAll();
|
AlarmCollectionPtr alarms = mgr->getAlarmStore()->getAll();
|
||||||
ASSERT_EQ(alarms->size(), 1);
|
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];
|
AlarmPtr alarm = (*alarms)[0];
|
||||||
ASSERT_TRUE(alarm);
|
ASSERT_TRUE(alarm);
|
||||||
EXPECT_EQ(*alarm, *key) << "alarm:" << alarm->getLabel();
|
EXPECT_EQ(*alarm, *key) << "alarm:" << alarm->getLabel();
|
||||||
|
|||||||
Reference in New Issue
Block a user