Update to the new config format
continuous-integration/drone/push Build is passing Details

pull/4/head
Clément FRÉVILLE 2 years ago
parent 34335045ca
commit 3f4588f44a

@ -15,7 +15,7 @@ FetchContent_MakeAvailable(tomlplusplus)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/libzmq-pkg-config)
find_package(ZeroMQ QUIET)
add_executable(planificador src/host.cpp src/runner.cpp src/network.cpp src/config.cpp src/main.cpp)
add_executable(planificador src/runner.cpp src/network.cpp src/config.cpp src/main.cpp)
if (NOT ZeroMQ_FOUND)
message(STATUS "ZeroMQ not found, using bundled version")
FetchContent_Declare(

@ -0,0 +1,6 @@
planificador
===========
A sandbox execution environment for untrusted code. It acts as a front-end in front of Docker+Bubblewrap.
Tasks are submitted using a ZeroMQ message queue, allowing quick scaling of the system.

@ -1,12 +0,0 @@
[serveurs]
[serveurs.serveur1]
ip = '100.000.000.000'
nbContainerMax = 10
[serveurs.serveur2]
ip = '200.000.000.000'
nbContainerMax = 20
[serveurs.serveur3]
ip = '300.000.000.000'
nbContainerMax = 30

@ -0,0 +1,7 @@
[queue]
pull = "tcp://localhost:5557"
push = "tcp://localhost:5558"
threads = 1
[runner]
timeout = 2

@ -1,29 +1,33 @@
#include "config.hpp"
std::vector<sk::host> sk::config::loadHostsFromToml(const fs::path &confFile) {
std::vector<sk::host> hosts;
#include <iostream>
#include <toml++/toml.h>
auto config = toml::parse_file(confFile.string());
toml::table *serverSection = config.get_as<toml::table>("serveurs");
if (serverSection == nullptr) {
return hosts;
static sk::config read(const toml::table &config) {
return sk::config{
sk::queue_config{
config["queue"]["pull"].value_or("tcp://localhost:5557"),
config["queue"]["push"].value_or("tcp://localhost:5558"),
config["queue"]["threads"].value_or(1u),
},
sk::runner_config{
config["runner"]["timeout"].value_or(2u),
},
};
}
// Parcourir les serveurs
for (const auto &[serverNameKey, serverInfoValue] : *serverSection) {
std::string serverName{serverNameKey};
toml::table *serverInfoPtr = serverInfoValue.as_table();
if (serverInfoPtr == nullptr) {
sk::config sk::config::read_or_default(const std::filesystem::path &path, bool expect_present) {
std::ifstream t(path);
if (!t) {
if (errno == ENOENT && !expect_present) {
std::cout << "Using default config\n";
} else {
std::cerr << "Failed to open config file " << path << ": " << strerror(errno) << "\n";
}
toml::table &serverInfo = *serverInfoPtr;
if (serverInfo.get_as<std::string>("ip") && serverInfo.get_as<int64_t>("nbContainerMax")) {
std::string serverIp = serverInfo.get_as<std::string>("ip")->get();
int serverMaxContainers = serverInfo.get_as<int64_t>("nbContainerMax")->get();
hosts.push_back(sk::host(serverIp, serverMaxContainers));
return read(toml::table{});
}
}
return hosts;
std::stringstream buffer;
buffer << t.rdbuf();
auto config = toml::parse(buffer.str(), path);
return read(config);
}

@ -1,15 +1,23 @@
#pragma once
#include <filesystem>
#include <toml++/toml.h>
#include <vector>
#include "host.hpp"
namespace fs = std::filesystem;
#include <string>
namespace sk {
class config {
public:
static std::vector<sk::host> loadHostsFromToml(const fs::path &confFile);
struct queue_config {
std::string pull_addr;
std::string push_addr;
unsigned int nb_threads;
};
struct runner_config {
unsigned int timeout;
};
struct config {
queue_config queue;
runner_config runner;
static config read_or_default(const std::filesystem::path &path, bool expect_present = false);
};
}

@ -1,16 +0,0 @@
#include "host.hpp"
namespace sk {
host::host(const std::string &ip, unsigned int connectionsMax) : ip{ip}, connections{0}, connectionsMax{connectionsMax}, runners{} {}
void host::addConnection(sk::runner &runner) {
runners.push(&runner);
connections += 1;
}
const std::string &host::getIp() const { return ip; }
unsigned int host::getNbConnections() const { return connections; }
unsigned int host::getNbConnectionsMax() const { return connectionsMax; }
}

@ -1,27 +0,0 @@
#pragma once
#include "runner.hpp"
#include <queue>
#include <string>
namespace sk {
class host {
std::string ip;
unsigned int connections;
unsigned int connectionsMax;
std::queue<sk::runner *> runners;
public:
host(const std::string &ip, unsigned int connectionsMax);
void addConnection(sk::runner &runner);
const std::string &getIp() const;
unsigned int getNbConnections() const;
unsigned int getNbConnectionsMax() const;
bool operator<(const host &other) const { return (connectionsMax - connections) < other.getNbConnectionsMax() - other.getNbConnections(); }
};
}

@ -9,6 +9,7 @@
#include <unistd.h>
#include <wait.h>
#include "config.hpp"
#include "zmq_addon.hpp"
static constexpr uint32_t JOB_ID_LEN = 32;
@ -34,12 +35,18 @@ sk::runner *global_runner = nullptr;
int main(int argc, char **argv) {
int opt;
std::optional<sk::runner_backend> selected_backend;
while ((opt = getopt(argc, argv, "bc")) != -1) {
std::filesystem::path config_path("config.toml");
bool may_use_default_config = true;
while ((opt = getopt(argc, argv, "bc:d")) != -1) {
switch (opt) {
case 'b':
selected_backend = sk::runner_backend::BubbleWrap;
break;
case 'c':
config_path = optarg;
may_use_default_config = false;
break;
case 'd':
selected_backend = sk::runner_backend::Docker;
break;
default:
@ -48,7 +55,8 @@ int main(int argc, char **argv) {
}
}
sk::runner runner(selected_backend.has_value() ? selected_backend.value() : detect_backend());
sk::config config = sk::config::read_or_default(config_path, !may_use_default_config);
sk::runner runner(selected_backend.has_value() ? selected_backend.value() : detect_backend(), config.runner);
global_runner = &runner;
struct sigaction action {};
action.sa_handler = [](int) {
@ -76,11 +84,11 @@ int main(int argc, char **argv) {
return 0;
}
zmq::context_t context(1);
zmq::context_t context(static_cast<int>(config.queue.nb_threads));
zmq::socket_t receiver(context, zmq::socket_type::pull);
receiver.connect("tcp://localhost:5557");
receiver.connect(config.queue.pull_addr);
zmq::socket_t sender(context, zmq::socket_type::push);
sender.connect("tcp://localhost:5558");
sender.connect(config.queue.push_addr);
while (true) {
zmq::message_t request;

@ -11,8 +11,6 @@
#include <unistd.h>
#include <wait.h>
static constexpr int TIMEOUT_SECONDS = 2;
// Define a helper to throw a system error if a syscall fails
static auto ensure = [](int res) -> void {
if (res == -1) {
@ -21,7 +19,7 @@ static auto ensure = [](int res) -> void {
};
namespace sk {
runner::runner(runner_backend backend) : backend{backend} {}
runner::runner(runner_backend backend, const runner_config &config) : backend{backend}, timeout{static_cast<int>(config.timeout)} {}
run_result runner::run_blocking(const program &program) {
// Open file descriptors ahead of time
@ -38,7 +36,7 @@ run_result runner::run_blocking(const program &program) {
throw std::system_error{errno, std::generic_category()};
}
itimerspec timer{};
timer.it_value.tv_sec = TIMEOUT_SECONDS;
timer.it_value.tv_sec = timeout;
if (timerfd_settime(timerfd, 0, &timer, nullptr) == -1) {
throw std::system_error{errno, std::generic_category()};
}

@ -1,5 +1,6 @@
#pragma once
#include "config.hpp"
#include "program.hpp"
#include <mutex>
#include <string>
@ -21,11 +22,12 @@ enum class runner_backend { BubbleWrap, Docker };
class runner {
runner_backend backend;
int timeout;
std::vector<active_job> active_jobs;
std::mutex active_jobs_mutex;
public:
explicit runner(runner_backend backend);
runner(runner_backend backend, const runner_config &config);
run_result run_blocking(const program &program);
void exit_active_jobs();

Loading…
Cancel
Save