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:
parent
79c3ee5fcb
commit
0df97e95fd
@ -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)
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
25
src/node.cpp
25
src/node.cpp
@ -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;
|
||||
}
|
@ -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_
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user