File Coverage

blib/lib/FusionInventory/Agent.pm
Criterion Covered Total %
statement 232 396 58.5
branch 50 154 32.4
condition 12 54 22.2
subroutine 36 49 73.4
pod 7 11 63.6
total 337 664 50.7


line stmt bran cond sub pod time code
1             package FusionInventory::Agent;
2              
3 30     30   356461 use strict;
  30         48  
  30         765  
4 30     30   112 use warnings;
  30         42  
  30         697  
5              
6 30     30   96 use Cwd;
  30         114  
  30         1843  
7 30     30   494 use English qw(-no_match_vars);
  30         2477  
  30         169  
8 30     30   11128 use UNIVERSAL::require;
  30         3507  
  30         176  
9 30     30   649 use File::Glob;
  30         40  
  30         1417  
10 30     30   7723 use IO::Handle;
  30         73340  
  30         1225  
11 30     30   8863 use POSIX ":sys_wait_h"; # WNOHANG
  30         91738  
  30         272  
12 30     30   23515 use Storable 'dclone';
  30         10668  
  30         1443  
13              
14 30     30   10414 use FusionInventory::Agent::Config;
  30         60  
  30         296  
15 30     30   11537 use FusionInventory::Agent::HTTP::Client::OCS;
  30         60  
  30         330  
16 30     30   2401 use FusionInventory::Agent::Logger;
  30         34  
  30         1519  
17 30     30   10502 use FusionInventory::Agent::Storage;
  30         59  
  30         263  
18 30     30   10532 use FusionInventory::Agent::Target::Local;
  30         48  
  30         275  
19 30     30   10436 use FusionInventory::Agent::Target::Server;
  30         41  
  30         254  
20 30     30   585 use FusionInventory::Agent::Tools;
  30         33  
  30         3363  
21 30     30   10438 use FusionInventory::Agent::Tools::Hostname;
  30         47  
  30         1248  
22 30     30   10233 use FusionInventory::Agent::XML::Query::Prolog;
  30         49  
  30         237  
