SMCOU72FKTPFNCDXFJAILVUWFE4DY33CJJE4436H5POKENFFDFFAC
7Z7HOZQ3JN5OW2WEU4NWE2XTUWAOHMWDQDJIKKO5KK2ZQTDNJGAAC
SGNXIOI4SO56F4YCGVMGZZO3AYXGPDL4FL75RDXAK5Y22IYWPPAQC
YJAHR4FUF7HYQXY4BAXJ6DSSFA4FQS6WCHO3XSYC6AVGD36WEU4AC
EFWN7JBV7YIHNMCA6ZGFRSHZIUQJ2EX57SWYGVT7ZRJCHPIM2R3QC
QT4FO2HPUPOS72Y5UTILN5AOV7S47AGG7V32CT24NA7TOVP76NAQC
ZWCTAZGLJZQNTYWTC2XQUKMILJF6JGDL5IND6QNYWK4FIGMLRFXAC
J5UVLXOK6EDIL5I7VKWH4V2QDS4DPD7FHRK6XBWSXFRQS4JKXFZQC
D5QIOJGPKQJIYBUCSC3MFJ3TXLPNZ2XMI37GXMFRVRFWWR2VMTFAC
KAZWI5G4DN2WUW7L2KWZR3D3QQJON4ISQYP7CRLC5HAOPIDYQGRQC
IK53RV4VGOHLCZGQCCIKPB45M3C7M7YMNBOJFBGZJ4LWIZNU4QNQC
F2YSY4BKQD4Y5XSSIOHAZVH5OQOEYDZJDXCY2JHHFPNRSUIUULSAC
UVMFS73TI6RARMAAGY2UVS5LCPZUKLQECXQQVER4F7S4BNUXQQ3AC
ODNCGFQ5FPKFI624BVMLW7PJ2EFJOR3TY66OCZM42UNNTWBCF2TQC
QL55ECJ6KMMBUOWQ6LKSOVN7L43CH4S6SPE2AQ3VX3KSGC32RP4AC
2M7J26V4WXJTOVN7TIOMOLUD2QA4LNTFLNOUTJWKL4XEGE6W2GKQC
N22GPKYTOLZLBGTGDATQDVZ4R5APZEAOIA7L32X4UXBH4XNI7MWAC
RBNQKATLSAKTGW2IRNB5CRV3SEH5F6E4BPVWX4BII7MH5TCIPINQC
use Data::Dump qw(dump);
sub nixMachines {
my ($c) = @_;
my $result = '';
foreach my $machine ($c->model("DB::BuildMachines")->all) {
if($machine->enabled) {
$result = $result . $machine->username . '@'. $machine->hostname . ' ';
foreach my $system ($machine->buildmachinesystemtypes) {
$result = $result . $system->system .',';
}
chop $result;
$result = $result . ' '. $machine->ssh_key . ' ' . $machine->maxconcurrent . ' '. $machine->speedfactor . ' ' . $machine->options . "\n";
}
}
return $result;
}
sub saveNixMachines {
my ($c) = @_;
die("File not writable: /etc/nix.machines") if ! -w "/etc/nix.machines" ;
$c->stash->{machines} = [$c->model('DB::BuildMachines')->search(
{},
{ order_by => "hostname"
, '+select' => ["(select bs.stoptime from buildsteps as bs where bs.machine = (me.username || '\@' || me.hostname) and not bs.stoptime is null order by bs.stoptime desc limit 1)"]
, '+as' => ['idle']
})];
$c->stash->{steps} = [ $c->model('DB::BuildSteps')->search(
{ 'me.busy' => 1, 'schedulingInfo.busy' => 1 },
{ join => [ 'schedulingInfo', 'build' ]
, order_by => [ 'machine', 'outpath' ]
} ) ];
}
sub machines : Chained('admin') PathPart('machines') Args(0) {
my ($self, $c) = @_;
$c->stash->{machines} = [$c->model('DB::BuildMachines')->search({}, {order_by => "hostname"})];
$c->stash->{systems} = [$c->model('DB::SystemTypes')->search({}, {select => ["system"], order_by => "system" })];
$c->stash->{nixMachines} = nixMachines($c);
$c->stash->{nixMachinesWritable} = (-e "/etc/nix.machines" && -w "/etc/nix.machines");
$c->stash->{template} = 'machines.tt';
}
sub machine : Chained('admin') PathPart('machine') CaptureArgs(1) {
my ($self, $c, $machineName) = @_;
requireAdmin($c);
my $machine = $c->model('DB::BuildMachines')->find($machineName)
or notFound($c, "Machine $machineName doesn't exist.");
$c->stash->{machine} = $machine;
sub machine_edit : Chained('machine') PathPart('edit') Args(0) {
my ($self, $c) = @_;
$c->stash->{template} = 'machine.tt';
$c->stash->{systemtypes} = [$c->model('DB::SystemTypes')->search({}, {order_by => "system"})];
$c->stash->{edit} = 1;
}
sub machine_edit_submit : Chained('machine') PathPart('submit') Args(0) {
my ($self, $c) = @_;
requirePost($c);
txn_do($c->model('DB')->schema, sub {
updateMachine($c, $c->stash->{machine}) ;
});
saveNixMachines($c);
$c->res->redirect("/admin/machines");
}
sub updateMachine {
my ($c, $machine) = @_;
my $hostname = trim $c->request->params->{"hostname"};
my $username = trim $c->request->params->{"username"};
my $maxconcurrent = trim $c->request->params->{"maxconcurrent"};
my $speedfactor = trim $c->request->params->{"speedfactor"};
my $ssh_key = trim $c->request->params->{"ssh_key"};
my $systems = $c->request->params->{"systems"} ;
error($c, "Invalid or empty username.") if $username eq "";
error($c, "Max concurrent builds should be an integer > 0.") if $maxconcurrent eq "" || ! $maxconcurrent =~ m/[0-9]+/;
error($c, "Speed factor should be an integer > 0.") if $speedfactor eq "" || ! $speedfactor =~ m/[0-9]+/;
error($c, "Invalid or empty SSH key.") if $ssh_key eq "";
$machine->update(
{ username => $username
, maxconcurrent => $maxconcurrent
, speedfactor => $speedfactor
, ssh_key => $ssh_key
});
$machine->buildmachinesystemtypes->delete_all;
if(ref($systems) eq 'ARRAY') {
for my $s (@$systems) {
$machine->buildmachinesystemtypes->create({ system => $s}) ;
}
} else {
$machine->buildmachinesystemtypes->create({ system => $systems}) ;
}
}
sub create_machine : Chained('admin') PathPart('create-machine') Args(0) {
my ($self, $c) = @_;
requireAdmin($c);
$c->stash->{template} = 'machine.tt';
$c->stash->{systemtypes} = [$c->model('DB::SystemTypes')->search({}, {order_by => "system"})];
$c->stash->{edit} = 1;
$c->stash->{create} = 1;
}
sub create_machine_submit : Chained('admin') PathPart('create-machine/submit') Args(0) {
my ($self, $c) = @_;
requireAdmin($c);
my $hostname = trim $c->request->params->{"hostname"};
error($c, "Invalid or empty hostname.") if $hostname eq "";
txn_do($c->model('DB')->schema, sub {
my $machine = $c->model('DB::BuildMachines')->create(
{ hostname => $hostname });
updateMachine($c, $machine);
});
$c->res->redirect("/admin/machines");
}
sub machine_delete : Chained('machine') PathPart('delete') Args(0) {
my ($self, $c) = @_;
requirePost($c);
txn_do($c->model('DB')->schema, sub {
$c->stash->{machine}->delete;
});
saveNixMachines($c);
$c->res->redirect("/admin/machines");
}
sub machine_enable : Chained('machine') PathPart('enable') Args(0) {
my ($self, $c) = @_;
$c->stash->{machine}->update({ enabled => 1});
saveNixMachines($c);
$c->res->redirect("/admin/machines");
}
sub machine_disable : Chained('machine') PathPart('disable') Args(0) {
my ($self, $c) = @_;
$c->stash->{machine}->update({ enabled => 0});
saveNixMachines($c);
$c->res->redirect("/admin/machines");
}
package Hydra::Schema::BuildMachineSystemTypes;
# Created by DBIx::Class::Schema::Loader
# DO NOT MODIFY THE FIRST PART OF THIS FILE
use strict;
use warnings;
use base 'DBIx::Class::Core';
=head1 NAME
Hydra::Schema::BuildMachineSystemTypes
=cut
__PACKAGE__->table("BuildMachineSystemTypes");
=head1 ACCESSORS
=head2 hostname
data_type: text
default_value: undef
is_foreign_key: 1
is_nullable: 0
size: undef
=head2 system
data_type: text
default_value: undef
is_nullable: 0
size: undef
=cut
__PACKAGE__->add_columns(
"hostname",
{
data_type => "text",
default_value => undef,
is_foreign_key => 1,
is_nullable => 0,
size => undef,
},
"system",
{
data_type => "text",
default_value => undef,
is_nullable => 0,
size => undef,
},
);
__PACKAGE__->set_primary_key("hostname", "system");
=head1 RELATIONS
=head2 hostname
Type: belongs_to
Related object: L<Hydra::Schema::BuildMachines>
=cut
__PACKAGE__->belongs_to(
"hostname",
"Hydra::Schema::BuildMachines",
{ hostname => "hostname" },
{},
);
# Created by DBIx::Class::Schema::Loader v0.05000 @ 2010-10-08 13:47:26
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:F/voQZLNESTotUOWRbg4WA
# You can replace this text with custom content, and it will be preserved on regeneration
1;
package Hydra::Schema::BuildMachines;
# Created by DBIx::Class::Schema::Loader
# DO NOT MODIFY THE FIRST PART OF THIS FILE
use strict;
use warnings;
use base 'DBIx::Class::Core';
=head1 NAME
Hydra::Schema::BuildMachines
=cut
__PACKAGE__->table("BuildMachines");
=head1 ACCESSORS
=head2 hostname
data_type: text
default_value: undef
is_nullable: 0
size: undef
=head2 username
data_type: text
default_value: undef
is_nullable: 0
size: undef
=head2 ssh_key
data_type: text
default_value: undef
is_nullable: 0
size: undef
=head2 options
data_type: text
default_value: undef
is_nullable: 0
size: undef
=head2 maxconcurrent
data_type: integer
default_value: 2
is_nullable: 0
size: undef
=head2 speedfactor
data_type: integer
default_value: 1
is_nullable: 0
size: undef
=head2 enabled
data_type: integer
default_value: 1
is_nullable: 0
size: undef
=cut
__PACKAGE__->add_columns(
"hostname",
{
data_type => "text",
default_value => undef,
is_nullable => 0,
size => undef,
},
"username",
{
data_type => "text",
default_value => undef,
is_nullable => 0,
size => undef,
},
"ssh_key",
{
data_type => "text",
default_value => undef,
is_nullable => 0,
size => undef,
},
"options",
{
data_type => "text",
default_value => undef,
is_nullable => 0,
size => undef,
},
"maxconcurrent",
{ data_type => "integer", default_value => 2, is_nullable => 0, size => undef },
"speedfactor",
{ data_type => "integer", default_value => 1, is_nullable => 0, size => undef },
"enabled",
{ data_type => "integer", default_value => 1, is_nullable => 0, size => undef },
);
__PACKAGE__->set_primary_key("hostname");
=head1 RELATIONS
=head2 buildmachinesystemtypes
Type: has_many
Related object: L<Hydra::Schema::BuildMachineSystemTypes>
=cut
__PACKAGE__->has_many(
"buildmachinesystemtypes",
"Hydra::Schema::BuildMachineSystemTypes",
{ "foreign.hostname" => "self.hostname" },
);
# Created by DBIx::Class::Schema::Loader v0.05000 @ 2010-10-11 12:58:16
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:gje+VA73Hghl7JXp+Fl8pw
# You can replace this text with custom content, and it will be preserved on regeneration
1;
[% FOREACH m IN machines %]
<table style="width: 40em;">
<thead>
<tr>
<th colspan="5">
[% IF m.enabled == 1 %]
[% INCLUDE maybeLink uri = c.uri_for('/admin/machine' m.hostname 'disable' ) content='-' %]
[% ELSE %]
[% INCLUDE maybeLink uri = c.uri_for('/admin/machine' m.hostname 'enable' ) content='+' %]
[% END %]
[% m.hostname %] <tt>[% FOREACH ms IN m.buildmachinesystemtypes %] [% ms.system %][% END %]</tt>
</th>
</tr>
</thead>
<tbody>
[% idle = 1 %]
[% FOREACH step IN steps %]
[% IF step.machine.match('@(.*)').0 == m.hostname %]
[% idle = 0 %]
<tr>
<td><tt>[% INCLUDE renderFullJobName project = step.build.project.name jobset = step.build.jobset.name job = step.build.job.name %]</tt></td>
<td><tt>[% step.system %]</tt></td>
<td><a href="[% c.uri_for('/build' step.build.id) %]">[% step.build.id %]</a></td>
<td><tt>[% step.outpath.match('-(.*)').0 %]</tt></td>
<td class='right'>[% INCLUDE renderDuration duration = curTime - step.starttime %] </td>
</tr>
[% END %]
[% END %]
[% IF idle == 1 %]
<tr><td colspan="5">Idle since [% INCLUDE renderDuration duration = curTime - m.get_column('idle') %]</td></tr>
[% END %]
</tbody>
</table>
[% END %]
[% BLOCK hydraStatus %]
<table class="tablesorter">
<thead>
<tr><th>Machine</th><th>Job</th><th>Type</th><th>Build</th><th>Step</th><th>What</th><th>Since</th></tr>
</thead>
<tbody>
[% FOREACH step IN steps %]
<tr>
<td><tt>[% IF step.machine; step.machine.match('@(.*)').0; ELSE; 'localhost'; END %]</tt></td>
<td><tt>[% INCLUDE renderFullJobName project = step.build.project.name jobset = step.build.jobset.name job = step.build.job.name %]</tt></td>
<td><tt>[% step.system %]</tt></td>
<td><a href="[% c.uri_for('/build' step.build.id) %]">[% step.build.id %]</a></td>
<td><a href="[% c.uri_for('/build' step.build.id 'nixlog' step.stepnr) %]">[% step.stepnr %]</a></td>
<td><tt>[% step.outpath.match('-(.*)').0 %]</tt></td>
<td class='right'>[% INCLUDE renderDuration duration = curTime - step.starttime %] </td>
</tr>
[% END %]
</tbody>
</table>
[% END %]
[% IF admin %]
[% WRAPPER makeSubMenu title="Admin" %]
[% INCLUDE makeLink
uri = c.uri_for(c.controller('Admin').action_for('machines'))
title = "Machines" %]
[% INCLUDE makeLink
uri = c.uri_for(c.controller('Admin').action_for('managenews'))
title = "News" %]
[% END %]
[% END %]
<table class="tablesorter">
<thead>
<tr><th>Machine</th><th>Type</th><th>Build</th><th>Step</th><th>What</th><th>Since</th></tr>
</thead>
<tbody>
[% FOREACH step IN steps %]
<tr>
<td><tt>[% IF step.machine; step.machine.match('@(.*)').0; ELSE; 'localhost'; END %]</tt></td>
<td><tt>[% step.system %]</tt></td>
<td><a href="[% c.uri_for('/build' step.build.id) %]">[% step.build.id %]</a></td>
<td><a href="[% c.uri_for('/build' step.build.id 'nixlog' step.stepnr) %]">[% step.stepnr %]</a></td>
<td><tt>[% step.outpath.match('-(.*)').0 %]</tt></td>
<td class='right'>[% INCLUDE renderDuration duration = curTime - step.starttime %] </td>
</tr>
[% END %]
</tbody>
</table>
[% INCLUDE hydraStatus %]