mirror of
https://github.com/zeek/zeek.git
synced 2025-10-12 19:48:20 +00:00
Add skeleton logic for handling supevisor control messages
This commit is contained in:
parent
e46cf88435
commit
7c08488dfc
5 changed files with 170 additions and 34 deletions
|
@ -4,18 +4,19 @@
|
||||||
module Supervisor;
|
module Supervisor;
|
||||||
|
|
||||||
export {
|
export {
|
||||||
type Status: record {
|
type Node: record {
|
||||||
# TODO: add proper status fields
|
# TODO: add proper config fields
|
||||||
n: count;
|
|
||||||
};
|
|
||||||
|
|
||||||
type NodeConfig: record {
|
|
||||||
# TODO: add proper config field
|
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type Status: record {
|
||||||
|
# TODO: add proper status fields
|
||||||
|
n: count;
|
||||||
|
nodes: table[string] of Node;
|
||||||
|
};
|
||||||
|
|
||||||
global status: function(nodes: string &default="all"): Status;
|
global status: function(nodes: string &default="all"): Status;
|
||||||
global create: function(config: NodeConfig): string;
|
global create: function(node: Node): string;
|
||||||
global destroy: function(nodes: string): bool;
|
global destroy: function(nodes: string): bool;
|
||||||
global restart: function(nodes: string &default="all"): bool;
|
global restart: function(nodes: string &default="all"): bool;
|
||||||
|
|
||||||
|
@ -24,7 +25,7 @@ export {
|
||||||
global Supervisor::status_request: event(id: count, nodes: string);
|
global Supervisor::status_request: event(id: count, nodes: string);
|
||||||
global Supervisor::status_response: event(id: count, result: Status);
|
global Supervisor::status_response: event(id: count, result: Status);
|
||||||
|
|
||||||
global Supervisor::create_request: event(id: count, config: NodeConfig);
|
global Supervisor::create_request: event(id: count, node: Node);
|
||||||
global Supervisor::create_response: event(id: count, result: string);
|
global Supervisor::create_response: event(id: count, result: string);
|
||||||
|
|
||||||
global Supervisor::destroy_request: event(id: count, nodes: string);
|
global Supervisor::destroy_request: event(id: count, nodes: string);
|
||||||
|
|
|
@ -28,9 +28,9 @@ event Supervisor::status_request(id: count, nodes: string)
|
||||||
Broker::publish(topic, Supervisor::status_response, id, res);
|
Broker::publish(topic, Supervisor::status_response, id, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
event Supervisor::create_request(id: count, config: NodeConfig)
|
event Supervisor::create_request(id: count, node: Node)
|
||||||
{
|
{
|
||||||
local res = Supervisor::create(config);
|
local res = Supervisor::create(node);
|
||||||
local topic = Supervisor::topic_prefix + "/create_response";
|
local topic = Supervisor::topic_prefix + "/create_response";
|
||||||
Broker::publish(topic, Supervisor::create_response, id, res);
|
Broker::publish(topic, Supervisor::create_response, id, res);
|
||||||
}
|
}
|
||||||
|
@ -54,9 +54,9 @@ function Supervisor::status(nodes: string): Status
|
||||||
return Supervisor::__status(nodes);
|
return Supervisor::__status(nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
function create(config: NodeConfig): string
|
function create(node: Node): string
|
||||||
{
|
{
|
||||||
return Supervisor::__create(config);
|
return Supervisor::__create(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
function destroy(nodes: string): bool
|
function destroy(nodes: string): bool
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <poll.h>
|
||||||
|
|
||||||
#include "Supervisor.h"
|
#include "Supervisor.h"
|
||||||
#include "Reporter.h"
|
#include "Reporter.h"
|
||||||
|
@ -201,43 +202,171 @@ void zeek::Supervisor::RunStem(std::unique_ptr<bro::Pipe> pipe)
|
||||||
fprintf(stderr, "failed to set stem process group: %s\n",
|
fprintf(stderr, "failed to set stem process group: %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
|
|
||||||
|
std::string msg_buffer;
|
||||||
|
std::map<std::string, Node> nodes;
|
||||||
|
|
||||||
|
auto extract_messages = [](std::string* buf) -> std::vector<std::string>
|
||||||
|
{
|
||||||
|
std::vector<std::string> rval;
|
||||||
|
|
||||||
for ( ; ; )
|
for ( ; ; )
|
||||||
{
|
{
|
||||||
// TODO: make a proper I/O loop w/ message processing via pipe
|
auto msg_end = buf->find('\0');
|
||||||
// TODO: better way to detect loss of parent than polling
|
|
||||||
|
if ( msg_end == std::string::npos )
|
||||||
|
// Don't have a full message yet
|
||||||
|
break;
|
||||||
|
|
||||||
|
auto msg = buf->substr(0, msg_end);
|
||||||
|
rval.emplace_back(std::move(msg));
|
||||||
|
buf->erase(0, msg_end + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
};
|
||||||
|
|
||||||
|
for ( ; ; )
|
||||||
|
{
|
||||||
|
// TODO: better way to detect loss of parent than polling ?
|
||||||
|
|
||||||
|
pollfd fds = { pipe->ReadFD(), POLLIN, 0 };
|
||||||
|
constexpr auto poll_timeout_ms = 1000;
|
||||||
|
auto res = poll(&fds, 1, poll_timeout_ms);
|
||||||
|
|
||||||
|
if ( res < 0 )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "poll() failed: %s\n", strerror(errno));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if ( getppid() == 1 )
|
if ( getppid() == 1 )
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|
||||||
sleep(5);
|
if ( res == 0 )
|
||||||
printf("Stem wakeup\n");
|
continue;
|
||||||
write(pipe->WriteFD(), "hi", 2);
|
|
||||||
|
char buf[256];
|
||||||
|
int bytes_read = read(pipe->ReadFD(), buf, 256);
|
||||||
|
|
||||||
|
if ( bytes_read == 0 )
|
||||||
|
// EOF
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
if ( bytes_read < 0 )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "read() failed: %s\n", strerror(errno));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg_buffer.append(buf, bytes_read);
|
||||||
|
auto msgs = extract_messages(&msg_buffer);
|
||||||
|
|
||||||
|
for ( auto& msg : msgs )
|
||||||
|
{
|
||||||
|
// TODO: improve message format ...
|
||||||
|
std::vector<std::string> msg_tokens;
|
||||||
|
tokenize_string(std::move(msg), " ", &msg_tokens);
|
||||||
|
const auto& cmd = msg_tokens[0];
|
||||||
|
const auto& node_name = msg_tokens[1];
|
||||||
|
|
||||||
|
if ( cmd == "create" )
|
||||||
|
{
|
||||||
|
auto res = nodes.emplace(node_name, Node{node_name});
|
||||||
|
assert(res.second);
|
||||||
|
// TODO: fork
|
||||||
|
printf("Stem creating node: %s\n", node_name.data());
|
||||||
|
}
|
||||||
|
else if ( cmd == "destroy" )
|
||||||
|
{
|
||||||
|
auto res = nodes.erase(node_name);
|
||||||
|
assert(res > 0 );
|
||||||
|
printf("Stem destroying node: %s\n", node_name.data());
|
||||||
|
// TODO: kill
|
||||||
|
}
|
||||||
|
else if ( cmd == "restart" )
|
||||||
|
{
|
||||||
|
auto it = nodes.find(node_name);
|
||||||
|
assert(it != nodes.end());
|
||||||
|
printf("Stem restarting node: %s\n", node_name.data());
|
||||||
|
// TODO: re-use logic for destroy then create
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fprintf(stderr, "unknown supervisor message: %s", cmd.data());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RecordVal* zeek::Supervisor::Status(const std::string& nodes)
|
static zeek::Supervisor::Node node_val_to_struct(const RecordVal* node)
|
||||||
{
|
{
|
||||||
|
zeek::Supervisor::Node rval;
|
||||||
|
rval.name = node->Lookup("name")->AsString()->CheckString();
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static RecordVal* node_struct_to_val(const zeek::Supervisor::Node& node)
|
||||||
|
{
|
||||||
|
auto rval = new RecordVal(BifType::Record::Supervisor::Node);
|
||||||
|
rval->Assign(0, new StringVal(node.name));
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
RecordVal* zeek::Supervisor::Status(const std::string& node_name)
|
||||||
|
{
|
||||||
|
// TODO: handle node classes
|
||||||
// TODO: return real status information
|
// TODO: return real status information
|
||||||
static auto count = 0;
|
static auto count = 0;
|
||||||
auto rval = new RecordVal(BifType::Record::Supervisor::Status);
|
auto rval = new RecordVal(BifType::Record::Supervisor::Status);
|
||||||
rval->Assign(0, val_mgr->GetCount(count++));
|
rval->Assign(0, val_mgr->GetCount(count++));
|
||||||
|
|
||||||
|
auto tt = BifType::Record::Supervisor::Status->FieldType("nodes");
|
||||||
|
auto node_table_val = new TableVal(tt->AsTableType());
|
||||||
|
rval->Assign(1, node_table_val);
|
||||||
|
|
||||||
|
for ( const auto& n : nodes )
|
||||||
|
{
|
||||||
|
const auto& node = n.second;
|
||||||
|
auto key = new StringVal(node.name);
|
||||||
|
auto val = node_struct_to_val(node);
|
||||||
|
node_table_val->Assign(key, val);
|
||||||
|
Unref(key);
|
||||||
|
}
|
||||||
|
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string zeek::Supervisor::Create(const RecordVal* node_config)
|
std::string zeek::Supervisor::Create(const RecordVal* node_val)
|
||||||
{
|
{
|
||||||
// TODO: return error msg on fail, or empty on success
|
auto node = node_val_to_struct(node_val);
|
||||||
|
|
||||||
|
if ( nodes.find(node.name) != nodes.end() )
|
||||||
|
return fmt("node with name '%s' already exists", node.name.data());
|
||||||
|
|
||||||
|
std::string msg = fmt("create %s", node.name.data());
|
||||||
|
safe_write(stem_pipe->WriteFD(), msg.data(), msg.size() + 1);
|
||||||
|
nodes.emplace(node.name, node);
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool zeek::Supervisor::Destroy(const std::string& nodes)
|
bool zeek::Supervisor::Destroy(const std::string& node_name)
|
||||||
{
|
{
|
||||||
// TODO: return true if a matching node exists
|
// TODO: handle node classes
|
||||||
|
|
||||||
|
if ( ! nodes.erase(node_name) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
std::string msg = fmt("destroy %s", node_name.data());
|
||||||
|
safe_write(stem_pipe->WriteFD(), msg.data(), msg.size() + 1);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool zeek::Supervisor::Restart(const std::string& nodes)
|
bool zeek::Supervisor::Restart(const std::string& node_name)
|
||||||
{
|
{
|
||||||
// TODO: return true if a matching node exists
|
// TODO: handle node classes
|
||||||
|
|
||||||
|
if ( nodes.find(node_name) == nodes.end() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
std::string msg = fmt("restart %s", node_name.data());
|
||||||
|
safe_write(stem_pipe->WriteFD(), msg.data(), msg.size() + 1);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include "iosource/IOSource.h"
|
#include "iosource/IOSource.h"
|
||||||
#include "Pipe.h"
|
#include "Pipe.h"
|
||||||
|
@ -24,6 +25,10 @@ public:
|
||||||
std::string zeek_exe_path;
|
std::string zeek_exe_path;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Node {
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
Supervisor(Config cfg, std::unique_ptr<bro::Pipe> stem_pipe, pid_t stem_pid);
|
Supervisor(Config cfg, std::unique_ptr<bro::Pipe> stem_pipe, pid_t stem_pid);
|
||||||
|
|
||||||
~Supervisor();
|
~Supervisor();
|
||||||
|
@ -33,10 +38,10 @@ public:
|
||||||
|
|
||||||
void ObserveChildSignal();
|
void ObserveChildSignal();
|
||||||
|
|
||||||
RecordVal* Status(const std::string& nodes);
|
RecordVal* Status(const std::string& node_name);
|
||||||
std::string Create(const RecordVal* node_config);
|
std::string Create(const RecordVal* node);
|
||||||
bool Destroy(const std::string& nodes);
|
bool Destroy(const std::string& node_name);
|
||||||
bool Restart(const std::string& nodes);
|
bool Restart(const std::string& node_name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -57,6 +62,7 @@ private:
|
||||||
pid_t stem_pid;
|
pid_t stem_pid;
|
||||||
std::unique_ptr<bro::Pipe> stem_pipe;
|
std::unique_ptr<bro::Pipe> stem_pipe;
|
||||||
bro::Flare signal_flare;
|
bro::Flare signal_flare;
|
||||||
|
std::map<std::string, Node> nodes;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Supervisor* supervisor;
|
extern Supervisor* supervisor;
|
||||||
|
|
|
@ -7,16 +7,16 @@
|
||||||
module Supervisor;
|
module Supervisor;
|
||||||
|
|
||||||
type Supervisor::Status: record;
|
type Supervisor::Status: record;
|
||||||
type Supervisor::NodeConfig: record;
|
type Supervisor::Node: record;
|
||||||
|
|
||||||
function Supervisor::__status%(nodes: string%): Supervisor::Status
|
function Supervisor::__status%(nodes: string%): Supervisor::Status
|
||||||
%{
|
%{
|
||||||
return zeek::supervisor->Status(nodes->CheckString());
|
return zeek::supervisor->Status(nodes->CheckString());
|
||||||
%}
|
%}
|
||||||
|
|
||||||
function Supervisor::__create%(config: Supervisor::NodeConfig%): string
|
function Supervisor::__create%(node: Supervisor::Node%): string
|
||||||
%{
|
%{
|
||||||
auto rval = zeek::supervisor->Create(config->AsRecordVal());
|
auto rval = zeek::supervisor->Create(node->AsRecordVal());
|
||||||
return new StringVal(rval);
|
return new StringVal(rval);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue