mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
Management framework: add get_id_value dispatch
This adds support for retrieving the value of a global identifier from any subset of cluster nodes. It relies on the lookup_ID() BiF to retrieve the val, and to_json() to render the value to an easily parsed string. Ideally we'd send the val directly, but this hits several roadblocks, including the fact that Broker won't serialize arbitrary values.
This commit is contained in:
parent
788348f9d6
commit
497b2723d7
5 changed files with 121 additions and 2 deletions
|
@ -66,7 +66,11 @@ export {
|
||||||
## The controller sends this to every agent to request a dispatch (the
|
## The controller sends this to every agent to request a dispatch (the
|
||||||
## execution of a pre-implemented activity) to all cluster nodes. This
|
## execution of a pre-implemented activity) to all cluster nodes. This
|
||||||
## is the generic controller-agent "back-end" implementation of explicit
|
## is the generic controller-agent "back-end" implementation of explicit
|
||||||
## client-controller "front-end" interactions.
|
## client-controller "front-end" interactions, including:
|
||||||
|
##
|
||||||
|
## - :zeek:see:`Management::Controller::API::get_id_value_request`: two
|
||||||
|
## arguments, the first being "get_id_value" and the second the name
|
||||||
|
## of the ID to look up.
|
||||||
##
|
##
|
||||||
## reqid: a request identifier string, echoed in the response event.
|
## reqid: a request identifier string, echoed in the response event.
|
||||||
##
|
##
|
||||||
|
|
|
@ -321,6 +321,10 @@ event Management::Node::API::node_dispatch_response(reqid: string, result: Manag
|
||||||
# confirm their type here based on the requested dispatch command.
|
# confirm their type here based on the requested dispatch command.
|
||||||
switch req$node_dispatch_state$action[0]
|
switch req$node_dispatch_state$action[0]
|
||||||
{
|
{
|
||||||
|
case "get_id_value":
|
||||||
|
if ( result?$data )
|
||||||
|
result$data = result$data as string;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Management::Log::error(fmt("unexpected dispatch command %s",
|
Management::Log::error(fmt("unexpected dispatch command %s",
|
||||||
req$node_dispatch_state$action[0]));
|
req$node_dispatch_state$action[0]));
|
||||||
|
|
|
@ -80,6 +80,31 @@ export {
|
||||||
result: Management::ResultVec);
|
result: Management::ResultVec);
|
||||||
|
|
||||||
|
|
||||||
|
## zeek-client sends this event to retrieve the current value of a
|
||||||
|
## variable in Zeek's global namespace, referenced by the given
|
||||||
|
## identifier (i.e., variable name). The controller asks all agents
|
||||||
|
## to retrieve this value from each cluster node, accumulates the
|
||||||
|
## returned responses, and responds with a get_id_value_response
|
||||||
|
## event back to the client.
|
||||||
|
##
|
||||||
|
## reqid: a request identifier string, echoed in the response event.
|
||||||
|
##
|
||||||
|
## id: the name of the variable whose value to retrieve.
|
||||||
|
global get_id_value_request: event(reqid: string, id: string);
|
||||||
|
|
||||||
|
## Response to a get_id_value_request event. The controller sends this
|
||||||
|
## back to the client.
|
||||||
|
##
|
||||||
|
## reqid: the request identifier used in the request event.
|
||||||
|
##
|
||||||
|
## result: a :zeek:type:`vector` of :zeek:see:`Management::Result`
|
||||||
|
## records. Each record covers one Zeek cluster node. Each record's
|
||||||
|
## data field contains a string with the JSON rendering (as produced
|
||||||
|
## by :zeek:id:`to_json`, including the error strings it potentially
|
||||||
|
## returns).
|
||||||
|
global get_id_value_response: event(reqid: string, result: Management::ResultVec);
|
||||||
|
|
||||||
|
|
||||||
# Testing events. These don't provide operational value but expose
|
# Testing events. These don't provide operational value but expose
|
||||||
# internal functionality, triggered by test cases.
|
# internal functionality, triggered by test cases.
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,11 @@ export {
|
||||||
## and report their outcomes. See
|
## and report their outcomes. See
|
||||||
## :zeek:see:`Management::Agent::API::node_dispatch_request` and
|
## :zeek:see:`Management::Agent::API::node_dispatch_request` and
|
||||||
## :zeek:see:`Management::Agent::API::node_dispatch_response` for the
|
## :zeek:see:`Management::Agent::API::node_dispatch_response` for the
|
||||||
## agent/controller interaction.
|
## agent/controller interaction, and
|
||||||
|
## :zeek:see:`Management::Controller::API::get_id_value_request` and
|
||||||
|
## :zeek:see:`Management::Controller::API::get_id_value_response`
|
||||||
|
## for an example of a specific API the controller generalizes into
|
||||||
|
## a dispatch.
|
||||||
type NodeDispatchState: record {
|
type NodeDispatchState: record {
|
||||||
## The dispatched action. The first string is a command,
|
## The dispatched action. The first string is a command,
|
||||||
## any remaining strings its arguments.
|
## any remaining strings its arguments.
|
||||||
|
@ -598,6 +602,10 @@ event Management::Agent::API::node_dispatch_response(reqid: string, results: Man
|
||||||
# type "any": confirm their (known) type here.
|
# type "any": confirm their (known) type here.
|
||||||
switch req$node_dispatch_state$action[0]
|
switch req$node_dispatch_state$action[0]
|
||||||
{
|
{
|
||||||
|
case "get_id_value":
|
||||||
|
if ( results[i]?$data )
|
||||||
|
results[i]$data = results[i]$data as string;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Management::Log::error(fmt("unexpected dispatch command %s",
|
Management::Log::error(fmt("unexpected dispatch command %s",
|
||||||
req$node_dispatch_state$action[0]));
|
req$node_dispatch_state$action[0]));
|
||||||
|
@ -620,6 +628,12 @@ event Management::Agent::API::node_dispatch_response(reqid: string, results: Man
|
||||||
# Send response event to the client based upon the dispatch type.
|
# Send response event to the client based upon the dispatch type.
|
||||||
switch req$node_dispatch_state$action[0]
|
switch req$node_dispatch_state$action[0]
|
||||||
{
|
{
|
||||||
|
case "get_id_value":
|
||||||
|
Management::Log::info(fmt(
|
||||||
|
"tx Management::Controller::API::get_id_value_response %s",
|
||||||
|
Management::Request::to_string(req)));
|
||||||
|
event Management::Controller::API::get_id_value_response(req$id, req$results);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Management::Log::error(fmt("unexpected dispatch command %s",
|
Management::Log::error(fmt("unexpected dispatch command %s",
|
||||||
req$node_dispatch_state$action[0]));
|
req$node_dispatch_state$action[0]));
|
||||||
|
@ -629,6 +643,42 @@ event Management::Agent::API::node_dispatch_response(reqid: string, results: Man
|
||||||
Management::Request::finish(req$id);
|
Management::Request::finish(req$id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event Management::Controller::API::get_id_value_request(reqid: string, id: string)
|
||||||
|
{
|
||||||
|
Management::Log::info(fmt("rx Management::Controller::API::get_id_value_request %s %s", reqid, id));
|
||||||
|
|
||||||
|
# Special case: if we have no instances, respond right away.
|
||||||
|
if ( |g_instances| == 0 )
|
||||||
|
{
|
||||||
|
Management::Log::info(fmt("tx Management::Controller::API::get_id_value_response %s", reqid));
|
||||||
|
event Management::Controller::API::get_id_value_response(reqid, vector(
|
||||||
|
Management::Result($reqid=reqid, $success=F, $error="no instances connected")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
local action = vector("get_id_value", id);
|
||||||
|
local req = Management::Request::create(reqid);
|
||||||
|
req$node_dispatch_state = NodeDispatchState($action=action);
|
||||||
|
|
||||||
|
for ( name in g_instances )
|
||||||
|
{
|
||||||
|
if ( name !in g_instances_ready )
|
||||||
|
next;
|
||||||
|
|
||||||
|
local agent_topic = Management::Agent::topic_prefix + "/" + name;
|
||||||
|
local areq = Management::Request::create();
|
||||||
|
|
||||||
|
areq$parent_id = req$id;
|
||||||
|
add req$node_dispatch_state$requests[areq$id];
|
||||||
|
|
||||||
|
Management::Log::info(fmt(
|
||||||
|
"tx Management::Agent::API::node_dispatch_request %s %s to %s",
|
||||||
|
areq$id, action, name));
|
||||||
|
|
||||||
|
Broker::publish(agent_topic, Management::Agent::API::node_dispatch_request, areq$id, action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
event Management::Request::request_expired(req: Management::Request::Request)
|
event Management::Request::request_expired(req: Management::Request::Request)
|
||||||
{
|
{
|
||||||
# Various handlers for timed-out request state. We use the state members
|
# Various handlers for timed-out request state. We use the state members
|
||||||
|
@ -665,6 +715,12 @@ event Management::Request::request_expired(req: Management::Request::Request)
|
||||||
|
|
||||||
switch req$node_dispatch_state$action[0]
|
switch req$node_dispatch_state$action[0]
|
||||||
{
|
{
|
||||||
|
case "get_id_value":
|
||||||
|
Management::Log::info(fmt(
|
||||||
|
"tx Management::Controller::API::get_id_value_response %s",
|
||||||
|
Management::Request::to_string(req)));
|
||||||
|
event Management::Controller::API::get_id_value_response(req$id, req$results);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Management::Log::error(fmt("unexpected dispatch command %s",
|
Management::Log::error(fmt("unexpected dispatch command %s",
|
||||||
req$node_dispatch_state$action[0]));
|
req$node_dispatch_state$action[0]));
|
||||||
|
@ -717,6 +773,7 @@ event zeek_init()
|
||||||
Management::Controller::API::get_instances_response,
|
Management::Controller::API::get_instances_response,
|
||||||
Management::Controller::API::set_configuration_response,
|
Management::Controller::API::set_configuration_response,
|
||||||
Management::Controller::API::get_nodes_response,
|
Management::Controller::API::get_nodes_response,
|
||||||
|
Management::Controller::API::get_id_value_response,
|
||||||
Management::Controller::API::test_timeout_response
|
Management::Controller::API::test_timeout_response
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,36 @@ redef Management::Log::role = Management::NODE;
|
||||||
## provided result record.
|
## provided result record.
|
||||||
type DispatchCallback: function(args: vector of string, res: Management::Result);
|
type DispatchCallback: function(args: vector of string, res: Management::Result);
|
||||||
|
|
||||||
|
## Implementation of the "get_id_value" dispatch. Its only argument is the name
|
||||||
|
## of the ID to look up.
|
||||||
|
function dispatch_get_id_value(args: vector of string, res: Management::Result)
|
||||||
|
{
|
||||||
|
if ( |args| == 0 )
|
||||||
|
{
|
||||||
|
res$success = F;
|
||||||
|
res$error = "get_id_value expects name of global identifier";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
local val = lookup_ID(args[0]);
|
||||||
|
|
||||||
|
# The following lookup_ID() result strings indicate errors:
|
||||||
|
if ( type_name(val) == "string" )
|
||||||
|
{
|
||||||
|
local valstr: string = val;
|
||||||
|
if ( valstr == "<unknown id>" || valstr == "<no ID value>" )
|
||||||
|
{
|
||||||
|
res$success = F;
|
||||||
|
res$error = valstr[1:-1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( res$success )
|
||||||
|
res$data = to_json(val);
|
||||||
|
}
|
||||||
|
|
||||||
global g_dispatch_table: table[string] of DispatchCallback = {
|
global g_dispatch_table: table[string] of DispatchCallback = {
|
||||||
|
["get_id_value"] = dispatch_get_id_value,
|
||||||
};
|
};
|
||||||
|
|
||||||
event Management::Node::API::node_dispatch_request(reqid: string, action: vector of string)
|
event Management::Node::API::node_dispatch_request(reqid: string, action: vector of string)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue