#!/usr/bin/python
+from __future__ import division
+
import datetime
import hashlib
import logging
return sorted(arches)
def get_load(self):
- slots = 1
- running_jobs = 0
-
- for builder in self.get_all():
- if not builder.state == "online":
- continue
+ res1 = self.db.get("SELECT SUM(max_jobs) AS max_jobs FROM builders \
+ WHERE status = 'enabled'")
+ if not res1:
+ return 0
- slots += builder.max_jobs
- running_jobs += len(builder.get_active_jobs(uploads=False))
+ res2 = self.db.get("SELECT COUNT(*) AS count FROM jobs \
+ WHERE state = 'dispatching' OR state = 'running' OR state = 'uploading'")
+ if not res2:
+ return 0
- return int(running_jobs * 100 / slots)
+ return (res2.count * 100 / res1.max_jobs)
def get_history(self, limit=None, offset=None, builder=None, user=None):
query = "SELECT * FROM builders_history"
@property
def data(self):
if self._data is None:
- self._data = \
- self.db.get("SELECT *, NOW() - time_keepalive AS updated \
- FROM builders WHERE id = %s", self.id)
+ self._data = self.db.get("SELECT * FROM builders WHERE id = %s", self.id)
+ assert self._data
return self._data
if self.data.time_keepalive is None:
return "offline"
- if self.data.updated >= 5*60:
- return "offline"
+ #if self.data.updated >= 5*60:
+ # return "offline"
return "online"
+ @property
+ def active_jobs(self):
+ jobs = self.get_active_jobs()
+
+ return len(jobs)
+
def get_active_jobs(self, uploads=True):
if self._active_jobs is None:
self._active_jobs = \
</li>
</ul>
+ <div class="page-header">
+ <h2>{{ _("Builder") }}: {{ builder.name }}</h2>
+ </div>
+
{% if builder.overload %}
- <div class="alert alert-warning">
- <strong>{{ _("Warning") }}</strong>! {{ _("This builder is overloaded.") }}
- {{ _("That means it will take no additional jobs although it has not reached its threshold.") }}
- {{ _("If the load decreases new jobs will be added automatically.") }}
+ <div class="alert alert-block alert-warning">
+ <h4 class="alert-heading">{{ _("Warning") }}!</h4>
+ {{ _("This builder is overloaded.") }}
+ {{ _("That means it will not take any additional jobs although it has not reached its threshold of running jobs, yet.") }}
+ {{ _("New jobs will be started automatically after the load decreased.") }}
</div>
{% end %}
- <div class="page-header">
- <h1>{{ _("Builder") }}: {{ builder.name }}</h1>
- </div>
-
<div class="row">
- <div class="span4 offset1">
- <table class="table">
+ <div class="span5">
+ <table class="table table-striped table-hover">
<tbody>
<tr>
<td>{{ _("State") }}</td>
{% end %}
</div>
- <div class="span6">
- <table class="table">
+ <div class="span7">
+ <table class="table table-striped table-hover">
<tbody>
<tr>
<td>{{ _("Pakfire version") }}</td>
</div>
{% if current_user and current_user.has_perm("maintain_builders") %}
- <div class="row">
- <div class="span10 offset1">
- <div class="btn-toolbar">
- <div class="btn-group pull-right">
- {% if builder.enabled %}
- <a class="btn btn-danger" href="/builder/{{ builder.name }}/disable">
- {{ _("Disable") }}
- </a>
- {% else %}
- <a class="btn btn-success" href="/builder/{{ builder.name }}/enable">
- {{ _("Enable") }}
- </a>
- {% end %}
-
- <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
- {{ _("Action") }}
- <span class="caret"></span>
- </a>
- <ul class="dropdown-menu">
- <li>
- <a href="/builder/{{ builder.name }}/edit">
- <i class="icon-edit"></i>
- {{ _("Edit settings") }}
- </a>
- </li>
-
- {% if not builder.enabled %}
- <li>
- <a href="/builder/{{ builder.name }}/renew">
- <i class="icon-refresh"></i>
- {{ _("Renew passphrase") }}
- </a>
- </li>
- {% end %}
+ <hr>
- <li class="divider"></li>
- <li>
- <a href="/builder/{{ builder.name }}/delete">
- <i class="icon-trash"></i>
- {{ _("Delete builder") }}
- </a>
- </li>
- </ul>
- </div>
- </div>
- </div>
- </div>
- {% end %}
+ <div class="btn-toolbar ac">
+ {% if builder.enabled %}
+ <a class="btn btn-danger" href="/builder/{{ builder.name }}/disable">
+ {{ _("Disable builder") }}
+ </a>
+ {% else %}
+ <a class="btn btn-success" href="/builder/{{ builder.name }}/enable">
+ {{ _("Enable builder") }}
+ </a>
+ {% end %}
+
+ <a class="btn" href="/builder/{{ builder.name }}/edit">
+ <i class="icon-edit"></i>
+ {{ _("Edit builder") }}
+ </a>
+
+ {% if not builder.enabled %}
+ <a class="btn" href="/builder/{{ builder.name }}/renew">
+ <i class="icon-refresh"></i>
+ {{ _("Renew passphrase") }}
+ </a>
+ {% end %}
- {% if builder.get_active_jobs() %}
- <div class="row">
- <div class="span10 offset1">
- <h2>{{ _("Currently running builds on this host") }}</h2>
- {% module JobsList(builder.get_active_jobs()) %}
- </div>
+ <a class="btn" href="/builder/{{ builder.name }}/delete">
+ <i class="icon-trash"></i>
+ {{ _("Delete builder") }}
+ </a>
</div>
{% end %}
- <div class="row">
- <div class="span10 offset1">
- <h2>{{ _("Log") }}</h2>
- {% module Log(builder.get_history(limit=20)) %}
- </div>
- </div>
+ <hr>
+
+ <h3>{{ _("Log") }}</h3>
+ {% module Log(builder.get_history(limit=5)) %}
{% end block %}
-{% extends "base-form1.html" %}
+{% extends "base.html" %}
-{% block title %}{{ _("Edit builder %s") % builder.hostname }}{% end block %}
+{% block title %}{{ _("Manage builder %s") % builder.hostname }}{% end block %}
{% block body %}
<ul class="breadcrumb">
</ul>
<div class="page-header">
- <h1>{{ _("Manage builder:") }} {{ builder.hostname }}</h1>
+ <h2>{{ _("Builder: %s") % builder.hostname }} <small>{{ _("Manage") }}</small></h2>
</div>
- <div class="row">
- <div class="span8">
- <form class="form-horizontal" method="POST" action="">
- {% raw xsrf_form_html() %}
- <fieldset>
- <div class="control-group">
- <label class="control-label">{{ _("Hostname") }}</label>
- <div class="controls">
- <span class="input-xlarge uneditable-input">{{ builder.hostname }}</span>
- <p class="help-block">
- {{ _("The hostname cannot be changed.") }}
- </p>
- </div>
- </div>
+ <form class="form-horizontal" method="POST" action="">
+ {% raw xsrf_form_html() %}
+ <fieldset>
+ <div class="control-group">
+ <label class="control-label">{{ _("Hostname") }}</label>
+ <div class="controls">
+ <span class="input-xlarge uneditable-input">{{ builder.hostname }}</span>
+ <p class="help-block">
+ {{ _("The hostname cannot be changed.") }}
+ </p>
+ </div>
+ </div>
- <div class="control-group">
- <label class="control-label" for="enabled">{{ _("Enabled") }}</label>
- <div class="controls">
- <label class="checkbox">
- <input type="checkbox" id="enabled" name="enabled" {% if builder.enabled %}checked="checked"{% end %}>
- {{ _("The builder must be enabled in order to process build jobs.") }}
- </label>
- </div>
- </div>
- </fieldset>
+ <div class="control-group">
+ <label class="control-label" for="enabled">{{ _("Enabled") }}</label>
+ <div class="controls">
+ <label class="checkbox">
+ <input type="checkbox" id="enabled" name="enabled" {% if builder.enabled %}checked="checked"{% end %}>
+ {{ _("The builder must be enabled in order to process build jobs.") }}
+ </label>
+ </div>
+ </div>
+ </fieldset>
- <fieldset>
- <legend>{{ _("Build job settings") }}</legend>
+ <fieldset>
+ <legend>{{ _("Build job settings") }}</legend>
- <div class="control-group">
- <label class="control-label" for="max_jobs">{{ _("Maximum number of parallel build jobs") }}</label>
- <div class="controls">
- <select id="max_jobs" name="max_jobs">
- {% for i in range(1, (2 * builder.cpu_count) + 1) %}
- <option value="{{ i }}" {% if i == builder.max_jobs %}selected="selected"{% end %}>{{ i }}</option>
- {% end %}
- </select>
+ <div class="control-group">
+ <label class="control-label" for="max_jobs">{{ _("Maximum number of parallel build jobs") }}</label>
+ <div class="controls">
+ <select id="max_jobs" name="max_jobs">
+ {% for i in range(1, (2 * builder.cpu_count) + 1) %}
+ <option value="{{ i }}" {% if i == builder.max_jobs %}selected="selected"{% end %}>{{ i }}</option>
+ {% end %}
+ </select>
- <p class="help-block">
- {{ _("This is the number of build jobs that are started in parallel.") }}
- </p>
- </div>
- </div>
+ <p class="help-block">
+ {{ _("This is the number of build jobs that are started in parallel.") }}
+ </p>
+ </div>
+ </div>
- <div class="control-group">
- <div class="controls">
- <label class="checkbox">
- <input type="checkbox" id="build_release" name="build_release" {%if builder.build_release %}checked="checked"{% end %}>
- {{ _("Authorized to build release builds.") }}
- </label>
- </div>
- </div>
+ <div class="control-group">
+ <div class="controls">
+ <label class="checkbox">
+ <input type="checkbox" id="build_release" name="build_release" {%if builder.build_release %}checked="checked"{% end %}>
+ {{ _("Authorized to build release builds.") }}
+ </label>
+ </div>
+ </div>
- <div class="control-group">
- <div class="controls">
- <label class="checkbox">
- <input type="checkbox" id="build_scratch" name="build_scratch" {%if builder.build_scratch %}checked="checked"{% end %}>
- {{ _("Authorized to build scratch builds.") }}
- </label>
- </div>
- </div>
+ <div class="control-group">
+ <div class="controls">
+ <label class="checkbox">
+ <input type="checkbox" id="build_scratch" name="build_scratch" {%if builder.build_scratch %}checked="checked"{% end %}>
+ {{ _("Authorized to build scratch builds.") }}
+ </label>
+ </div>
+ </div>
- <div class="control-group">
- <div class="controls">
- <label class="checkbox">
- <input type="checkbox" id="build_test" name="build_test" {%if builder.build_test %}checked="checked"{% end %}>
- {{ _("Authorized to build test builds.") }}
- </label>
- </div>
- </div>
+ <div class="control-group">
+ <div class="controls">
+ <label class="checkbox">
+ <input type="checkbox" id="build_test" name="build_test" {%if builder.build_test %}checked="checked"{% end %}>
+ {{ _("Authorized to build test builds.") }}
+ </label>
+ </div>
+ </div>
- <div class="control-group">
- <label class="control-label" for="arches">{{ _("Enable host for these architectures") }}</label>
- <div class="controls">
- <select multiple="multiple" id="arches" name="arches">
- {% for arch in builder.get_arches() %}
- <option value="{{ arch.name }}" {% if arch in builder.arches %}selected="selected"{% end %}>{{ arch.name }}</option>
- {% end %}
- </select>
+ <div class="control-group">
+ <label class="control-label" for="arches">{{ _("Enable host for these architectures") }}</label>
+ <div class="controls">
+ <select multiple="multiple" id="arches" name="arches">
+ {% for arch in builder.get_arches() %}
+ <option value="{{ arch.name }}" {% if arch in builder.arches %}selected="selected"{% end %}>{{ arch.name }}</option>
+ {% end %}
+ </select>
- <p class="help-block">
- {{ _("Select or deselect the architectures, this builder should build or not.") }}
- </p>
- </div>
- </div>
+ <p class="help-block">
+ {{ _("Select or deselect the architectures, this builder should build or not.") }}
+ </p>
+ </div>
+ </div>
- <div class="form-actions">
- <button type="submit" class="btn btn-primary">{{ _("Save changes") }}</button>
- </div>
- </fieldset>
- </form>
- </div>
- </div>
+ <div class="form-actions">
+ <button type="submit" class="btn btn-primary">{{ _("Save changes") }}</button>
+ </div>
+ </fieldset>
+ </form>
{% end block %}
{% extends "base.html" %}
-{% block title %}{{ _("Build servers") }}{% end block %}
+{% block title %}{{ _("Builders") }}{% end block %}
{% block body %}
<ul class="breadcrumb">
</ul>
<div class="page-header">
- <h1>{{ _("Build servers") }}</h1>
+ <h2>{{ _("Builders") }}</h2>
</div>
- <div class="row">
- <div class="span12">
- <p>
- {{ _("Builders are those, that do all the hard work.") }}
- {{ _("Build jobs are scheduled to these hosts that they process and send back the result.") }}
- </p>
- </div>
- </div>
+ {% module BuildersLoad() %}
+
+ <hr>
<div class="row">
- <div class="span6 offset3">
+ <div class="span12">
<table class="table table-striped table-hover">
<thead>
<tr>
<th> </th>
<th>{{ _("Hostname") }}</th>
- <th>{{ _("Load") }}</th>
- <th>{{ _("Running jobs") }}</th>
+ <th>{{ _("Architectures") }}</th>
+ <th>{{ _("Jobs") }}</th>
</tr>
</thead>
<tbody>
{% for builder in builders %}
<tr>
- <td>
- <img src="{{ static_url("images/icons/builder-%s.png" % builder.state.lower()) }}"
- alt="{{ _("State %s") % builder.state }}" />
+ <td class="lead">
+ {% if builder.state == "disabled" %}
+ <i class="icon-stop text-error"></i>
+ {% elif builder.state == "offline" %}
+ <i class="icon-pause text-warning"></i>
+ {% elif builder.state == "online" %}
+ <i class="icon-play text-success"></i>
+ {% end %}
</td>
<td>
<a href="/builder/{{ builder.name }}">{{ builder.name }}</a>
{% if builder.overload %}
- <span class="label label-important">{{ _("Overload") }}</span>
+ <span class="label label-important pull-right">{{ _("Overload") }}</span>
{% end %}
- <br />
- {{ locale.list([a.name for a in builder.arches]) }}
+ <br>
+ {{ builder.cpu_model or _("Unknown CPU") }} - {{ format_size(builder.memory) }}
</td>
<td>
- {{ builder.load1 or _("N/A") }}
+ {% if builder.arches %}
+ {{ locale.list([a.name for a in builder.arches]) }}
+ {% else %}
+ {{ _("N/A") }}
+ {% end %}
</td>
<td>
- {{ len(builder.get_active_jobs()) }}/{{ builder.max_jobs }}
+ <p class="{% if builder.active_jobs == 0 %}text-success{% elif builder.active_jobs >= builder.max_jobs %}text-error{% else %}text-warning{% end %}">
+ {{ len(builder.get_active_jobs()) }}/{{ builder.max_jobs }}
+ </p>
</td>
</tr>
{% end %}
-
- <tr>
- <td colspan="3">
- <div class="progress progress-info">
- <div class="bar" style="width: {{ load }}%;"></div>
- </div>
- </td>
- <td>
- {% if current_user and current_user.is_admin() %}
- <div class="btn-group pull-right">
- <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
- {{ _("Action") }}
- <span class="caret"></span>
- </a>
- <ul class="dropdown-menu">
- <li>
- <a href="/builder/new">{{ _("Create new builder") }}</a>
- </li>
- </ul>
- </div>
- {% end %}
- </td>
- </tr>
</tbody>
</table>
- </div>
- </div>
- <div class="row">
- <div class="span12">
- {% if log %}
- <h2>{{ _("Log") }}</h2>
- {% module Log(log) %}
+ {% if current_user and current_user.is_admin() %}
+ <div class="btn-group pull-right">
+ <a class="btn" href="/builder/new">{{ _("Create new builder") }}</a>
+ </div>
{% end %}
</div>
</div>
"LogEntry" : LogEntryModule,
"LogEntryComment" : LogEntryCommentModule,
+ # Builders
+ "BuildersLoad" : BuildersLoadModule,
+
"BuildHeadline" : BuildHeadlineModule,
"BuildStateWarnings" : BuildStateWarningsModule,
class BuilderListHandler(BaseHandler):
def get(self):
builders = self.pakfire.builders.get_all()
- load = self.pakfire.builders.get_load()
- log = self.pakfire.builders.get_history(limit=10)
-
- self.render("builder-list.html", builders=builders, load=load, log=log)
+ self.render("builder-list.html", builders=builders)
class BuilderDetailHandler(BaseHandler):
prefix=prefix, build=build, pkg=build.pkg, short=short, shorter=shorter)
+class BuildersLoadModule(UIModule):
+ def render(self):
+ load = self.pakfire.builders.get_load()
+
+ return self.render_string("modules/builders/load.html", load=load)
+
+
class BugsTableModule(UIModule):
def render(self, pkg, bugs):
return self.render_string("modules/bugs-table.html",