1#!/usr/bin/env perl
2
3use strict;
4use warnings;
5
6use FindBin;
7FindBin::again();
8use Path::Class 'dir';
9
10BEGIN {
11  # stuff useful locations into @INC
12  unshift @INC,
13    dir($FindBin::RealBin)->parent->subdir('lib')->stringify,
14    dir($FindBin::RealBin, 'lib')->stringify;
15
16  unshift @INC,
17    split m/:/, ($ENV{NETDISCO_INC} || '');
18}
19
20use App::Netdisco;
21use Dancer qw/:moose :script/;
22
23BEGIN {
24  warning sprintf "App::Netdisco %s backend", ($App::Netdisco::VERSION || 'HEAD');
25
26  # this can take a few seconds - only do it once
27  use Net::Domain 'hostfqdn';
28  info 'resolving backend hostname...';
29  setting('workers')->{'BACKEND'} ||= (hostfqdn || 'fqdn-undefined');
30}
31
32use App::Netdisco::Util::MCE; # set $0 and parse maxworkers
33use NetAddr::IP::Lite ':lower'; # to quench AF_INET6 symbol errors
34use Role::Tiny::With;
35
36use MCE::Signal '-setpgrp';
37use MCE::Flow Sereal => 1;
38use MCE::Queue;
39
40# set temporary MCE files' location in home directory
41my $home = ($ENV{NETDISCO_HOME} || $ENV{HOME});
42my $tmp_dir = ($ENV{NETDISCO_TEMP} || dir($home, 'tmp'));
43mkdir $tmp_dir if ! -d $tmp_dir;
44
45# process-table text
46prctl 'nd2: master';
47
48# shared local job queue
49my $queue = MCE::Queue->new;
50
51# support a scheduler-only node
52setting('workers')->{'no_manager'} = 1
53  if setting('workers')->{tasks} eq '0';
54
55# MCE::Util has a limit of ncpu if AUTO is used in max_workers,
56# so we parse the field ourselves.
57my $max_workers = parse_max_workers( setting('workers')->{tasks} ) || 0;
58
59mce_flow {
60  task_name => [qw/ scheduler manager poller /],
61  max_workers => [ 1, 1, $max_workers ],
62  tmp_dir => $tmp_dir,
63  on_post_exit => sub { MCE->restart_worker },
64}, _mk_wkr('Scheduler'), _mk_wkr('Manager'), _mk_wkr('Poller');
65
66sub _mk_wkr {
67  my $role = shift;
68  return sub {
69    my $self = shift;
70    $self->{queue} = $queue;
71
72    prctl sprintf 'nd2: #%s %s: init', MCE->wid, lc($role);
73    info sprintf 'applying role %s to worker %s', $role, MCE->wid;
74
75    # post-fork, become manager, scheduler, poller, etc
76    Role::Tiny->apply_roles_to_object(
77      $self => "App::Netdisco::Backend::Role::$role");
78
79    $self->worker_begin if $self->can('worker_begin');
80    $self->worker_body;
81  };
82}
83
84=head1 NAME
85
86netdisco-backend-fg - Job Control for Netdisco
87
88=head1 SEE ALSO
89
90=over 4
91
92=item *
93
94L<App::Netdisco>
95
96=back
97
98=cut
99