1
0
mirror of https://github.com/ohwgiles/laminar.git synced 2024-10-27 20:34:20 +00:00

support for job and node tags

This commit is contained in:
Oliver Giles 2015-09-24 22:02:11 +02:00
parent 79c3ee5fcb
commit 0df97e95fd
6 changed files with 72 additions and 31 deletions

View File

@ -82,7 +82,7 @@ generate_compressed_bins(${CMAKE_BINARY_DIR} js/angular.min.js js/angular-route.
## Server
add_executable(laminard src/database.cpp src/main.cpp src/server.cpp src/laminar.cpp
src/conf.cpp src/resources.cpp src/run.cpp src/node.cpp laminar.capnp.c++ ${COMPRESSED_BINS})
src/conf.cpp src/resources.cpp src/run.cpp laminar.capnp.c++ ${COMPRESSED_BINS})
# TODO: some alternative to boost::filesystem?
target_link_libraries(laminard capnp capnp-rpc kj-async kj boost_filesystem boost_system sqlite3)

View File

@ -310,6 +310,17 @@ bool Laminar::loadConfiguration() {
Node node;
node.name = it.path().filename().string();
node.numExecutors = conf.get<int>("EXECUTORS", 6);
std::string tags = conf.get<std::string>("TAGS");
if(!tags.empty()) {
std::istringstream iss(tags);
std::set<std::string> tagList;
std::copy(std::istream_iterator<std::string>(iss),
std::istream_iterator<std::string>(),
std::inserter(tagList, tagList.begin()));
node.tags = tagList;
}
nm.emplace(node.name, std::move(node));
}
}
@ -324,6 +335,32 @@ bool Laminar::loadConfiguration() {
nodes = nm;
fs::path jobsDir = fs::path(homeDir)/"cfg"/"jobs";
if(fs::is_directory(jobsDir)) {
fs::directory_iterator dit(jobsDir);
for(fs::directory_entry& it : dit) {
if(!fs::is_directory(it.status()))
continue;
fs::directory_entry config(it.path()/"config");
if(!fs::is_regular_file(config.status()))
continue;
StringMap conf = parseConfFile(config.path().string().c_str());
std::string tags = conf.get<std::string>("TAGS");
if(!tags.empty()) {
std::istringstream iss(tags);
std::set<std::string> tagList;
std::copy(std::istream_iterator<std::string>(iss),
std::istream_iterator<std::string>(),
std::inserter(tagList, tagList.begin()));
jobTags[it.path().filename().string()] = tagList;
}
}
}
return true;
}
@ -425,6 +462,29 @@ void Laminar::reapAdvance() {
assignNewJobs();
}
bool Laminar::nodeCanQueue(const Node& node, const Run& run) const {
// if a node is too busy, it can't take the job
if(node.busyExecutors >= node.numExecutors)
return false;
auto it = jobTags.find(run.name);
// if both nodes have no tags, it's OK
if(it == jobTags.end() && node.tags.size() == 0)
return true;
// but if just one of them does, don't allow the build
if(it == jobTags.end() || node.tags.size() == 0)
return false;
// in other cases, allow the build if they have a tag in common
for(const std::string& tag : it->second) {
if(node.tags.find(tag) != node.tags.end())
return true;
}
return false;
}
void Laminar::assignNewJobs() {
auto it = queuedJobs.begin();
while(it != queuedJobs.end()) {
@ -432,7 +492,7 @@ void Laminar::assignNewJobs() {
for(auto& sn : nodes) {
Node& node = sn.second;
std::shared_ptr<Run> run = *it;
if(node.queue(*run)) {
if(nodeCanQueue(node, *run)) {
node.busyExecutors++;
run->node = &node;
run->startedAt = time(0);

View File

@ -61,6 +61,7 @@ private:
void assignNewJobs();
bool stepRun(std::shared_ptr<Run> run);
void runFinished(const Run*);
bool nodeCanQueue(const Node&, const Run&) const;
std::list<std::shared_ptr<Run>> queuedJobs;
@ -79,6 +80,8 @@ private:
std::unordered_map<std::string, uint> buildNums;
std::unordered_map<std::string, std::set<std::string>> jobTags;
RunSet activeJobs;
Database* db;
Server* srv;

View File

@ -1,25 +0,0 @@
///
/// Copyright 2015 Oliver Giles
///
/// This file is part of Laminar
///
/// Laminar is free software: you can redistribute it and/or modify
/// it under the terms of the GNU General Public License as published by
/// the Free Software Foundation, either version 3 of the License, or
/// (at your option) any later version.
///
/// Laminar is distributed in the hope that it will be useful,
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
/// GNU General Public License for more details.
///
/// You should have received a copy of the GNU General Public License
/// along with Laminar. If not, see <http://www.gnu.org/licenses/>
///
#include "node.h"
bool Node::queue(const Run& run) {
// later this could check if the given run is allowed to run
// on this node, for example if the run's tags match the node's tags
return busyExecutors < numExecutors;
}

View File

@ -16,10 +16,11 @@
/// You should have received a copy of the GNU General Public License
/// along with Laminar. If not, see <http://www.gnu.org/licenses/>
///
#ifndef NODE_H
#define NODE_H
#ifndef _LAMINAR_NODE_H_
#define _LAMINAR_NODE_H_
#include <string>
#include <set>
class Run;
@ -32,10 +33,11 @@ public:
std::string name;
int numExecutors;
int busyExecutors = 0;
std::set<std::string> tags;
// Attempts to queue the given run to this node. Returns true if succeeded.
bool queue(const Run& run);
};
#endif // NODE_H
#endif // _LAMINAR_NODE_H_

View File

@ -91,6 +91,7 @@ bool Run::step() {
setenv("PATH", PATH.c_str(), true);
setenv("lBuildNum", buildNum.c_str(), true);
setenv("lJobName", name.c_str(), true);
if(!node->name.empty())
setenv("lNode", node->name.c_str(), true);
setenv("lResult", to_string(result).c_str(), true);
setenv("lLastResult", to_string(lastResult).c_str(), true);