diff --git a/scripts/base/frameworks/supervisor/api.zeek b/scripts/base/frameworks/supervisor/api.zeek index 7a13a5ce09..0c2ad8285c 100644 --- a/scripts/base/frameworks/supervisor/api.zeek +++ b/scripts/base/frameworks/supervisor/api.zeek @@ -22,6 +22,7 @@ export { type Node: record { name: string; interface: string &optional; + directory: string &optional; cluster: table[string] of ClusterEndpoint &default=table(); # TODO: separate node config fields from status fields ? diff --git a/src/Supervisor.cc b/src/Supervisor.cc index bec830237b..135795e0d3 100644 --- a/src/Supervisor.cc +++ b/src/Supervisor.cc @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include @@ -720,6 +720,11 @@ Supervisor::Node Supervisor::Node::FromRecord(const RecordVal* node) if ( iface_val ) rval.interface = iface_val->AsString()->CheckString(); + auto directory_val = node->Lookup("directory"); + + if ( directory_val ) + rval.directory = directory_val->AsString()->CheckString(); + auto cluster_table_val = node->Lookup("cluster")->AsTableVal(); auto cluster_table = cluster_table_val->AsTable(); auto c = cluster_table->InitForIteration(); @@ -754,11 +759,12 @@ Supervisor::Node Supervisor::Node::FromJSON(const std::string& json) auto j = nlohmann::json::parse(json); rval.name = j["name"]; - auto it = j.find("interface"); - - if ( it != j.end() ) + if ( auto it = j.find("interface"); it != j.end() ) rval.interface = *it; + if ( auto it = j.find("directory"); it != j.end() ) + rval.directory= *it; + auto cluster = j["cluster"]; for ( const auto& e : cluster.items() ) @@ -803,6 +809,9 @@ IntrusivePtr Supervisor::Node::ToRecord() const if ( interface ) rval->Assign(rt->FieldOffset("interface"), new StringVal(*interface)); + if ( directory ) + rval->Assign(rt->FieldOffset("directory"), new StringVal(*directory)); + auto tt = BifType::Record::Supervisor::Node->FieldType("cluster"); auto cluster_val = new TableVal(tt->AsTableType()); rval->Assign(rt->FieldOffset("cluster"), cluster_val); @@ -926,6 +935,15 @@ std::string Supervisor::Create(const Supervisor::Node& node) if ( nodes.find(node.name) != nodes.end() ) return fmt("node with name '%s' already exists", node.name.data()); + if ( node.directory ) + { + auto res = ensure_intermediate_dirs(node.directory->data()); + + if ( ! res ) + return fmt("failed to create working directory %s\n", + node.directory->data()); + } + auto msg = make_create_message(node); safe_write(stem_pipe->OutFD(), msg.data(), msg.size() + 1); nodes.emplace(node.name, node); diff --git a/src/Supervisor.h b/src/Supervisor.h index 543ff8a89e..52e4bef016 100644 --- a/src/Supervisor.h +++ b/src/Supervisor.h @@ -45,6 +45,7 @@ public: std::string name; std::optional interface; + std::optional directory; std::map cluster; pid_t pid = 0; diff --git a/src/main.cc b/src/main.cc index 091a3ac33d..77121d453e 100644 --- a/src/main.cc +++ b/src/main.cc @@ -800,6 +800,18 @@ int main(int argc, char** argv) exit(1); } } + + if ( zeek::supervised_node->directory ) + { + if ( chdir(zeek::supervised_node->directory->data()) ) + { + fprintf(stderr, "supervised node %s failed to chdir to %s: %s\n", + node_name.data(), + zeek::supervised_node->directory->data(), + strerror(errno)); + exit(1); + } + } } std::set_new_handler(bro_new_handler);