23              
24             our $VERSION = '2.3.18';
25             our $VERSION_STRING = _versionString($VERSION);
26             our $AGENT_STRING = "FusionInventory-Agent_v$VERSION";
27             our $CONTINUE_WORD = "...";
28              
29             sub _versionString {
30 30     30   51 my ($VERSION) = @_;
31              
32 30         65 my $string = "FusionInventory Agent ($VERSION)";
33 30 50       129 if ($VERSION =~ /^\d\.\d\.99(\d\d)/) {
34 0         0 $string .= " **THIS IS A DEVELOPMENT RELEASE **";
35             }
36              
37 30         59 return $string;
38             }
39              
40             sub new {
41 1     1 1 955 my ($class, %params) = @_;
42              
43             my $self = {
44             status => 'unknown',
45             confdir => $params{confdir},
46             datadir => $params{datadir},
47             libdir => $params{libdir},
48             vardir => $params{vardir},
49             sigterm => $params{sigterm},
50 1         10 targets => [],
51             tasks => []
52             };
53 1         2 bless $self, $class;
54              
55 1         2 return $self;
56             }
57              
58             sub init {
59 1     1 1 2129 my ($self, %params) = @_;
60              
61             my $config = FusionInventory::Agent::Config->new(
62             confdir => $self->{confdir},
63             options => $params{options},
64 1         13 );
65 1         2 $self->{config} = $config;
66              
67             my $verbosity = $config->{debug} && $config->{debug} == 1 ? LOG_DEBUG :
68 1 50 33     23 $config->{debug} && $config->{debug} == 2 ? LOG_DEBUG2 :
    50 33        
69             LOG_INFO ;
70              
71             my $logger = FusionInventory::Agent::Logger->new(
72             config => $config,
73             backends => $config->{logger},
74 1         9 verbosity => $verbosity
75             );
76 1         2 $self->{logger} = $logger;
77              
78 1         3 $logger->debug("Configuration directory: $self->{confdir}");
79 1         3 $logger->debug("Data directory: $self->{datadir}");
80 1         3 $logger->debug("Storage directory: $self->{vardir}");
81 1         4 $logger->debug("Lib directory: $self->{libdir}");
82              
83             $self->{storage} = FusionInventory::Agent::Storage->new(
84             logger => $logger,
85             directory => $self->{vardir}
86 1         9 );
87              
88             # handle persistent state
89 1         4 $self->_loadState();
90              
91 1 50       5 $self->{deviceid} = _computeDeviceId() if !$self->{deviceid};
92              
93 1         4 $self->_saveState();
94              
95 1         157 $self->_createTargets();
96              
97 1 50       4 if (!$self->getTargets()) {
98 0         0 $logger->error("No target defined, aborting");
99 0         0 exit 1;
100             }
101              
102             # compute list of allowed tasks
103 1         4 my %available = $self->getAvailableTasks(disabledTasks => $config->{'no-task'});
104 1         4 my @tasks = keys %available;
105 1         4 my @plannedTasks = $self->computeTaskExecutionPlan(\@tasks);
106 1         4 $self->{tasksExecutionPlan} = \@plannedTasks;
107              
108 1         4 my %available_lc = map { (lc $_) => $_ } keys %available;
  3         6  
109 1 50       4 if (!@tasks) {
110 0         0 $logger->error("No tasks available, aborting");
111 0         0 exit 1;
112             }
113              
114 1         4 $logger->debug("Available tasks:");
115 1         3 foreach my $task (keys %available) {
116 3         7 $logger->debug("- $task: $available{$task}");
117             }
118 1         3 $logger->debug("Planned tasks:");
119 1         1 foreach my $task (@{$self->{tasksExecutionPlan}}) {
  1         2  
120 3         3 my $task_lc = lc $task;
121 3         8 $logger->debug("- $task: " . $available{$available_lc{$task_lc}});
122             }
123              
124 1         2 $self->{tasks} = \@tasks;
125              
126 1 50       3 if ($config->{daemon}) {
127 0         0 $self->_createDaemon();
128             }
129              
130             # create HTTP interface
131 1 50 33     7 if (($config->{daemon} || $config->{service}) && !$config->{'no-httpd'}) {
      33        
132 0         0 $self->_createHttpInterface();
133             }
134              
135             # install signal handler to handle graceful exit
136 1         4 $self->_installSignalHandlers();
137              
138             $self->{logger}->info("FusionInventory Agent starting")
139 1 50 33     5 if $self->{config}->{daemon} || $self->{config}->{service};
140              
141             $self->{logger}->info("Options 'no-task' and 'tasks' are both used. Be careful that 'no-task' always excludes tasks.")
142 1 50 33     3 if ($self->{config}->isParamArrayAndFilled('no-task') && $self->{config}->isParamArrayAndFilled('tasks'));
143              
144 1         4 $self->resetLastConfigLoad();
145             }
146              
147             sub reinit {
148 1     1 0 914 my ($self) = @_;
149              
150 1         4 $self->{logger}->debug('agent reinit');
151              
152 1         6 $self->{config}->reloadFromInputAndBackend($self->{confdir});
153              
154 1         2 my $config = $self->{config};
155              
156             my $verbosity = $config->{debug} && $config->{debug} == 1 ? LOG_DEBUG :
157 1 50 33     7 $config->{debug} && $config->{debug} == 2 ? LOG_DEBUG2 :
    50 33        
158             LOG_INFO ;
159              
160 1         2 my $logger = undef;
161 1 50       3 if (! defined($self->{logger})) {
162             $logger = FusionInventory::Agent::Logger->new(
163             config => $config,
164             backends => $config->{logger},
165 0         0 verbosity => $verbosity
166             );
167 0         0 $self->{logger} = $logger;
168             } else {
169 1         1 $logger = $self->{logger};
170             }
171              
172 1         5 $logger->debug("Configuration directory: $self->{confdir}");
173 1         4 $logger->debug("Data directory: $self->{datadir}");
174 1         4 $logger->debug("Storage directory: $self->{vardir}");
175 1         3 $logger->debug("Lib directory: $self->{libdir}");
176              
177             # handle persistent state
178 1         3 $self->_loadState();
179              
180 1 50       3 $self->{deviceid} = _computeDeviceId() if !$self->{deviceid};
181              
182 1         3 $self->_saveState();
183              
184 1 50       117 if (!$self->getTargets()) {
185 0         0 $logger->error("No target defined, aborting");
186 0         0 exit 1;
187             }
188              
189             # compute list of allowed tasks
190 1         4 my %available = $self->getAvailableTasks(disabledTasks => $config->{'no-task'});
191 1         4 my @tasks = keys %available;
192 1         3 my @plannedTasks = $self->computeTaskExecutionPlan(\@tasks);
193 1         3 $self->{tasksExecutionPlan} = \@plannedTasks;
194              
195 1         3 my %available_lc = map { (lc $_) => $_ } keys %available;
  3         6  
196 1 50       4 if (!@tasks) {
197 0         0 $logger->error("No tasks available, aborting");
198 0         0 exit 1;
199             }
200              
201 1         4 $logger->debug("Available tasks:");
202 1         3 foreach my $task (keys %available) {
203 3         8 $logger->debug("- $task: $available{$task}");
204             }
205 1         3 $logger->debug("Planned tasks:");
206 1         1 foreach my $task (@{$self->{tasksExecutionPlan}}) {
  1         3  
207 0         0 my $task_lc = lc $task;
208 0         0 $logger->debug("- $task: " . $available{$available_lc{$task_lc}});
209             }
210              
211 1         1 $self->{tasks} = \@tasks;
212              
213 1         3 $self->resetLastConfigLoad();
214              
215 1         2 $self->{logger}->debug('agent reinit done.');
216             }
217              
218             sub resetLastConfigLoad {
219 2     2 0 2 my ($self) = @_;
220              
221 2         6 $self->{lastConfigLoad} = time;
222             }
223              
224             sub run {
225 0     0 1 0 my ($self) = @_;
226              
227 0         0 $self->{status} = 'waiting';
228              
229 0         0 my @targets = $self->getTargets();
230              
231 0 0 0     0 if ($self->{config}->{daemon} || $self->{config}->{service}) {
232              
233 0         0 $self->{logger}->debug2("Running in background mode");
234              
235             # background mode: work on a targets list copy, but loop while
236             # the list really exists so we can stop quickly when asked for
237 0         0 while ($self->getTargets()) {
238 0         0 my $time = time();
239              
240 0 0       0 @targets = $self->getTargets() unless @targets;
241 0         0 my $target = shift @targets;
242              
243 0         0 $self->_reloadConfIfNeeded();
244              
245 0 0       0 if ($time >= $target->getNextRunDate()) {
246              
247 0         0 eval {
248 0         0 $self->_runTarget($target);
249             };
250 0 0       0 $self->{logger}->error($EVAL_ERROR) if $EVAL_ERROR;
251 0         0 $target->resetNextRunDate();
252              
253             # Leave immediately if we passed in terminate method
254 0 0       0 last unless $self->getTargets();
255             }
256              
257 0 0       0 if ($self->{server}) {
258             # check for http interface messages, default timeout is 1 second
259 0 0       0 $self->{server}->handleRequests() or delay(1);
260             } else {
261 0         0 delay(1);
262             }
263             }
264             } else {
265              
266 0         0 $self->{logger}->debug2("Running in foreground mode");
267              
268             # foreground mode: check each targets once
269 0         0 my $time = time();
270 0   0     0 while ($self->getTargets() && @targets) {
271 0         0 my $target = shift @targets;
272 0 0 0     0 if ($self->{config}->{lazy} && $time < $target->getNextRunDate()) {
273             $self->{logger}->info(
274 0         0 "$target->{id} is not ready yet, next server contact " .
275             "planned for " . localtime($target->getNextRunDate())
276             );
277 0         0 next;
278             }
279              
280 0         0 eval {
281 0         0 $self->_runTarget($target);
282             };
283 0 0       0 $self->{logger}->error($EVAL_ERROR) if $EVAL_ERROR;
284             }
285             }
286             }
287              
288             sub terminate {
289 0     0 1 0 my ($self) = @_;
290              
291             # Forget our targets
292 0         0 $self->{targets} = [];
293              
294             # Kill current running task
295 0 0       0 if ($self->{current_runtask}) {
296 0         0 kill 'TERM', $self->{current_runtask};
297 0         0 delete $self->{current_runtask};
298             }
299              
300             $self->{logger}->info("FusionInventory Agent exiting")
301 0 0 0     0 if $self->{config}->{daemon} || $self->{config}->{service};
302 0 0       0 $self->{current_task}->abort() if $self->{current_task};
303              
304             # Handle killed callback
305 0 0       0 &{$self->{sigterm}}() if $self->{sigterm};
  0         0  
306             }
307              
308             sub _runTarget {
309 0     0   0 my ($self, $target) = @_;
310              
311 0 0       0 $self->{logger}->debug('_runTarget') if defined $self->{logger};
312             # the prolog dialog must be done once for all tasks,
313             # but only for server targets
314 0         0 my $response;
315 0 0       0 if ($target->isa('FusionInventory::Agent::Target::Server')) {
316             my $client = FusionInventory::Agent::HTTP::Client::OCS->new(
317             logger => $self->{logger},
318             timeout => $self->{timeout},
319             user => $self->{config}->{user},
320             password => $self->{config}->{password},
321             proxy => $self->{config}->{proxy},
322             ca_cert_file => $self->{config}->{'ca-cert-file'},
323             ca_cert_dir => $self->{config}->{'ca-cert-dir'},
324 0         0 no_ssl_check => $self->{config}->{'no-ssl-check'},
325             );
326              
327             my $prolog = FusionInventory::Agent::XML::Query::Prolog->new(
328             deviceid => $self->{deviceid},
329 0         0 );
330              
331 0         0 $self->{logger}->info("sending prolog request to server $target->{id}");
332 0         0 $response = $client->send(
333             url => $target->getUrl(),
334             message => $prolog
335             );
336 0 0       0 die "No answer from the server" unless $response;
337              
338             # update target
339 0         0 my $content = $response->getContent();
340 0 0       0 if (defined($content->{PROLOG_FREQ})) {
341 0         0 $target->setMaxDelay($content->{PROLOG_FREQ} * 3600);
342             }
343             }
344              
345 0         0 foreach my $name (@{$self->{tasksExecutionPlan}}) {
  0         0  
346 0         0 eval {
347 0         0 $self->_runTask($target, $name, $response);
348             };
349 0 0       0 $self->{logger}->error($EVAL_ERROR) if $EVAL_ERROR;
350 0         0 $self->{status} = 'waiting';
351              
352             # Leave earlier while requested
353 0 0       0 last unless $self->getTargets();
354             }
355             }
356              
357             sub _runTask {
358 0     0   0 my ($self, $target, $name, $response) = @_;
359              
360 0         0 $self->{status} = "running task $name";
361              
362 0 0 0     0 if ($self->{config}->{daemon} || $self->{config}->{service}) {
363             # server mode: run each task in a child process
364 0 0       0 if (my $pid = fork()) {
365             # parent
366 0         0 $self->{current_runtask} = $pid;
367 0         0 while (waitpid($pid, WNOHANG) == 0) {
368 0 0       0 if ($self->{server}) {
369 0 0       0 $self->{server}->handleRequests() or delay(1);
370             } else {
371 0         0 delay(1);
372             }
373              
374             # Leave earlier while requested
375 0 0       0 last unless $self->getTargets();
376             }
377 0         0 delete $self->{current_runtask};
378             } else {
379             # child
380 0 0       0 die "fork failed: $ERRNO" unless defined $pid;
381              
382 0         0 $self->{logger}->debug("forking process $PID to handle task $name");
383 0         0 $self->_runTaskReal($target, $name, $response);
384 0         0 exit(0);
385             }
386             } else {
387             # standalone mode: run each task directly
388 0         0 $self->_runTaskReal($target, $name, $response);
389             }
390             }
391              
392             sub _runTaskReal {
393 0     0   0 my ($self, $target, $name, $response) = @_;
394              
395 0         0 my $class = "FusionInventory::Agent::Task::$name";
396              
397 0         0 $class->require();
398              
399             my $task = $class->new(
400             config => $self->{config},
401             confdir => $self->{confdir},
402             datadir => $self->{datadir},
403             logger => $self->{logger},
404             target => $target,
405             deviceid => $self->{deviceid},
406 0         0 );
407              
408 0 0       0 return if !$task->isEnabled($response);
409              
410 0         0 $self->{logger}->info("running task $name");
411 0         0 $self->{current_task} = $task;
412              
413             $task->run(
414             user => $self->{config}->{user},
415             password => $self->{config}->{password},
416             proxy => $self->{config}->{proxy},
417             ca_cert_file => $self->{config}->{'ca-cert-file'},
418             ca_cert_dir => $self->{config}->{'ca-cert-dir'},
419 0         0 no_ssl_check => $self->{config}->{'no-ssl-check'},
420             );
421 0         0 delete $self->{current_task};
422             }
423              
424             sub getStatus {
425 6     6 1 10 my ($self) = @_;
426 6         84 return $self->{status};
427             }
428              
429             sub getTargets {
430 27     27 1 37 my ($self) = @_;
431              
432 27         34 return @{$self->{targets}};
  27         108  
433             }
434              
435             sub getAvailableTasks {
436 8     8 1 11516 my ($self, %params) = @_;
437              
438 8         10 my %tasks;
439 8         11 my %disabled = map { lc($_) => 1 } @{$params{disabledTasks}};
  3         7  
  8         22  
440              
441             # tasks may be located only in agent libdir
442 8         21 my $directory = $self->{libdir};
443 8         16 $directory =~ s,\\,/,g;
444 8         9 my $subdirectory = "FusionInventory/Agent/Task";
445             # look for all perl modules here
446 8         636 foreach my $file (File::Glob::glob("$directory/$subdirectory/*.pm")) {
447 30 50       186 next unless $file =~ m{($subdirectory/(\S+)\.pm)$};
448 30         73 my $module = file2module($1);
449 30         55 my $name = file2module($2);
450              
451 30 100       62 next if $disabled{lc($name)};
452              
453 29         21 my $version;
454 29 50 33     82 if ($self->{config}->{daemon} || $self->{config}->{service}) {
455             # server mode: check each task version in a child process
456 0         0 my ($reader, $writer);
457 0         0 pipe($reader, $writer);
458 0         0 $writer->autoflush(1);
459              
460 0 0       0 if (my $pid = fork()) {
461             # parent
462 0         0 close $writer;
463 0         0 $version = <$reader>;
464 0         0 close $reader;
465 0         0 waitpid($pid, 0);
466             } else {
467             # child
468 0 0       0 die "fork failed: $ERRNO" unless defined $pid;
469              
470 0         0 close $reader;
471 0         0 $version = $self->_getTaskVersion($module);
472 0 0       0 print $writer $version if $version;
473 0         0 close $writer;
474 0         0 exit(0);
475             }
476             } else {
477             # standalone mode: check each task version directly
478 29         47 $version = $self->_getTaskVersion($module);
479             }
480              
481             # no version means non-functionning task
482 29 100       48 next unless $version;
483              
484 18         26 $tasks{$name} = $version;
485 18 100       35 if (defined $self->{logger}) {
486 6         23 $self->{logger}->debug2( "getAvailableTasks() : add of task ".$name.' version '.$version );
487             }
488             }
489              
490 8         45 return %tasks;
491             }
492              
493             sub _getTaskVersion {
494 29     29   27 my ($self, $module) = @_;
495              
496 29         24 my $logger = $self->{logger};
497              
498 29 100       140 if (!$module->require()) {
499 6 100       58 $logger->debug2("module $module does not compile: $@") if $logger;
500 6         8 return;
501             }
502              
503 23 100       501 if (!$module->isa('FusionInventory::Agent::Task')) {
504 5 100       14 $logger->debug2("module $module is not a task") if $logger;
505 5         6 return;
506             }
507              
508 18         12 my $version;
509             {
510 30     30   57698 no strict 'refs'; ## no critic
  30         42  
  30         30272  
  18         13  
511 18         16 $version = ${$module . '::VERSION'};
  18         39  
512             }
513              
514 18         23 return $version;
515             }
516              
517             sub _isAlreadyRunning {
518 0     0   0 my ($self, $pidfile) = @_;
519              
520 0         0 Proc::PID::File->require();
521 0 0       0 if ($EVAL_ERROR) {
522             $self->{logger}->debug(
523 0         0 'Proc::PID::File unavailable, unable to check for running agent'
524             );
525 0         0 return 0;
526             }
527              
528 0         0 my $pid = Proc::PID::File->new();
529 0         0 $pid->{path} = $pidfile;
530 0         0 return $pid->alive();
531             }
532              
533             sub _loadState {
534 2     2   3 my ($self) = @_;
535              
536 2         8 my $data = $self->{storage}->restore(name => 'FusionInventory-Agent');
537              
538 2 100       6 $self->{deviceid} = $data->{deviceid} if $data->{deviceid};
539             }
540              
541             sub _saveState {
542 2     2   3 my ($self) = @_;
543              
544             $self->{storage}->save(
545             name => 'FusionInventory-Agent',
546             data => {
547             deviceid => $self->{deviceid},
548             }
549 2         12 );
550             }
551              
552             # compute an unique agent identifier, based on host name and current time
553             sub _computeDeviceId {
554 1     1   4 my $hostname = getHostname();
555              
556 1         28 my ($year, $month , $day, $hour, $min, $sec) =
557             (localtime (time))[5, 4, 3, 2, 1, 0];
558              
559 1         9 return sprintf "%s-%02d-%02d-%02d-%02d-%02d-%02d",
560             $hostname, $year + 1900, $month + 1, $day, $hour, $min, $sec;
561             }
562              
563             sub _appendElementsNotAlreadyInList {
564 2     2   3366 my ($list, $elements, $logger) = @_;
565              
566 2 50       9 if (! UNIVERSAL::isa($list, 'ARRAY')) {
567 0 0       0 $logger->error('_appendElementsNotAlreadyInList(): first argument is not an ARRAY ref') if defined $logger;
568 0         0 return $list;
569             }
570 2 50       10 if (UNIVERSAL::isa($elements, 'HASH')) {
    50          
571 0         0 @$elements = keys %$elements;
572             } elsif (! UNIVERSAL::isa($elements, 'ARRAY')) {
573 0 0       0 $logger->error('_appendElementsNotAlreadyInList(): second argument is neither an ARRAY ref nor a HASH ref') if defined $logger;
574 0         0 return $list;
575             }
576              
577 2         4 my %list = map { $_ => $_ } @$list;
  10         15  
578             # we want to add elements only once, so we ensure that there are no duplicates
579 2         4 my %elements = map { $_ => 1 } @$elements;
  11         15  
580 2         7 @$elements = keys %elements;
581              
582             # union of list AND elements which are NOT in list
583 2         10 my @newList = (@$list, grep( !defined($list{$_}), @$elements));
584              
585 2         10 return @newList;
586             }
587              
588             sub computeTaskExecutionPlan {
589 3     3 0 12 my ($self, $availableTasksNames) = @_;
590              
591 3 50 33     19 if (! defined($self->{config}) || !(UNIVERSAL::isa($self->{config}, 'FusionInventory::Agent::Config'))) {
592 0 0       0 $self->{logger}->error( "no config found in agent. Can't compute tasks execution plan" ) if (defined $self->{logger});
593 0         0 return;
594             }
595              
596 3         5 my @executionPlan = ();
597 3 100       12 if ($self->{config}->isParamArrayAndFilled('tasks')) {
598 2 50       9 $self->{logger}->debug2('isParamArrayAndFilled(\'tasks\') : true') if (defined $self->{logger});
599 2         6 @executionPlan = _makeExecutionPlan($self->{config}->{'tasks'}, $availableTasksNames, $self->{logger});
600             } else {
601 1 50       5 $self->{logger}->debug2('isParamArrayAndFilled(\'tasks\') : false') if (defined $self->{logger});
602 1         2 @executionPlan = @$availableTasksNames;
603             }
604              
605 3         7 return @executionPlan;
606             }
607              
608             sub _makeExecutionPlan {
609 6     6   5694 my ($sortedTasks, $availableTasksNames, $logger) = @_;
610              
611 6         178 my $sortedTasksCloned = dclone $sortedTasks;
612 6         8 my @executionPlan = ();
613 6         11 my %available = map { (lc $_) => $_ } @$availableTasksNames;
  21         45  
614              
615 6         11 my $task = shift @$sortedTasksCloned;
616 6         15 while (defined $task) {
617 46 100       58 if ($task eq $CONTINUE_WORD) {
618 1         2 last;
619             }
620 45         37 $task = lc $task;
621 45 100       52 if ( defined($available{$task})) {
622 25         20 push @executionPlan, $available{$task};
623             }
624 45         58 $task = shift @$sortedTasksCloned;
625             }
626 6 100 66     19 if ( defined($task) && $task eq $CONTINUE_WORD) {
627             # we append all other available tasks
628 1         3 @executionPlan = _appendElementsNotAlreadyInList(\@executionPlan, $availableTasksNames, $logger);
629             }
630              
631 6         22 return @executionPlan;
632             }
633              
634             sub getTasksExecutionPlan {
635 0     0 0 0 my ($self) = @_;
636              
637 0         0 return $self->{tasksExecutionPlan};
638             }
639              
640             sub _createTargets {
641 1     1   2 my ($self) = @_;
642              
643 1         3 my $config = $self->{config};
644             # create target list
645 1 50       3 if ($config->{local}) {
646 1         1 foreach my $path (@{$config->{local}}) {
  1         3  
647 1         13 push @{$self->{targets}},
648             FusionInventory::Agent::Target::Local->new(
649             logger => $self->{logger},
650             deviceid => $self->{deviceid},
651             delaytime => $config->{delaytime},
652             basevardir => $self->{vardir},
653             path => $path,
654             html => $config->{html},
655 1         1 );
656             }
657             }
658              
659 1 50       4 if ($config->{server}) {
660 1         1 foreach my $url (@{$config->{server}}) {
  1         4  
661 0         0 push @{$self->{targets}},
662             FusionInventory::Agent::Target::Server->new(
663             logger => $self->{logger},
664             deviceid => $self->{deviceid},
665             delaytime => $config->{delaytime},
666             basevardir => $self->{vardir},
667             url => $url,
668             tag => $config->{tag},
669 0         0 );
670             }
671             }
672             }
673              
674             sub _createDaemon {
675 0     0   0 my ($self) = @_;
676              
677 0         0 my $config = $self->{config};
678 0         0 my $logger = $self->{logger};
679             my $pidfile = $config->{pidfile} ||
680 0   0     0 $self->{vardir} . '/fusioninventory.pid';
681 0 0       0 if ($self->_isAlreadyRunning($pidfile)) {
682 0         0 $logger->error("An agent is already running, exiting...");
683 0         0 exit 1;
684             }
685 0 0       0 if (!$config->{'no-fork'}) {
686              
687 0         0 Proc::Daemon->require();
688 0 0       0 if ($EVAL_ERROR) {
689 0         0 $logger->error("Failed to load Proc::Daemon: $EVAL_ERROR");
690 0         0 exit 1;
691             }
692              
693             # If we use relative path, we must stay in the current directory
694 0 0       0 my $workdir = substr($self->{libdir}, 0, 1) eq '/' ? '/' : getcwd();
695              
696 0         0 Proc::Daemon::Init({
697             work_dir => $workdir,
698             pid_file => $pidfile
699             });
700              
701 0         0 $self->{logger}->debug("Agent daemonized");
702             }
703             }
704              
705             sub _createHttpInterface {
706 0     0   0 my ($self) = @_;
707              
708 0         0 my $logger = $self->{logger};
709 0         0 my $config = $self->{config};
710 0         0 FusionInventory::Agent::HTTP::Server->require();
711 0 0       0 if ($EVAL_ERROR) {
712 0         0 $logger->error("Failed to load HTTP server: $EVAL_ERROR");
713             } else {
714             $self->{server} = FusionInventory::Agent::HTTP::Server->new(
715             logger => $logger,
716             agent => $self,
717             htmldir => $self->{datadir} . '/html',
718             ip => $config->{'httpd-ip'},
719             port => $config->{'httpd-port'},
720 0         0 trust => $config->{'httpd-trust'}
721             );
722 0         0 $self->{server}->init();
723             }
724             }
725              
726             sub _installSignalHandlers {
727 1     1   2 my ($self) = @_;
728              
729 1     0   21 $SIG{INT} = sub { $self->terminate(); exit 0; };
  0         0  
  0         0  
730 1     0   7 $SIG{TERM} = sub { $self->terminate(); exit 0; };
  0            
  0            
731             }
732              
733             sub _reloadConfIfNeeded {
734 0     0     my ($self) = @_;
735              
736 0 0         if ($self->_isReloadConfNeeded()) {
737 0           $self->{logger}->debug2('_reloadConfIfNeeded() is true, init agent now...');
738 0           $self->reinit();
739             }
740             }
741              
742             sub _isReloadConfNeeded() {
743 0     0     my ($self) = @_;
744              
745 0           my $time = time;
746             #$self->{logger}->debug2('_isReloadConfNeeded : ' . $self->{lastConfigLoad} . ' - ' . $time . ' > ' . $self->{config}->{'conf-reload-interval'} . ' ?');
747 0   0       return ($self->{config}->{'conf-reload-interval'} > 0) && (($time - $self->{lastConfigLoad}) > $self->{config}->{'conf-reload-interval'});
748             }
749              
750             1;
751             __END__