Merge branch 'topic/christian/node-status-notification'

* topic/christian/node-status-notification:
  Add Supervisor::node_status notification event
This commit is contained in:
Christian Kreibich 2022-05-31 12:53:01 -07:00
commit 93bed5a261
11 changed files with 103 additions and 1 deletions

View file

@ -1,3 +1,7 @@
5.0.0-dev.525 | 2022-05-31 12:53:01 -0700
* Add Supervisor::node_status notification event (Christian Kreibich, Corelight)
5.0.0-dev.523 | 2022-05-31 11:13:47 -0700 5.0.0-dev.523 | 2022-05-31 11:13:47 -0700
* Update spicy-plugin with change that checks for zeek version (Tim Wojtulewicz, Corelight) * Update spicy-plugin with change that checks for zeek version (Tim Wojtulewicz, Corelight)

6
NEWS
View file

@ -71,6 +71,12 @@ New Functionality
directly or indirectly. The number is not meant to be precise, but directly or indirectly. The number is not meant to be precise, but
rather comparable: larger footprint correlates with more memory consumption. rather comparable: larger footprint correlates with more memory consumption.
- The Supervisor features two new events, ``Supervisor::node_status`` and
``SupervisorControl::node_status``, to notify recipients of the fact that
the stem process has (re-)started a node. The events indicate the node's
name and its new PID, reflecting the information the stem already shares
with the Supervisor core.
- The new ``configure --statedir`` option lets you adjust the installation's - The new ``configure --statedir`` option lets you adjust the installation's
persistent state directory. It defaults to ``var/lib`` under your Zeek persistent state directory. It defaults to ``var/lib`` under your Zeek
installation's root directory. installation's root directory.

View file

@ -1 +1 @@
5.0.0-dev.523 5.0.0-dev.525

View file

@ -150,4 +150,15 @@ export {
## ##
## msg: line-buffered contents from the stderr of a child process. ## msg: line-buffered contents from the stderr of a child process.
global stderr_hook: hook(node: string, msg: string); global stderr_hook: hook(node: string, msg: string);
## A notification event the Supervisor generates when it receives a
## status message update from the stem, indicating node has
## (re-)started.
##
## node: the name of a previously created node via
## :zeek:see:`Supervisor::create` indicating to which
## child process the stdout line is associated.
##
## pid: the process ID the stem reported for this node.
global node_status: event(node: string, pid: count);
} }

View file

@ -91,4 +91,16 @@ export {
## process tree. There is no response to this message as the Supervisor ## process tree. There is no response to this message as the Supervisor
## simply terminates on receipt. ## simply terminates on receipt.
global SupervisorControl::stop_request: event(); global SupervisorControl::stop_request: event();
## A notification event the Supervisor generates when it receives a
## status message update from the stem, indicating node has
## (re-)started. This is the remote equivalent of
## :zeek:see:`Supervisor::node_status`.
##
## node: the name of a previously created node via
## :zeek:see:`Supervisor::create` indicating to which
## child process the stdout line is associated.
##
## pid: the process ID the stem reported for this node.
global SupervisorControl::node_status: event(node: string, pid: count);
} }

View file

@ -99,3 +99,12 @@ event SupervisorControl::restart_request(reqid: string, node: string)
local topic = SupervisorControl::topic_prefix + fmt("/restart_response/%s", reqid); local topic = SupervisorControl::topic_prefix + fmt("/restart_response/%s", reqid);
Broker::publish(topic, SupervisorControl::restart_response, reqid, res); Broker::publish(topic, SupervisorControl::restart_response, reqid, res);
} }
event Supervisor::node_status(node: string, pid: count)
{
if ( ! Supervisor::is_supervisor() )
return;
local topic = SupervisorControl::topic_prefix + "/node_status";
Broker::publish(topic, SupervisorControl::node_status, node, pid);
}

View file

@ -26,6 +26,8 @@ extern "C"
#include "zeek/DebugLogger.h" #include "zeek/DebugLogger.h"
#include "zeek/Dict.h" #include "zeek/Dict.h"
#include "zeek/Event.h"
#include "zeek/EventHandler.h"
#include "zeek/ID.h" #include "zeek/ID.h"
#include "zeek/NetVar.h" #include "zeek/NetVar.h"
#include "zeek/RE.h" #include "zeek/RE.h"
@ -484,6 +486,8 @@ void Supervisor::HandleChildSignal()
void Supervisor::InitPostScript() void Supervisor::InitPostScript()
{ {
node_status = event_registry->Register("Supervisor::node_status");
stem_stdout.hook = id::find_func("Supervisor::stdout_hook"); stem_stdout.hook = id::find_func("Supervisor::stdout_hook");
stem_stderr.hook = id::find_func("Supervisor::stderr_hook"); stem_stderr.hook = id::find_func("Supervisor::stderr_hook");
@ -597,6 +601,10 @@ size_t Supervisor::ProcessMessages()
if ( it != nodes.end() ) if ( it != nodes.end() )
it->second.pid = std::stoi(msg_tokens[2]); it->second.pid = std::stoi(msg_tokens[2]);
if ( node_status )
event_mgr.Enqueue(node_status, make_intrusive<StringVal>(name),
val_mgr->Count(std::stoi(msg_tokens[2])));
} }
else if ( type == "debug" ) else if ( type == "debug" )
{ {

View file

@ -332,6 +332,7 @@ private:
detail::Flare signal_flare; detail::Flare signal_flare;
NodeMap nodes; NodeMap nodes;
std::string msg_buffer; std::string msg_buffer;
EventHandlerPtr node_status;
}; };
namespace detail namespace detail

View file

@ -3,6 +3,7 @@
warning in <...>/check-unused-event-handlers.test, line 6: handler for non-existing event cannot be invoked (this_is_never_used) warning in <...>/check-unused-event-handlers.test, line 6: handler for non-existing event cannot be invoked (this_is_never_used)
warning in <params>, line 1: event handler never invoked: InputConfig::new_value warning in <params>, line 1: event handler never invoked: InputConfig::new_value
warning in <params>, line 1: event handler never invoked: InputRaw::process_finished warning in <params>, line 1: event handler never invoked: InputRaw::process_finished
warning in <params>, line 1: event handler never invoked: Supervisor::node_status
warning in <params>, line 1: event handler never invoked: SupervisorControl::create_request warning in <params>, line 1: event handler never invoked: SupervisorControl::create_request
warning in <params>, line 1: event handler never invoked: SupervisorControl::destroy_request warning in <params>, line 1: event handler never invoked: SupervisorControl::destroy_request
warning in <params>, line 1: event handler never invoked: SupervisorControl::restart_request warning in <params>, line 1: event handler never invoked: SupervisorControl::restart_request

View file

@ -0,0 +1,3 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
got node_status event, grault
got node_status event, grault

View file

@ -0,0 +1,47 @@
# This test verifies that the Supervisor triggers Supervisor::node_status
# events when the stem (re)creates nodes.
#
# @TEST-EXEC: btest-bg-run zeek zeek -j -b %INPUT
# @TEST-EXEC: btest-bg-wait 30
# @TEST-EXEC: btest-diff zeek/.stdout
# So the supervised node doesn't terminate right away.
redef exit_only_after_terminate=T;
global status_count = 0;
global check_interval = 0.1sec;
event Supervisor::node_status(node: string, pid: count)
{
# We handle this once for the initial node creation, once for the
# restart, then quit.
if ( ++status_count == 2)
terminate();
print "got node_status event", node;
# The status update has a PID for the new node, so checking node status
# now should report a matching PID. This will output only in case the
# PIDs do not match, failing the test.
local s = Supervisor::status(node);
local ns = s$nodes["grault"];
if ( ! ns$pid )
print "pid unavailable via Supervisor::status()", pid;
else if ( ns$pid != pid )
print "pid mismatch", ns$pid, pid;
Supervisor::restart("grault");
}
event zeek_init()
{
if ( Supervisor::is_supervisor() )
{
local sn = Supervisor::NodeConfig($name="grault");
local res = Supervisor::create(sn);
if ( res != "" )
print "failed to create node", res;
}
}