From 6961b4c7fd1b67b5a9f0e7679f37063433a327a7 Mon Sep 17 00:00:00 2001 From: Guillaume Bougard Date: Tue, 12 Dec 2023 18:37:43 +0100 Subject: [PATCH] fix: Fix current folder local target support --- Changes | 4 +++ lib/GLPI/Agent/Daemon.pm | 4 +-- lib/GLPI/Agent/Daemon/Win32.pm | 13 ++++++++ lib/GLPI/Agent/HTTP/Server.pm | 2 +- .../Agent/HTTP/Server/ToolBox/Inventory.pm | 30 ++++++++++++++++--- lib/GLPI/Agent/Target/Local.pm | 20 +++++++++++++ lib/GLPI/Agent/Task/Inventory.pm | 2 +- lib/GLPI/Agent/Task/NetDiscovery.pm | 19 ++++++------ lib/GLPI/Agent/Task/NetInventory.pm | 4 +-- share/html/toolbox/inventory-language-en.txt | 1 + share/html/toolbox/inventory-language-fr.txt | 1 + share/html/toolbox/inventory-list.tpl | 5 +++- 12 files changed, 85 insertions(+), 20 deletions(-) diff --git a/Changes b/Changes index 9a641a972..e3a0bae91 100644 --- a/Changes +++ b/Changes @@ -8,6 +8,8 @@ core: * Move runPowerShell() API remote case support in RemoteInventory API * Update httpd default page to show targets id and server url or local path only for trusted clients +* Update local target API to support getFullPath() & setFullPath() calls +* Handle '.' local target when run as a service to save inventories in vardir inventory: * PR #531: Add SentinelOne Antivirus support on Linux, thanks to @MarcSamD @@ -36,6 +38,7 @@ netdiscovery/netinventory: * Update timeout to backend-collect-timeout configuration when scanning ESX or RemoteInventory after a successful scan requested by ToolBox * Fix possible concurrency error leading to an unrecoverable blocked task +* Use new local target API to set expected saving folder esx: * Fix first connection timeout support @@ -44,6 +47,7 @@ esx: toolbox: * fix #533: Fix Toolbox export buttons in inventory results * Fix wrong remote inventory results when using a short timeout for quickier detection +* Handle agent folder as vardir folder when agent is running as a service injector: * fix #537: Make -x, --xml-ua & --json-ua options equivalent and update help text diff --git a/lib/GLPI/Agent/Daemon.pm b/lib/GLPI/Agent/Daemon.pm index 2a61d47a6..ddf69a87b 100644 --- a/lib/GLPI/Agent/Daemon.pm +++ b/lib/GLPI/Agent/Daemon.pm @@ -107,8 +107,8 @@ sub run { foreach my $target (@targets) { my $date = $target->getFormatedNextRunDate(); my $id = $target->id(); - my $name = $target->getName(); - $logger->info("target $id: next run: $date - $name"); + my $info = $target->isType('local') ? $target->getFullPath() : $target->getName(); + $logger->info("target $id: next run: $date - $info"); } } diff --git a/lib/GLPI/Agent/Daemon/Win32.pm b/lib/GLPI/Agent/Daemon/Win32.pm index d70f478fd..5059c053d 100644 --- a/lib/GLPI/Agent/Daemon/Win32.pm +++ b/lib/GLPI/Agent/Daemon/Win32.pm @@ -39,6 +39,19 @@ sub new { return $self; } +sub init { + my ($self, %params) = @_; + + $self->SUPER::init(%params); + + # When running as a service the script makes a chdir to perl/bin and this isn't + # convenient for local target set to "." so we need to fix it to vardir folder + foreach my $target (@{$self->{targets}}) { + next unless $target->isType('local') && $target->getPath() eq '.'; + $target->setFullPath($self->{config}->{vardir}); + } +} + sub name { my ($self, $name) = @_; diff --git a/lib/GLPI/Agent/HTTP/Server.pm b/lib/GLPI/Agent/HTTP/Server.pm index 8e529263a..a33b24f5c 100644 --- a/lib/GLPI/Agent/HTTP/Server.pm +++ b/lib/GLPI/Agent/HTTP/Server.pm @@ -331,7 +331,7 @@ sub _handle_root { $self->{agent}->getTargets(); my @local_targets = - map { { id => $_->id(), target => $trust ? $_->getPath() : '', date => $_->getFormatedNextRunDate() } } + map { { id => $_->id(), target => $trust ? $_->getFullPath() : '', date => $_->getFormatedNextRunDate() } } grep { $_->isType('local') } $self->{agent}->getTargets(); diff --git a/lib/GLPI/Agent/HTTP/Server/ToolBox/Inventory.pm b/lib/GLPI/Agent/HTTP/Server/ToolBox/Inventory.pm index 6a723e3a1..5a9be6474 100644 --- a/lib/GLPI/Agent/HTTP/Server/ToolBox/Inventory.pm +++ b/lib/GLPI/Agent/HTTP/Server/ToolBox/Inventory.pm @@ -62,6 +62,18 @@ sub init { return unless $self->read_yaml(); + # Update networktask_save folder is running as a service and folder set to '.' + my $yaml_config = $self->yaml('configuration') || {}; + if (empty($yaml_config->{'networktask_save'}) || $yaml_config->{'networktask_save'} eq '.') { + my $agent = $self->{toolbox}->{server}->{agent}; + if (($OSNAME eq 'MSWin32' && ref($agent) eq 'GLPI::Agent::Daemon::Win32') || getppid() == 1) { + # We are running as a service and we must fix networktask_save to vardir + $yaml_config->{'networktask_save'} = $agent->{vardir}; + $self->need_save("configuration"); + $self->write_yaml(); + } + } + $self->_load_jobs(); } @@ -224,11 +236,14 @@ sub update_template_hash { next if $target->isType('listener'); my $id = $target->id() or next; - $hash->{targets}->{$id} = [ $target->getType(), $target->getName() ]; + $hash->{targets}->{$id} = [ $target->getType(), $target->isType('local') ? $target->getFullPath() : $target->getName() ]; } # Default target when creating a new task $hash->{default_target} = $hash->{targets}->{server0} ? 'server0' : ''; + # Default folder: '.' means "Agent Folder" + $hash->{default_local} = $yaml_config->{networktask_save} // '.'; + # Set running task $hash->{outputid} = $self->{taskid} || ''; $hash->{tasks} = $self->{tasks} || {}; @@ -842,7 +857,7 @@ sub netscan { # If not using an agent target, create a local target and update it to run now unless ($target) { - my $path = $yaml_config->{networktask_save} // '.'; + my $path = $yaml_config->{networktask_save} || '.'; # Make sure path exists as folder mkdir $path unless -d $path; @@ -854,6 +869,10 @@ sub netscan { basevardir => $agent->{vardir}, path => $path ); + + # When running as a service we need to use vardir as default local folder + $target->setFullPath($agent->{vardir}) + if $path eq '.' && (($OSNAME eq 'MSWin32' && ref($agent) eq 'GLPI::Agent::Daemon::Win32') || getppid() == 1); } # Create an NetDiscovery task @@ -965,8 +984,7 @@ sub _run_local { # If not using an agent target, create a local target and update it to run now unless ($target) { - my $path = !$yaml_config->{networktask_save} || $yaml_config->{networktask_save} eq '.' ? - "inventory" : $yaml_config->{networktask_save}."/inventory"; + my $path = $yaml_config->{networktask_save} || '.'; # Make sure path exists as folder mkdir $path unless -d $path; @@ -978,6 +996,10 @@ sub _run_local { basevardir => $agent->{vardir}, path => $path ); + + # When running as a service we need to use vardir as default local folder + $target->setFullPath($agent->{vardir}) + if $path eq '.' && (($OSNAME eq 'MSWin32' && ref($agent) eq 'GLPI::Agent::Daemon::Win32') || getppid() == 1); } # Create an Inventory task diff --git a/lib/GLPI/Agent/Target/Local.pm b/lib/GLPI/Agent/Target/Local.pm index deecbc001..d3182560c 100644 --- a/lib/GLPI/Agent/Target/Local.pm +++ b/lib/GLPI/Agent/Target/Local.pm @@ -5,6 +5,9 @@ use warnings; use parent 'GLPI::Agent::Target'; +use File::Spec; +use Cwd qw(abs_path); + my $count = 0; sub new { @@ -15,6 +18,8 @@ sub new { my $self = $class->SUPER::new(%params); $self->{path} = $params{path}; + $self->{fullpath} = abs_path(File::Spec->rel2abs($params{path})) + unless $self->{path} eq '-'; $self->{format} = $params{json} ? 'json' : $params{html} ? 'html' : 'xml'; @@ -36,6 +41,14 @@ sub getPath { return $self->{path}; } +sub getFullPath { + my ($self, $subfolder) = @_; + + my $fullpath = $self->{fullpath} || $self->{path}; + + return $subfolder ? "$fullpath/$subfolder" : $fullpath; +} + sub setPath { my ($self, $path) = @_; @@ -43,6 +56,13 @@ sub setPath { if $path && -d $path; } +sub setFullPath { + my ($self, $path) = @_; + + $self->{fullpath} = $path + if $path && -d $path; +} + sub getName { my ($self) = @_; diff --git a/lib/GLPI/Agent/Task/Inventory.pm b/lib/GLPI/Agent/Task/Inventory.pm index 873db684d..8368e7359 100644 --- a/lib/GLPI/Agent/Task/Inventory.pm +++ b/lib/GLPI/Agent/Task/Inventory.pm @@ -262,7 +262,7 @@ sub submit { if ($self->{target}->isType('local')) { - my $file = $inventory->save($self->{target}->getPath()); + my $file = $inventory->save($self->{target}->getFullPath()); $self->{logger}->info("Inventory ".($file eq '-' ? "dumped on standard output" : "saved in $file")) if $file; diff --git a/lib/GLPI/Agent/Task/NetDiscovery.pm b/lib/GLPI/Agent/Task/NetDiscovery.pm index d19526d8c..970f794e3 100644 --- a/lib/GLPI/Agent/Task/NetDiscovery.pm +++ b/lib/GLPI/Agent/Task/NetDiscovery.pm @@ -459,10 +459,12 @@ sub run { $timeout = $self->{config}->{"backend-collect-timeout"}; $found->timeout($timeout); - my $path; - $path = $self->{target}->getPath() if $self->{target}->isType('local'); - # When target path is agent folder, inventory should be saved in inventory subfolder - $path .= '/inventory' if $path eq '.'; + my ($path, $agentfolder); + if ($self->{target}->isType('local')) { + $agentfolder = $self->{target}->getPath() eq '.' ? 'inventory' : ''; + # When target path is agent folder, inventory should be saved in inventory subfolder + $path = $self->{target}->getFullPath($agentfolder); + } # As we still have run the connection part in _scanAddressByRemote(), we reuse the connected object if ($credentials->{TYPE} eq 'esx') { $found->serverInventory($path, $collectdeviceid, $deviceid); @@ -470,9 +472,8 @@ sub run { # Setup a remote inventory as it is done in GLPI::Agent::Task::RemoteInventory GLPI::Agent::Task::Inventory->require(); - # Update local target path if the case it has been set to agent folder - $self->{target}->setPath($path) - if $self->{target}->isType('local'); + # Update local target path in the case it has been updated + $self->{target}->setFullPath($path) if $agentfolder; my $task = GLPI::Agent::Task::Inventory->new( logger => $self->{logger}, @@ -622,8 +623,8 @@ sub _sendMessage { } else { # We don't have to save control messages return unless $content->{DEVICE}; - $path .= "/netdiscovery"; - mkpath($path); + $path = $self->{target}->getFullPath("netdiscovery"); + mkpath($path) unless -d $path; $ip = $content->{DEVICE}->[0]->{IP}; $file = $path . "/$ip.xml"; } diff --git a/lib/GLPI/Agent/Task/NetInventory.pm b/lib/GLPI/Agent/Task/NetInventory.pm index 5025cd16b..0a93135f4 100644 --- a/lib/GLPI/Agent/Task/NetInventory.pm +++ b/lib/GLPI/Agent/Task/NetInventory.pm @@ -350,8 +350,8 @@ sub _sendMessage { if ($path eq '-') { $handle = \*STDOUT; } else { - $path .= "/netinventory"; - mkpath($path); + $path = $self->{target}->getFullPath("netinventory"); + mkpath($path) unless -d $path; $file = $path . "/$ip.xml"; } diff --git a/share/html/toolbox/inventory-language-en.txt b/share/html/toolbox/inventory-language-en.txt index 063af84a3..7b904952e 100644 --- a/share/html/toolbox/inventory-language-en.txt +++ b/share/html/toolbox/inventory-language-en.txt @@ -20,6 +20,7 @@ netdiscovery task not installed: netinventory task not installed: netdiscovery and netinventory tasks not installed: Agent folder: +Configured folder: Target: Created inventories: diff --git a/share/html/toolbox/inventory-language-fr.txt b/share/html/toolbox/inventory-language-fr.txt index f60a48971..05ebd5006 100644 --- a/share/html/toolbox/inventory-language-fr.txt +++ b/share/html/toolbox/inventory-language-fr.txt @@ -20,6 +20,7 @@ netdiscovery task not installed: Tâche netdiscovery non installée netinventory task not installed: Tâche netinventory non installée netdiscovery and netinventory tasks not installed: Tâches netdiscovery et netinventory non installées Agent folder: Dossier de l'agent +Configured folder: Dossier configuré Target: Cible Created inventories: Inventaires créés diff --git a/share/html/toolbox/inventory-list.tpl b/share/html/toolbox/inventory-list.tpl index 3d4988449..3fdce731b 100644 --- a/share/html/toolbox/inventory-list.tpl +++ b/share/html/toolbox/inventory-list.tpl @@ -81,9 +81,12 @@ if (@jobs_order) { my @target_tooltip; if ($target && $targets{$target}) { @target_tooltip = ( $targets{$target}->[0], encode('UTF-8', encode_entities($targets{$target}->[1]))); - } else { + } elsif (!$default_local || $default_local eq '.') { $target = _("Agent folder"); @target_tooltip = ( local => $target ); + } else { + $target = _("Configured folder"); + @target_tooltip = ( local => "$default_local" ); } push @configuration, _("Target").": 
$target