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 FILEuse strict;use warnings;use base 'DBIx::Class::Core';=head1 NAMEHydra::Schema::BuildMachineSystemTypes=cut__PACKAGE__->table("BuildMachineSystemTypes");=head1 ACCESSORS=head2 hostnamedata_type: textdefault_value: undefis_foreign_key: 1is_nullable: 0size: undef=head2 systemdata_type: textdefault_value: undefis_nullable: 0size: 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 hostnameType: belongs_toRelated 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 regeneration1;
package Hydra::Schema::BuildMachines;# Created by DBIx::Class::Schema::Loader# DO NOT MODIFY THE FIRST PART OF THIS FILEuse strict;use warnings;use base 'DBIx::Class::Core';=head1 NAMEHydra::Schema::BuildMachines=cut__PACKAGE__->table("BuildMachines");=head1 ACCESSORS=head2 hostnamedata_type: textdefault_value: undefis_nullable: 0size: undef=head2 usernamedata_type: textdefault_value: undefis_nullable: 0size: undef=head2 ssh_keydata_type: textdefault_value: undefis_nullable: 0size: undef=head2 optionsdata_type: textdefault_value: undefis_nullable: 0size: undef=head2 maxconcurrentdata_type: integerdefault_value: 2is_nullable: 0size: undef=head2 speedfactordata_type: integerdefault_value: 1is_nullable: 0size: undef=head2 enableddata_type: integerdefault_value: 1is_nullable: 0size: 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 buildmachinesystemtypesType: has_manyRelated 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 regeneration1;
[% 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 makeLinkuri = c.uri_for(c.controller('Admin').action_for('machines'))title = "Machines" %][% INCLUDE makeLinkuri = 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 %]